Custome Spells made but no xp given to party

Ask for help about creating mods and scripts for Grimrock 2 or share your tips, scripts, tools and assets with other modders here. Warning: forum contains spoilers!
User avatar
LordGarth
Posts: 500
Joined: Mon Jun 18, 2012 5:07 pm
Location: Colorado USA

Custome Spells made but no xp given to party

Post by LordGarth »

Here is some code for an Immolation spell and chain lightning.
Invisibility spell has been removed to make room for the gesture for the chain lightning spell.

firering texture will have to be make for the immolation spell and immosound made and put into the sound folder of your dungeon
wav file 16 bit.

both spells work but no exp awarded to party which i am working on.
I have been trying to put an onDie hook in monster code to give exp on death but it does not work.




defineObject{
name = "immolate",
baseObject = "base_spell",
components = {
{
class = "Particle",
particleSystem = "immo",
offset = vec(0, 1.5, 0),
},
{
class = "Light",
offset = vec(1.5, 1.0, 0),
color = vec(0.5, 0.5, 0.25),
brightness = 7,
range = 5,
fadeOut = 13,
disableSelf = true,
},
{
class = "CloudSpell",
attackPower = 35,
damageInterval = 0.5,
damageType = "fire",
duration = 8,
sound = "immosound",

},
},
}

defineSpell{
name = "immolate",
uiName = "Immolate",
gesture = 1458,
manaCost = 45,
requirements = { "fire_magic", 3 },
skill = "fire_magic",
icon = 60,
spellIcon = 1,
description = "Conjures a blast of fire that deals fire damage over time.",
onCast = function(champ)

if party.facing == 0 then
spawn("immolate", party.level, party.x, party.y-1, party.facing)
end
if party.facing == 1 then
spawn("immolate", party.level, party.x+1, party.y, party.facing)
end
if party.facing == 2 then
spawn("immolate", party.level, party.x, party.y+1, party.facing)
end
if party.facing == 3 then
spawn("immolate", party.level, party.x-1, party.y, party.facing)
end
end




}













defineParticleSystem{
name = "immo",
emitters = {
-- blast
{
spawnBurst = true,
maxParticles = 10,
boxMin = {-0.5, -0.4,-0.5},
boxMax = { 0.5, 0.2, 0.5},
sprayAngle = {0,360},
velocity = {0.1,0.7},
objectSpace = true,
texture = "mod_assets/textures/firering.tga",
lifetime = {0.4,0.8},
color0 = {0.5, 0.5, 0.5},
opacity = 1,
fadeIn = 0.1,
fadeOut = 1,
size = {1.0, 1.0},
gravity = {0,0,0},
airResistance = 0.1,
rotationSpeed = 0.5,
blendMode = "Additive",
},

-- fog
{
emissionRate = 5,
emissionTime = 0,
maxParticles = 100,
boxMin = {-1.2*0.3, -1.0*0.3,-1.2*0.3},
boxMax = { 1.2*0.3, 0.5*0.3, 1.2*0.3},
sprayAngle = {0,360},
velocity = {0.1,0.7*0.3},
objectSpace = true,
texture = "assets/textures/particles/smoke_01.tga",
lifetime = {2,2},
color0 = {0.29, 0.29, 0.145},
opacity = 0.8,
fadeIn = 1,
fadeOut = 1,
size = {1.4*0.5, 1.75*0.5},
gravity = {0,0,0},
airResistance = 0.1,
rotationSpeed = 0.1,
blendMode = "Translucent",
},

-- fog
{
emissionRate = 5,
emissionTime = 0,
maxParticles = 100,
boxMin = {-1.2*0.3, -0.5*0.3,-1.2*0.3},
boxMax = { 1.2*0.3, 0.5*0.3, 1.2*0.3},
sprayAngle = {0,360},
velocity = {0.1,0.3},
objectSpace = true,
texture = "mod_assets/textures/firering.tga",
lifetime = {2,2},
color0 = {1,1,1},
opacity = 0.8,
fadeIn = 1,
fadeOut = 1,
size = {1.4*0.75, 1.75*0.75},
gravity = {0,0,0},
airResistance = 0.1,
rotationSpeed = 0.1,
blendMode = "Additive",
},

-- pollen
{
emissionRate = 30,
emissionTime = 0,
maxParticles = 100,
boxMin = {-1*0.5,-1.3*0.5,-1*0.5},
boxMax = { 1*0.5, 0.8*0.5, 1*0.5},
sprayAngle = {0,30},
velocity = {0.5,1.0},
objectSpace = true,
texture = "assets/textures/particles/smoke_01.tga",
lifetime = {1,1},
color0 = {1.5,1.5,0.5},
opacity = 0.15,
fadeIn = 0.1,
fadeOut = 0.3,
size = {0.03, 0.05},
gravity = {0,-1.2,0},
airResistance = 0.1,
rotationSpeed = 2,
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 = {0.1, 0.12, 0.1},
opacity = 1,
fadeIn = 0.01,
fadeOut = 0.5,
size = {2, 2},
gravity = {0,0,0},
airResistance = 1,
rotationSpeed = 2,
blendMode = "Additive",
}
}
}


