Grimwold's Area of Effect Spell System
Have been working on this on and off for a few days since Akroma222 and, originally, cromcrom mentioned area effect spells... this is my somewhat generic system for creating such area effect spells.
First you will need a
script_entity which I have called
grimwold_spell_script. Here you paste in the following:
Code: Select all
function stormSpell(ordinal,effect,particle,sound,damage,area)
local dx,dy = getForward(party.facing) -- forward
local ldx,ldy = getForward((party.facing+3)%4) -- left
local rdx,rdy = getForward((party.facing+1)%4) -- right
local originator = 2 ^ (ordinal+1)
local effect_translation_table = {fire = 1 , cold = 1, shock = 1, poison = 1 }
local coords = {}
if area == "square" then
coords = {xcoord = {-1,-1,-1,0,0,1,1,1},ycoord = {-1,0,1,-1,1,-1,0,1}}
elseif area == "bigsquare" then
coords = {xcoord = {-2,-2,-2,-2,-2,-1,-1,-1,-1,-1,0,0,0,0,1,1,1,1,1,2,2,2,2,2},ycoord = {-2,-1,0,1,2,-2,-1,0,1,2,-2,-1,1,2,-2,-1,0,1,2,-2,-1,0,1,2}}
elseif area == "cone" then
coords = {xcoord = {dx,2*dx,2*dx+ldx,2*dx+rdx,3*dx,3*dx+2*ldx,3*dx+ldx,3*dx+rdx,3*dx+2*rdx},ycoord = {dy,2*dy,2*dy+ldy,2*dy+rdy,3*dy,3*dy+2*ldy,3*dy+ldy,3*dy+rdy,3*dy+2*rdy}}
elseif area == "smallcone" then
coords = {xcoord = {dx+ldx,dx,dx+rdx},ycoord = {dy+ldy,dy,dy+rdy}}
elseif area == "line" then
coords = {xcoord = {dx,2*dx,3*dx},ycoord = {dy,2*dy,3*dy}}
else
coords = {xcoord = {dx},ycoord = {dy}}
end
local coord_pairs = math.min(#coords["xcoord"],#coords["ycoord"])
for i = 1,coord_pairs do
if particle == "poison_cloud" or particle == "ice_shards" or particle == "one_ice_shard" then
spawn(particle,party.level, party.x + coords["xcoord"][i], party.y + coords["ycoord"][i], party.facing)
else
spawn("fx", party.level, party.x + coords["xcoord"][i], party.y + coords["ycoord"][i], party.facing)
:setParticleSystem(particle)
:translate(0, effect_translation_table[effect], 0)
playSoundAt(sound, party.level, party.x + coords["xcoord"][i], party.y + coords["ycoord"][i])
end
damageTile(party.level, party.x + coords["xcoord"][i], party.y + coords["ycoord"][i], party.facing, originator , effect, damage)
end
end
Then in your
spells.lua file you need to paste in the following, which also includes 4 sample spells for you to keep/tweak/overwrite:
Code: Select all
-- STORM SPELL PACK --
-- SAMPLE SPELL DEFINITIONS --
defineSpell{
name = "fire_storm",
uiName = "Fire Storm",
skill = "fire_magic",
level = 16,
runes = "AFH",
manaCost = 35,
onCast = function(caster,x,y,direction,skill)
return grimwold_spell_script.stormSpell(caster:getOrdinal(),"fire","firestorm","fireburst",skill*3,"square")
end,
}
defineSpell{
name = "ice_cone",
uiName = "Ice Cone",
skill = "ice_magic",
level = 19,
runes = "FHI",
manaCost = 35,
onCast = function(caster,x,y,direction,skill)
return grimwold_spell_script.stormSpell(caster:getOrdinal(),"cold","one_ice_shard","ice_shard",skill*3,"cone")
end,
}
defineSpell{
name = "lightning_storm",
uiName = "Lightning Storm",
skill = "air_magic",
level = 19,
runes = "CFH",
manaCost = 35,
onCast = function(caster,x,y,direction,skill)
return grimwold_spell_script.stormSpell(caster:getOrdinal(),"shock","shockburst","shockburst",skill*3,"bigsquare")
end,
}
defineSpell{
name = "poison_burst",
uiName = "Poision Burst",
skill = "earth_magic",
level = 13,
runes = "FGH",
manaCost = 35,
onCast = function(caster,x,y,direction,skill)
return grimwold_spell_script.stormSpell(caster:getOrdinal(),"poison","poison_cloud","poison_cloud",skill*3,"square")
end,
}
-- STORM SPELL PACK --
-- SAMPLE SPELL SCROLL ITEM DEFINITIONS --
defineObject{
name = "scroll_fire_storm",
class = "Item",
uiName = "Scroll of Fire Storm",
model = "assets/models/items/scroll_spell.fbx",
gfxIndex = 113,
scroll = true,
spell = "fire_storm",
weight = 0.3,
}
defineObject{
name = "scroll_ice_cone",
class = "Item",
uiName = "Scroll of Ice Storm",
model = "assets/models/items/scroll_spell.fbx",
gfxIndex = 113,
scroll = true,
spell = "ice_cone",
weight = 0.3,
}
defineObject{
name = "scroll_lightning_storm",
class = "Item",
uiName = "Scroll of Lightning Storm",
model = "assets/models/items/scroll_spell.fbx",
gfxIndex = 113,
scroll = true,
spell = "lightning_storm",
weight = 0.3,
}
defineObject{
name = "scroll_poison_burst",
class = "Item",
uiName = "Scroll of Poison Storm",
model = "assets/models/items/scroll_spell.fbx",
gfxIndex = 113,
scroll = true,
spell = "poison_burst",
weight = 0.3,
}
-- STORM SPELL PACK --
-- OBJECT DEFINITIONS --
defineObject{
name = "one_ice_shard",
class = "IceShards",
attackPower = 20,
chainCounter = 1,
--cameraShake = true,
tags = { "spell" },
}
-- STORM SPELL PACK --
-- PARTICLE DEFINITIONS --
defineParticleSystem{
name = "firestorm",
emitters = {
-- flames
{
spawnBurst = true,
maxParticles = 30,
sprayAngle = {0,360},
velocity = {3,5},
objectSpace = true,
texture = "assets/textures/particles/torch_flame.tga",
frameRate = 35,
frameSize = 64,
frameCount = 16,
lifetime = {0.4,0.6},
color0 = {1, 0.5, 0.25},
opacity = 1,
fadeIn = 0.1,
fadeOut = 0.3,
size = {0.5, 1.5},
gravity = {0,-15,0},
airResistance = 0.5,
rotationSpeed = 0,
blendMode = "Additive",
},
-- glow
{
spawnBurst = true,
emissionRate = 1,
emissionTime = 0,
maxParticles = 1,
boxMin = {0,0,-0.1},
boxMax = {0,0,-0.1},
sprayAngle = {0,30},
velocity = {0,0},
texture = "assets/textures/particles/glow.tga",
lifetime = {0.5, 0.5},
colorAnimation = false,
color0 = {1.500000, 0.495000, 0.090000},
opacity = 1,
fadeIn = 0.01,
fadeOut = 0.5,
size = {4, 4},
gravity = {0,0,0},
airResistance = 1,
rotationSpeed = 2,
blendMode = "Additive",
}
}
}
To define a new Area of Effect Spell you need to use the following patten, which I will explain.
Code: Select all
defineSpell{
name = "fire_storm",
uiName = "Fire Storm",
skill = "fire_magic",
level = 16,
runes = "AFH",
manaCost = 35,
onCast = function(caster,x,y,direction,skill)
return grimwold_spell_script.stormSpell(caster:getOrdinal(),"fire","firestorm","fireburst",skill*3,"square")
end,
}
The early entries should all be familiar to anyone who has defined a spell: name, uiName, skill, level, runes, manaCost. Following that is the meat of the spell definition, the function which takes a number of variables as follows:
#1 -
caster:getOrdinal() - this transfers the ordinal of the spellcaster to the function and is necessary for granting XP. This entry should remain unchanged.
#2 -
"fire" - this is the type of damage to deal. you can use "fire","cold","shock" or "poison"
#3 -
"firestorm" - this is the particle system to use in each square of the spell's effect. you can use any defined particle system, but there are 3 special cases "poison_cloud", "ice_shards" and my new "one_ice_shard" where the name is used to spawn an object instead of an FX with a particle system.
#4 -
"fireburst" - this is the sound to play in each square of the spell's effect. Can use any defined sound... preferably one that doesn't loop!
#5 -
skill*3 - this is the damage done in each square of the spell's effect. You can use any numerical value.
#6 -
"square" - this is the target pattern to use for the spell. supported patterns are "square", "bigsquare", "cone", "smallcone" and "line". If you don't use one of these, then only the square infront of the party will be affected.
The sample spells I have included are:
Firestorm - fire damage to the 8 spaces around the party in a "square". Using my new "firestorm" particle system.
Ice Cone - cold damage to a triangle of 9 squares in front of the party.. in the shape 1,3,5. this uses my new "one_ice_shard" object which creates a single space ice_shard instead of a chain of 4
Lightning Storm - shock damage to 24 spaces around the party like the "square" but 2 spaces wide
Poison Burst - poison damage to a row of 3 squares in front of the party (e.g. one side of the "square")