[Tutorial] Make a magic missile (or other projectile) spell

Talk about creating Grimrock 1 levels and mods here. Warning: forum contains spoilers!
Post Reply
User avatar
JKos
Posts: 464
Joined: Wed Sep 12, 2012 10:03 pm
Location: Finland
Contact:

[Tutorial] Make a magic missile (or other projectile) spell

Post by JKos »

Due to limitations of current custom spell support I had to invent a workaround for making projectile spells.
See this thread: viewtopic.php?f=14&t=3846

So I made a small tutorial about it as I promised :)
I will post this to grimwiki too.

how to make a properly working magic missile (or other projectile spell)

First we have to make a spell projectile model, for that a blue gem retextured with white_light material works nicely, this tutorial will not cover retexturing process, but you can download already retextured spell_projectile.model from here:
https://docs.google.com/open?id=0B7cR7s ... ENwRG5zamM

Save the spell_projectile.model file to your mods mod_assest/models/ directory

Next phase is to define an object which uses that model
mod_assets/scripts/objects.lua

Code: Select all

--general spell projectile object
defineObject{
	name = "spell_projectile",
	class = "Item",
	uiName = "Spell projectile",
	model = "mod_assets/models/spell_projectile.fbx",
	gfxIndex = 109,
	attackPower = 1,
	impactSound = "fireball_hit",
	stackable = false,
	sharpProjectile = false,
	projectileRotationY = 0,
	weight = 0,	
}
Now lets clone it as a magic missile

Code: Select all

cloneObject{
		name = "magic_missile",
		baseObject = "spell_projectile",
		uiName = "Magic missile",
		particleEffect = "magic_missile",
}
Define white glowing particle effect for magic missile

Code: Select all

defineParticleSystem{
	name = "magic_missile",
	emitters = {
		-- glow
		{
			spawnBurst = true,
			emissionRate = 1,
			emissionTime = 0,
			maxParticles = 1,
			boxMin = {-0.0, -0.0, 0.0},
			boxMax = { 0.0, 0.0,  -0.0},
			sprayAngle = {0,30},
			velocity = {0,0},
			texture = "assets/textures/particles/glow.tga",
			lifetime = {1000000, 1000000},
			colorAnimation = false,
			color0 = {1, 1, 1},
			opacity = 1,
			fadeIn = 0.1,
			fadeOut = 0.1,
			size = {0.8, 0.8},
			gravity = {0,0,0},
			airResistance = 1,
			rotationSpeed = 2,
			blendMode = "Additive",
			objectSpace = true,
		}
	}
}	
Ok, now we have an item that can be used as a projectile and looks like a white glowing ball of light.
But now it's time to do the real magic, so lets do some scripting.

Define the magic_missle spell

Code: Select all

defineSpell{
		name = "magic_missile",
		uiName = "Magic missile",
		skill = "fire_magic",
		level = 1,
		runes = "A",
		manaCost = 15,
		description = "The mage creates a bolt of magic force that unerringly strikes one target.",
		onCast = function(caster,x,y,direction,skill)
			mymod_spells.castMagicMissile(caster,x,y,direction,skill)
		end
	}
onCast-hook calls a function castMagicMissile from script entity named as mymod_spells(you can change that).
Of course the mymod_spells script entity does not exist yet so we have to create it in editor.

mymod_spells script entity

Code: Select all

function castMagicMissile(caster,x,y,direction,skill)
	shootProjectile('magic_missile', party.level, x, y, direction, 14, 0, 0, 0, 0, 0,10, party, true)
end
Now we can cast the magic missile (rune A). That was pretty easy right? BUT the caster or party will never get XP for kills made by magic missile spell.
So if we wan't to implement that, things do get bit trickier. For that we have to setup a onParticleHit hook for EVERY monster, but on this tutorial I will set it up for snail only.
mod_assets/scripts/monsters.lua

Code: Select all

cloneObject{
		name = "snail",
		baseObject = "snail",
		onProjectileHit = function(monster,projectile)
			return mymod_spells.magicMissileOnProjectileHitHook(monster,projectile)
		end
}
You can use a for loop to define that hook to all monsters. You just need a list of monsters.

Now we have to extend the mymod_spells script entity and add that function called from onProjectileHit-hook.

Code: Select all

-- we have to store the caster ordinal here 
-- so that we can calculate the right originator for damageTile on magicMissileOnProjectileHitHook
spellCasters = 0

function castMagicMissile(caster,x,y,direction,skill)
	shootProjectile('magic_missile', party.level, x, y, direction, 14, 0, 0, 0, 0, 0,100, party, true)
	spellCaster = caster:getOrdinal()
end
-- we have to use damageTile to deal the spell damage to monsters because that is the only way to give xp for the spell caster for kills 
function magicMissileOnProjectileHitHook(monster,projectile)
	if projectile.name == 'magic_missile' then
		local originator = 2 ^ (spellCaster+1) -- calculate the originator of the spell
		local damage = math.random(2,10) --
		damageTile(monster.level,monster.x,monster.y,(monster.facing + 2)%4,originator+1, 'physical',damage)
		playSoundAt("fireball_hit",monster.level,monster.x,monster.y)
		return false
	end
end
See this post about the damageTile flags argument: viewtopic.php?f=14&t=3861#p40130
- LoG Framework 2http://sites.google.com/site/jkoslog2 Define hooks in runtime by entity.name or entity.id + multiple hooks support.
- cloneObject viewtopic.php?f=22&t=8450
User avatar
Grimwold
Posts: 511
Joined: Thu Sep 13, 2012 11:45 pm
Location: A Dungeon somewhere in the UK

Re: [Tutorial] Make a magic missile (or other projectile) sp

Post by Grimwold »

Great tutorial, thanks!
User avatar
JohnWordsworth
Posts: 1397
Joined: Fri Sep 14, 2012 4:19 pm
Location: Devon, United Kingdom
Contact:

Re: [Tutorial] Make a magic missile (or other projectile) sp

Post by JohnWordsworth »

Awesome tutorial - let me know if you would like any help putting it on the Wiki (I noticed in your other thread that you said you might!).

It's a shame that projectiles don't have an 'onHit' hook instead of having to use the monster's hook.
My Grimrock Projects Page with links to the Grimrock Model Toolkit, GrimFBX, Atlas Toolkit, QuickBar, NoteBook and the Oriental Weapons Pack.
User avatar
JKos
Posts: 464
Joined: Wed Sep 12, 2012 10:03 pm
Location: Finland
Contact:

Re: [Tutorial] Make a magic missile (or other projectile) sp

Post by JKos »

Added to Grimwiki http://grimwiki.net/wiki/Make_a_magic_missile_spell

projectile:onHit() - hook would be great. I think I can implement it in LoG Framework, thanks for the idea.
- LoG Framework 2http://sites.google.com/site/jkoslog2 Define hooks in runtime by entity.name or entity.id + multiple hooks support.
- cloneObject viewtopic.php?f=22&t=8450
User avatar
akroma222
Posts: 1029
Joined: Thu Oct 04, 2012 10:08 am

Re: [Tutorial] Make a magic missile (or other projectile) sp

Post by akroma222 »

Very useful indeed! Thanks :D
User avatar
cromcrom
Posts: 549
Joined: Tue Sep 11, 2012 7:16 am
Location: Chateauroux in a socialist s#!$*&% formerly known as "France"

Re: [Tutorial] Make a magic missile (or other projectile) sp

Post by cromcrom »

I love it, thanks a lot, Adding this to TLC, crediting you of course.
A trip of a thousand leagues starts with a step.
Post Reply