defineSound{
name = "immosound",
filename = "mod_assets/sounds/immosound.wav",
loop = false,
volume = 1,
minDistance = 2,
maxDistance = 10,
}


defineSpell{
name = "invisibility",
uiName = "Invisibility",
gesture = 0,
manaCost = 45,
onCast = "invisibility",
skill = "air_magic",
requirements = { "air_magic", 3, "concentration", 2 },
icon = 74,
spellIcon = 15,
description = "Turns yourself and your friends invisible.",
}





defineObject{
name = "chainlightning",
baseObject = "base_spell",
components = {
{
class = "Particle",
particleSystem = "chainlightning",
offset = vec(0, 1.5, 0),
},
{
class = "Light",
offset = vec(1.5, 1.0, 0),
color = vec(0.5, 0.5, 0.25),
brightness = 7,
range = 5,
fadeOut = 13,
disableSelf = true,
},
{
class = "CloudSpell",
attackPower = 35,
damageInterval = 0.5,
damageType = "shock",
duration = 8,
sound = "shockburst",

},
},
}

defineSpell{
name = "chainlightning",
uiName = "Chain Lightning",
gesture = 3658,
manaCost = 45,
requirements = { "air_magic", 3 },
skill = "air_magic",
icon = 64,
spellIcon = 6,
description = "Conjures a bolts of lightning that deals fire damage over time.",
onCast = function(champ)

if party.facing == 0 then
spawn("chainlightning", party.level, party.x, party.y-1, party.facing)
end
if party.facing == 1 then
spawn("chainlightning", party.level, party.x+1, party.y, party.facing)
end
if party.facing == 2 then
spawn("chainlightning", party.level, party.x, party.y+1, party.facing)
end
if party.facing == 3 then
spawn("chainlightning", party.level, party.x-1, party.y, party.facing)
end
end




}













