Page 1 of 2
[HELP] Timers and waiting in scripts
Posted: Tue Nov 13, 2012 6:07 pm
by flatline
If I want to add an amount of protection with a spell and after 30 seconds return protection to its original value, how can I accomplish that in a script?
Say I want a "mana shield" spell where I get the casters current mana, and adds that amount of armor to all champions for 30 seconds. What is the way to achieve a 30 second wait inside that spell?
Re: [HELP] Timers and waiting in scripts
Posted: Tue Nov 13, 2012 6:16 pm
by cromcrom
You can spawn timers. I advise you to check grimwold's very nice spells that do this.
viewtopic.php?f=14&t=3475
Re: [HELP] Timers and waiting in scripts
Posted: Tue Nov 13, 2012 8:52 pm
by Komag
You could spawn a timer for it, and that's a good way to do it because if you place a timer in the editor beforehand and the party is on a different level when they cast the spell, the timer won't count at the right speed due to engine optimizations.
Here is an example:
Code: Select all
function manaShield()
--cast mana shield code
spawn("timer",party.level,0,0,0,"manaShieldTimer")
:addConnector("activate", "manaScript", "resetProtection")
:setTimerInterval(30)
:activate()
end
function resetProtection()
--reset the armor settings code
manaShieldTimer:destroy()
end
Re: [HELP] Timers and waiting in scripts
Posted: Wed Nov 14, 2012 12:34 am
by flatline
Thanks a bunch!
One thing struck me:
Say Champion 1 have 20 protection, spell is cast, adding 20 protection. During the spell effect, the hero equips or unequips armor, altering his protection value. Does this affect the base protection value when the spell is destroyed. IE, is the original protection value calculated as normal when the Mana shield turns off? I guess I'll try and see.
Re: [HELP] Timers and waiting in scripts
Posted: Wed Nov 14, 2012 1:19 am
by Grimwold
Komag wrote:You could spawn a timer for it, and that's a good way to do it because if you place a timer in the editor beforehand and the party is on a different level when they cast the spell, the timer won't count at the right speed due to engine optimizations.
Here is an example:
Code: Select all
function manaShield()
--cast mana shield code
spawn("timer",party.level,0,0,0,"manaShieldTimer")
:addConnector("activate", "manaScript", "resetProtection")
:setTimerInterval(30)
:activate()
end
function resetProtection()
--reset the armor settings code
manaShieldTimer:destroy()
end
This is very good, but I would suggest adding a little 'protection' into the script to avoid problems if the spell is cast again before the previous spell has finished. When the spell is cast, I would search for the timer and if it exists destroy it.. then go on to spawn a new timer.
Code: Select all
local mana_timer_entity = findEntity("manaShieldTimer")
if mana_timer_entity ~= nil then
mana_timer_entity:destroy()
end
Re: [HELP] Timers and waiting in scripts
Posted: Wed Nov 14, 2012 2:37 am
by JohnWordsworth
Just a quick question about using the timer method. If you create a timer manually (in script) is it immune to running at a different speed when you go down stairs? Or, if I cast a spell which spawns a timer to give me a buff and then jump down a pit - will it last twice as long?
I don't suppose we have access to any of the lua os.time() methods. In fact, a gameTicks() or gameTime() method that counts the in game seconds since the start of the game (not including pause mode etc) would be really, really useful. It wouldn't matter if the time fire every second, or every frame - you could always accurately measure the time an effect has been active and disable it round about after the right time.
Re: [HELP] Timers and waiting in scripts
Posted: Wed Nov 14, 2012 3:10 am
by flatline
Ok, I can't get this to work due to stupidity, tiredness and being away from modding for a few weeks.
I want to avoid having to place timers and lua scripts into the dungeon, if possible.
defineSpell{
name = "ManaShield",
uiName = "Holy Shield",
skill = "spellcraft",
level = 1,
runes = "GHI",
manaCost = 1,
onCast = function(Champ)
function spellcheck()
local mana_timer_entity = findEntity("manaShieldTimer")
if mana_timer_entity ~= nil then
mana_timer_entity:destroy()
end
--cast mana shield code
function manashield(Champ)
local base_energy = Champ.getStat("energy")
spawn("timer",party.level,0,0,0,"manaShieldTimer")
:addConnector("activate", "manaScript", "resetProtection")
:setTimerInterval(30)
:activate()
end
function manaScript()
for slot=1,4 do
if party:getChampion(slot) ~= nil then
party:getChampion(slot):modifyStat("protection", base_energy)
Champ:setStat("energy", 0)
end
function resetProtection()
--reset the armor settings code
manaShieldTimer:destroy()
end
end
}
Re: [HELP] Timers and waiting in scripts
Posted: Wed Nov 14, 2012 3:12 am
by Grimwold
Although I haven't tested it, I'm pretty sure that timers spawned in script behave the same as timers placed using the editor... and hence would suffer from the time-dilation effects of being on a different level to the party.
If needed, you could probably implement a script to transfer active party_timer_'s to the party's current level.. maybe as part of the onMove hook using a variable that stores the level the party was on last time it moved.
Also, I don't think we have access to the lua os library..
Re: [HELP] Timers and waiting in scripts
Posted: Wed Nov 14, 2012 3:37 am
by Komag
timers spawned via script are exactly the same, and suffer the same dilation. You can instead start a ticker that ticks a script counter every second and that way you can detect each second whether the timer and the party are still on the same level, and if not destroy the timer and spawn a new on on the party level to continue the tick
Re: [HELP] Timers and waiting in scripts
Posted: Wed Nov 14, 2012 3:38 am
by Grimwold
flatline wrote:I want to avoid having to place timers and lua scripts into the dungeon, if possible.
I'm pretty sure that for a complex spell like this, that uses multiple functions, you will be unable to manage without using a script entity in the dungeon. The spell definition can only handle a fire-once piece of code. That's why all my more complex spells (Push Monster; Hold Monster; Burn Monster) required a script entity in the dungeon for any ongoing effects.
You wouldn't need to manually place any timers in the dungeon, and would only need a single script entity, say called mana_shield_script.
Your spell definition would look something like this in
spells.lua:
Code: Select all
defineSpell{
name = "ManaShield",
uiName = "Holy Shield",
skill = "spellcraft",
level = 1,
runes = "GHI",
manaCost = 1,
onCast = function(champ)
return mana_shield_script.manashield(champ)
end,
}
and your
script entity called
mana_shield_script in the dungeon would be something like this:
Code: Select all
-- set initial base_energy value (this variable used for 'resetting' the protection)
base_energy = 0
-- modify protection value
function modifyProtection(modifier)
hudPrint("modifying by " .. modifier)
for slot=1,4 do
if party:getChampion(slot) ~= nil then
party:getChampion(slot):modifyStatCapacity("protection", modifier)
party:getChampion(slot):modifyStat("protection", modifier)
-- hudPrint("max protection " .. tostring(party:getChampion(slot):getStatMax("protection")))
end
end
end
-- check for and destroy mana timer
function checkManaTimer()
local mana_timer_entity = findEntity("manaShieldTimer")
if mana_timer_entity ~= nil then
mana_timer_entity:destroy()
end
end
-- cast mana shield code
function manashield(Champ)
checkManaTimer()
base_energy = Champ:getStat("energy")
-- hudPrint("base energy = " .. tostring(base_energy))
spawn("timer",party.level,0,0,0,"manaShieldTimer")
:addConnector("activate", "mana_shield_script", "resetProtection")
:setTimerInterval(30)
:activate()
Champ:setStat("energy", 0)
modifyProtection(base_energy)
end
function resetProtection()
modifyProtection(-base_energy)
checkManaTimer()
end
I haven't tested this code, and it's pretty late as I'm typing so I may have made the odd mistake, but the principle should be sound... if I get chance I'll plug it into a test dungeon and see what happens.
EDIT - When I tested the code I originally wrote, I ran into a problem regarding Max Stat value.. but once I found out that's why protection was not increasing I was able to modify the script and it now works as expected. the above code has been corrected, so should work.