garanixx Posted January 12, 2010 Share Posted January 12, 2010 I have no idea if this is the right place to post this. If it's not, I would kindly ask a moderator to move it to the proper place or to advise me on where to post it so it gets more attention. Basically, I've found and fixed the chain lightning bug. The one that seemingly randomly made the lightning stop jumping around, making the spell vanish. However, it is by far not just limited to chain lightning. I've discovered a whole irritating little "gotcha" which might cause a lot of people headaches related to spell/ability modding and even adding. So I wanted to share my findings and hopefully spare somebody the pain. The way chain lightning works, is that it continues to define the next creature it jumps to as its caster, from which further bolts branch out. It defines this under event object index 0. It also saves its current target under index 1 and the original caster of the spell under 2, as shown in the excerpt below: object oPrj = FireHomingProjectile(10,GetPosition(stEvent.oTarget),secondaryTargets[i], 0, stEvent.oCaster); event ev = Event(90210); ev = SetEventInteger(ev, 0, stEvent.nAbility); ev = SetEventObject(ev, 0, stEvent.oTarget); // oCaster ev = SetEventObject(ev, 1, secondaryTargets[i]); ev = SetEventObject(ev, 2, stEvent.oCaster); SetProjectileImpactEvent(oPrj, ev); The bug where the spell dissapears occurs when the creature that was considered the current caster(under index 0) dies before the next set of targets are hit and damaged by the bolts. If the creature that you cast the original spell on happens to die before the branching bolts hit their targets, they will do no damage and will simply vanish, effectively turning your chain lightning into a weak lightning bolt and nothing more. Below, I will explain exactly why this happens. Effect applications, effect removals and impact events are passed directly to the rules_core script to be handled. Within the rules_core script, events with the ID 90210 are further passed down to the ability_core script as a means of simulating a new spell being cast(hence how the chain lightning bounces and how stinging swarm changes targets). And it's in the ability_core script that this problem occurs. Now the ability_core script will normally call the corresponding ability/spell script based on the ability's ID(the exact same happens whenever you use an ability or cast a spell), in order to handle the passed down event. However, take note of the code below: // ------------------------------------------------------------------------ // Getting the event parameters: // // nEventType can be any of the following: // * EVENT_TYPE_COMMAND_PENDING (signaled by either creature_core, follower_core or player core) // * EVENT_TYPE_ABILITY_CAST_IMPACT (signaled by the engine) // * EVENT_TYPE_ABILITY_CAST_START (signaled by the engine) // // oCaster is the creature using the ability // oTarget is the object that the ability was targeted // oItem is the item used to cast the ability (optional) // nAbility is the ability that was triggered // ------------------------------------------------------------------------ event ev = GetCurrentEvent(); int nEventType = GetEventType(ev); object oCaster = GetEventObject(ev, 0); object oItem; object oTarget; if (nEventType == EVENT_TYPE_ABILITY_CAST_IMPACT || nEventType == EVENT_TYPE_ABILITY_CAST_START) { oItem = GetEventObject(ev, 1); oTarget = GetEventObject(ev, 2); // note: in case of a projectile impact, there might be more than one target (object 2+...) // this allows doing things like lightning bolts going through targets, but we're not making // use of this in scripting right now. } else { oTarget = GetEventObject(ev, 1); oItem = GetEventObject(ev, 2); } Here you are able to see exactly that the event objects 0, 1 and 2 are specifically assigned by this script. But most notably. If you check right below the first set of comments, you will see that oCaster is always event object with the index 0. Now take a further look at the conditional below, which can be found a bit further down in this same script: if(IsDead(oCaster)) // If the caster is dead for some reasons, ignore { Log_Trace(LOG_CHANNEL_EVENTS,sDebug,"Caster is dead - ignoring event"); return; } This means that if the caster is dead, the script will abort the event handling. Do you see the problem now? Chain lightning keeps setting the current target where it's jumping from as the caster of the spell. So if that creature dies, that particular branch of the spells will dissapear. If the first creature you cast it at dies, the spell will dissapear altogether! All I did in the end to fix it was simply swap the indexes to make 0 the original caster and 2 the "current caster". So, you should ALWAYS save the original caster of the spell under index 0, unless you desire your spell to behave in a different way. Hopefully this will spare someone a lot of frustration. Link to comment Share on other sites More sharing options...
Bridgepiece Posted January 15, 2010 Share Posted January 15, 2010 :ohmy: Nice find! This is tricky. The bolt stopping if death occurs can be viewed as both correct or bugged :P Sure, one can say that the bolt should continue regardless of death but then again if there is death then the player 'shouldnt' be allowed to use the corpse as a means to attack other creatures. For example, if the script is changed so the bolt continues and/or 'affects' dead creatures then this could lead to 'hacks' of sorts. Being able to target a dead body then have it chain is not how it should work, but then again how should it work?? lol Seems like WoW had a similiar issue with this.., trying to recall exactly what came of it.. Hmm.. could there be a script that can do a 'life check' of sorts? Basically, the script would determine if the creature is alive and/or near death.. if so, the bolt will 'search' for another target (closest in range etc..) Or, it could be made to where the bolt does not go from 'a to b to c to d..' but instead it would be several 'individual' bolts that leave the caster into all 3 targets at once. Im no scripter, but to me it seems that the bolt needs an 'AI' of its own, one that constently searches for new targets until x amount of targets have been hit or chained from.. This should be interesting to follow and watch develop :P lol Link to comment Share on other sites More sharing options...
TGBlank Posted January 15, 2010 Share Posted January 15, 2010 Bridgepiece, you're not getting it. Situation: Y~~~~~~~e_________EEEEEEEEEEEEEEEEEY = you~ = bolte = almost dead enemyE = enemies Vanilla: Y~~~~~x_______EEEEEEEEEEEEE x = dead enemy. E = unharmed enemy Fix: Y~~~~~x~~~~~~eeeeeeeeeeeee The bolt can only spread to live foes, what the code changes, is allowing the bolt to jump to it's next victim if the bolt itself killed the original one. Link to comment Share on other sites More sharing options...
Bridgepiece Posted January 17, 2010 Share Posted January 17, 2010 lol, I totally 'get it' :P I was just suggesting ways to fix it etc.. I played a shammy in WoW for some time, chain lighting was my #2 ability :O lol Link to comment Share on other sites More sharing options...
Recommended Posts