defineParticleSystem{
name = "chainlightning",
emitters = {
-- blast
{
spawnBurst = true,
maxParticles = 10,
boxMin = {-0.5, -0.4,-0.5},
boxMax = { 0.5, 0.2, 0.5},
sprayAngle = {0,360},
velocity = {0.1,0.7},
objectSpace = true,
texture = "assets/textures/particles/lightning01.tga",
lifetime = {0.4,0.8},
color0 = {0.5, 0.5, 0.5},
opacity = 1,
fadeIn = 0.1,
fadeOut = 1,
size = {1.0, 1.0},
gravity = {0,0,0},
airResistance = 0.1,
rotationSpeed = 0.5,
blendMode = "Additive",
},

-- fog
{
emissionRate = 5,
emissionTime = 0,
maxParticles = 100,
boxMin = {-1.2*0.3, -1.0*0.3,-1.2*0.3},
boxMax = { 1.2*0.3, 0.5*0.3, 1.2*0.3},
sprayAngle = {0,360},
velocity = {0.1,0.7*0.3},
objectSpace = true,
texture = "assets/textures/particles/smoke_01.tga",
lifetime = {2,2},
color0 = {0.29, 0.29, 0.145},
opacity = 0.8,
fadeIn = 1,
fadeOut = 1,
size = {1.4*0.5, 1.75*0.5},
gravity = {0,0,0},
airResistance = 0.1,
rotationSpeed = 0.1,
blendMode = "Translucent",
},

-- fog
{
emissionRate = 5,
emissionTime = 0,
maxParticles = 100,
boxMin = {-1.2*0.3, -0.5*0.3,-1.2*0.3},
boxMax = { 1.2*0.3, 0.5*0.3, 1.2*0.3},
sprayAngle = {0,360},
velocity = {0.1,0.3},
objectSpace = true,
texture = "assets/textures/particles/lightning01.tga",
lifetime = {2,2},
color0 = {1,1,1},
opacity = 0.8,
fadeIn = 1,
fadeOut = 1,
size = {1.4*0.75, 1.75*0.75},
gravity = {0,0,0},
airResistance = 0.1,
rotationSpeed = 0.1,
blendMode = "Additive",
},

-- pollen
{
emissionRate = 30,
emissionTime = 0,
maxParticles = 100,
boxMin = {-1*0.5,-1.3*0.5,-1*0.5},
boxMax = { 1*0.5, 0.8*0.5, 1*0.5},
sprayAngle = {0,30},
velocity = {0.5,1.0},
objectSpace = true,
texture = "assets/textures/particles/smoke_01.tga",
lifetime = {1,1},
color0 = {1.5,1.5,0.5},
opacity = 0.15,
fadeIn = 0.1,
fadeOut = 0.3,
size = {0.03, 0.05},
gravity = {0,-1.2,0},
airResistance = 0.1,
rotationSpeed = 2,
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 = {0.1, 0.12, 0.1},
opacity = 1,
fadeIn = 0.01,
fadeOut = 0.5,
size = {2, 2},
gravity = {0,0,0},
airResistance = 1,
rotationSpeed = 2,
blendMode = "Additive",
}
}
}
Dungeon Master and DOOM will live forever.
User avatar
akroma222
Posts: 1029
Joined: Thu Oct 04, 2012 10:08 am

Re: Custome Spells made but no xp given to party

Post by akroma222 »

Hey LordGarth

Take some time to read through either -
AndakRainor's spellpack
viewtopic.php?f=22&t=9579
or minmays spells
viewtopic.php?f=22&t=9065
or Zimber's ....
viewtopic.php?f=22&t=14538

most of your questions should be answered :)
Akroma
User avatar
Isaac
Posts: 3192
Joined: Fri Mar 02, 2012 10:02 pm

Re: Custome Spells made but no xp given to party

Post by Isaac »

LordGarth wrote:I have been trying to put an onDie hook in monster code to give exp on death but it does not work.
For "immolate", here is an alternate onCast(), that replaces the multiple IF conditions, centers spell on party if cast at a wall, and tags the spell for champion XP.

*Doesn't check for secret doors ~yet... (but will when I get back later tonight)

Code: Select all

onCast = function(champion, x, y, direction, elevation, skillLevel)
	local dX,dY = getForward(party.facing) 		--Directional offsets
	if party.map:isWall(party.x+dX, party.y+dY, party.elevation) then
		dX,dY = 0,0								--Targets Party's cell if cast on a wall
	end  
	--spell cast and tagged for the champion who cast it.
	spawn("immolate", party.level, party.x+dX, party.y+dY, party.facing, party.elevation).cloudspell:setCastByChampion(champion:getOrdinal())	
end
User avatar
LordGarth
Posts: 500
Joined: Mon Jun 18, 2012 5:07 pm
Location: Colorado USA

Re: Custome Spells made but no xp given to party

Post by LordGarth »

Thankyou

Will try

onCast = function(champion, x, y, direction, elevation, skillLevel)
local dX,dY = getForward(party.facing) --Directional offsets
if party.map:isWall(party.x+dX, party.y+dY, party.elevation) then
dX,dY = 0,0 --Targets Party's cell if cast on a wall
end
--spell cast and tagged for the champion who cast it.
spawn("immolate", party.level, party.x+dX, party.y+dY, party.facing, party.elevation).cloudspell:setCastByChampion(champion:getOrdinal())
end
Dungeon Master and DOOM will live forever.
User avatar
LordGarth
Posts: 500
Joined: Mon Jun 18, 2012 5:07 pm
Location: Colorado USA

Re: Custome Spells made but no xp given to party

Post by LordGarth »

This code works great thanks alot

onCast = function(champion, x, y, direction, elevation, skillLevel)
local dX,dY = getForward(party.facing) --Directional offsets
if party.map:isWall(party.x+dX, party.y+dY, party.elevation) then
dX,dY = 0,0 --Targets Party's cell if cast on a wall
end
--spell cast and tagged for the champion who cast it.
spawn("immolate", party.level, party.x+dX, party.y+dY, party.facing, party.elevation).cloudspell:setCastByChampion(champion:getOrdinal())
end

It does not work for launch spells that travel.
I get a cloudspell error. I tried replacing cloudspell with projectile and tried tiledamager and still wont work.
I tried putting an onHitMonster hook in the first and second object that the spell calls up and still no exp.

I will try to make code that will spawn the cloudspell in front of the party of course and 1 and 2 squares away so the spell will act like a flamethrower but will still be cloudspell and exp will be awarded.

LordGarth
Dungeon Master and DOOM will live forever.
User avatar
Isaac
Posts: 3192
Joined: Fri Mar 02, 2012 10:02 pm

Re: Custome Spells made but no xp given to party

Post by Isaac »

LordGarth wrote:This code works great thanks alot
Image
It does not work for launch spells that travel.
It was intended to apply only to cloudspells cast by [directly in front of] the party. It can certainly be modified; or incorporated into a larger onCast(). As-is, it doesn't even use the skillLevel parameter.

Have a look inside poison_bolt.lua, in the asset pack.

excerpt [from "poison_bolt_greater_blast"]:

Code: Select all

onHitMonster = function(self, monster)
				monster:setCondition("poisoned", 25)

				-- mark condition so that exp is awarded if monster is killed by the condition
				local poisonedCondition = monster.go.poisoned
				local ord = self:getCastByChampion()
				if poisonedCondition and ord then
					poisonedCondition:setCausedByChampion(ord)
				end
			end,
Last edited by Isaac on Fri Nov 25, 2016 11:35 pm, edited 1 time in total.
User avatar
LordGarth
Posts: 500
Joined: Mon Jun 18, 2012 5:07 pm
Location: Colorado USA

Re: Custome Spells made but no xp given to party

Post by LordGarth »

do you know how to make it work for launch spells.

Thanks,

LordGarth
Dungeon Master and DOOM will live forever.
User avatar
akroma222
Posts: 1029
Joined: Thu Oct 04, 2012 10:08 am

Re: Custome Spells made but no xp given to party

Post by akroma222 »

There are numerous versions of this floating around, but this is what Im using atm for projectileSpells:
(currently lets you cast through grating - sparse doors - will update....)
Call it this way:
SpoilerShow

Code: Select all

onCast(champion, x, y, direction, elevation, skillLevel)
        projectileScripts.script.projectileSpell(champion, x, y, direction, elevation, skillLevel, projectile, power, volleyCount, delay, sound, cost) 
end
projectile = "projectile_name"
power = number
volleyCount = number
delay = number
sound = "sound_name"
cost = number (extra cost for each additional projectile in volley)
SpoilerShow

Code: Select all

function getSpace()
	local dX,dY = getForward(party.facing)       
    if party.map:isWall(party.x+dX, party.y+dY, party.elevation) then
    	dX,dY = 0,0                       
    end
   	return dX,dY   
end

--print(scripty2.script.getSpace())


projectileSpellCaster = ""
projectileVolleyCount = 0

function projectileSpell(champion, x, y, direction, elevation, skillLevel, projectile, power, volleyCount, delay, sound, cost) 
	
	local c = 1
        local cordX, cordY = getSpace()
	projectileVolleyCount = 0
	-----------------------------1 sound
	if sound ~= nil then
		playSound(sound)
	end
	-----------------------------
	if cordX == 0 and cordY == 0 then
		------------------------------------------------------------
		local a = spawn(projectile, party.level, x, y, direction, elevation)
		a.projectile:setAttackPower(power)
		return false
		--------------------------------------------------------------stop volley if hitting party
	else 
		local a = spawn(projectile,party.level, x, y, direction, elevation)
       	a.projectile:setIgnoreEntity(party)
		--------------------------------------------------------------power														
		if power ~= "" then
       		a.projectile:setAttackPower(power)
		end
		-----------------------------------------------------------ordinal
		if champion then
			c = champion:getOrdinal()
		end
		a.projectile:setCastByChampion(c)
		-----------------------------------------------------------data (uncomment all this if you are attaching script components to your projectile spells)
		--if a.data then
			--print(a.data:isEnabled())
			--a.data:set("skill1", skillLevel)
			--a.data:set("champOrd", c)
			--a.data:set("power", power)
		--else
			--print("warning - no userdata comp. FIX THIS")
		--end
               ------------------------------------------------------------------------
		--print(a.data:get("skill"), a.data:get("ord"))
		-----------------------------------------------------------positioning
		local left = nil
        for i = 1,4 do
        	if party.party:getChampion(i):getOrdinal() == ord then
            	left = i == 1 or i == 3
                break
            end
        end
        local wpos = party:getWorldPosition()
        local dx = nil
        local dz = nil
       	if party.facing == 0 then
        	dx = left and -0.2 or 0.2
            dz = -2
        elseif party.facing == 1 then
            dz = left and 0.2 or -0.2
            dx = -2
       	 elseif party.facing == 2 then
            dx = left and 0.2 or -0.2
            dz = 2
        else 	-- party.facing == 3
            dz = left and -0.2 or 0.2
            dx = 2
        end
		a:setWorldPosition(vec(wpos[1]+dx,wpos[2]+1.35,wpos[3]+dz))
		-----------------------------------------------------------------if volley
		if volleyCount > 1 and delay ~= nil then
			------------------------------------------------------------------------------------------------------------------------ repeatCount()
			delayedCall("projectileScripts", delay, "volleyProjectileSpell", champion, projectile, power, volleyCount, delay, sound)
			projectileVolleyCount = projectileVolleyCount + 1
			print(volleyCount, delay, projectileVolleyCount, power)
		end
	end
	projectileSpellCaster = c
end
--------------------------------------------------------------------------------------volleyProjectileSpell(champion, projectile, power, volleyCount, delay, sound)

	function volleyProjectileSpell(champion, projectile, power, volleyCount, delay, sound)
	-----------------------------------------
		local x = party.x
		local y = party.y
		local direction = party.facing
		local elevation = party.elevation
		local dx,dy = getForward(party.facing)
                local cordX, cordY = getSpace()
		-----------------------------------------
		if projectileVolleyCount == volleyCount then
			projectileVolleyCount = 0
			return false
		else
			-----------------------------------------
			if sound ~= nil then
				playSound(sound)
			end
			-----------------------------------------extra cost()
			if cost then
				champion:regainEnergy(-cost)		
			end
			-----------------------------------------
			if cordX == 0 and cordY == 0 then  				
				------------------------------------------------------------
				local a = spawn(projectile, party.level, x, y, direction, elevation)
				a.projectile:setAttackPower(power)
				return false
				--------------------------------------------------------------stop volley if hitting party
			else
				local a = spawn(projectile,party.level, x, y, direction, elevation)
				a.projectile:setIgnoreEntity(party)
				--------------------------------------------------------------power														
				if power ~= "" then
					a.projectile:setAttackPower(power)
				end
				-----------------------------------------------------------ordinal
				if champion then
					c = champion:getOrdinal()
				end
				a.projectile:setCastByChampion(c)
				-----------------------------------------------------------data (same again)
				--if a.data then
					--print(a.data:isEnabled())
					--a.data:set("skill1", skillLevel)
					--a.data:set("champOrd", c)
					--a.data:set("power", power)
				--else
					--print("warning - no userdata comp. FIX THIS")
				--end
				--print(a.data:get("skill1"), a.data:get("champOrd"), a.data:get("power"))
				-----------------------------------------------------------positioning
				local left = nil
				for i = 1,4 do
					if party.party:getChampion(i):getOrdinal() == ord then
						left = i == 1 or i == 3
						break
					end
				end
				local wpos = party:getWorldPosition()
				local dx = nil
				local dz = nil
				if party.facing == 0 then
					dx = left and -0.2 or 0.2
					dz = -2
				elseif party.facing == 1 then
					dz = left and 0.2 or -0.2
					dx = -2
				elseif party.facing == 2 then
					dx = left and 0.2 or -0.2
					dz = 2
				else 	-- party.facing == 3
					dz = left and -0.2 or 0.2
					dx = 2
				end
				a:setWorldPosition(vec(wpos[1]+dx,wpos[2]+1.35,wpos[3]+dz))
				a:setSubtileOffset(math.random() - 0.5, math.random()- 0.5)
				projectileVolleyCount = projectileVolleyCount + 1
				print(volleyCount, delay, projectileVolleyCount, power)
				delayedCall("projectileScripts", delay, "volleyProjectileSpell", champion, projectile, power, volleyCount, delay, sound)
			end
		end
		projectileSpellCaster = champion:getOrdinal()
	end
	
Last edited by akroma222 on Sat Nov 26, 2016 2:23 pm, edited 1 time in total.
User avatar
akroma222
Posts: 1029
Joined: Thu Oct 04, 2012 10:08 am

Re: Custome Spells made but no xp given to party

Post by akroma222 »

Isaac wrote:

Code: Select all

onCast = function(champion, x, y, direction, elevation, skillLevel)
	local dX,dY = getForward(party.facing) 		--Directional offsets
	if party.map:isWall(party.x+dX, party.y+dY, party.elevation) then
		dX,dY = 0,0								--Targets Party's cell if cast on a wall
	end  
	--spell cast and tagged for the champion who cast it.
	spawn("immolate", party.level, party.x+dX, party.y+dY, party.facing, party.elevation).cloudspell:setCastByChampion(champion:getOrdinal())	
end
Isaac, this code was for cloud spells (allowing you cast through grating) ... do you have your version for projectiles (cant cast through grating) handy?
I can post mine, but Im pretty sure yours will be less messy! :lol: :roll:
(Ive just quickly added your^^ check to my script here to keep it simple)

we should really set up a definitive thread for these Spell basics
(we have all have posted this stuff so many times lol)
User avatar
Isaac
Posts: 3192
Joined: Fri Mar 02, 2012 10:02 pm

Re: Custome Spells made but no xp given to party

Post by Isaac »

akroma222 wrote:Isaac, this code was for cloud spells (allowing you cast through grating) ... do you have your version for projectiles (cant cast through grating) handy?
I do not have a version of that. [yet]
The cloudspell wall check was purpose built for this thread, after I read LordGarth's post.

*The poison_bolt spell won't cast past a door in the default game. :?
(Nothing can shoot the party through a door either; but the slimes can burn the adjacent party through a grate.)
Post Reply