| 03-20-2010, 12:44 PM | #1 |
Long story short, I have a spell based on Mana Burn that transforms the caster into a copy of the targeted unit for some time (30 seconds). During a MP test, a player using this spell found himself without both the caster and the copy-unit... he told me that the target unit died from the Mana Burn damage (20). What bugs me is that, if the copy-unit hasn't been created for this reason, why was this effect set m.e = AddSpecialEffectTarget("Abilities\\Spells\\Human\\ManaFlare\\ManaFlareTarget.mdl", u, "overhead") shown anyway? (There's no way that it could have been shown because of other triggers or abilities) Does anybody know why the "replacement" unit wasn't (probably) created but the effect was still shown? Assimilate:scope Assimilate initializer Init private struct morph unit c effect e integer i integer o real m integer n endstruct private function Morph takes nothing returns nothing local morph m = morph(GetTimerData(GetExpiredTimer())) local player p = GetOwningPlayer(m.c) local real x = GetUnitX(m.c) local real y = GetUnitY(m.c) local real f = GetUnitFacing(m.c) local real l = (GetUnitState(m.c, UNIT_STATE_LIFE) / GetUnitState(m.c, UNIT_STATE_MAX_LIFE)) local boolean s = IsUnitSelected(m.c, GetLocalPlayer()) local unit u = null if GetWidgetLife(m.c) > 0.405 then if m.n == 0 then set m.m = GetUnitState(m.c, UNIT_STATE_MANA) else call DestroyEffect(m.e) endif call KillUnit(m.c) call RemoveUnit(m.c) call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Human\\ManaFlare\\ManaFlareBoltImpact.mdl", x, y)) set u = CreateUnit(p, m.i, x, y, f) if (GetUnitState(u, UNIT_STATE_MAX_LIFE) * l) > 50 then call SetWidgetLife(u, GetUnitState(u, UNIT_STATE_MAX_LIFE) * l) else call SetWidgetLife(u, 50) endif if s then call SelectUnit(u, true) endif if m.n == 0 then set m.e = AddSpecialEffectTarget("Abilities\\Spells\\Human\\ManaFlare\\ManaFlareTarget.mdl", u, "overhead") call SetUnitState(u, UNIT_STATE_MANA, GetUnitState(u, UNIT_STATE_MAX_MANA) / 2) call UnitAddAbility(u, 'Bed1') set m.i = m.o set m.c = u set m.n = 1 call UnitApplyTimedLife(u, 'Beb2', 30) call TimerStart(GetExpiredTimer(), 29.9, false, function Morph) else call SetUnitState(u, UNIT_STATE_MANA, m.m) call ReleaseTimer(GetExpiredTimer()) call morph.destroy(m) endif else if m.e != null then call DestroyEffect(m.e) endif call morph.destroy(m) call ReleaseTimer(GetExpiredTimer()) endif set u = null set p = null endfunction private function Main takes nothing returns boolean local morph m local real dx = 0 local real dy = 0 local real d = 0 local timer t = null if GetSpellAbilityId() == 'Bea3' then set m = morph.create() set m.i = GetUnitTypeId(GetSpellTargetUnit()) set m.o = GetUnitTypeId(GetTriggerUnit()) set m.n = 0 set m.c = GetTriggerUnit() set t = NewTimer() set dx = GetUnitX(GetSpellTargetUnit()) - GetUnitX(m.c) set dy = GetUnitY(GetSpellTargetUnit()) - GetUnitY(m.c) set d = SquareRoot(dx * dx + dy * dy) call SetTimerData(t, m) call TimerStart(t, d, false, function Morph) endif return false endfunction //=========================================================================== private function Init takes nothing returns nothing local trigger t = CreateTrigger() call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT) call TriggerAddCondition(t, Condition(function Main)) endfunction endscope FYI, 'Bed1' is a buffplacer. And no, I want only the problem to be fixed, don't bug me with posts like "oh, you could write this or that in a different way, it'd look better". |
| 03-20-2010, 02:04 PM | #2 |
Add a check to make sure m.i is not 0 (maybe m.o aswell). |
| 03-20-2010, 02:16 PM | #3 |
Done a quick test, and even when the target is killed by the spell, m.i returns the right value and the spell fires correctly (tried on a Sorceress), so either there was some other stuff happening around and no one noticed or that bug is unit-dependant. Or I misunderstood what the player said. I will let you know, sorry guys =P |
| 03-21-2010, 12:34 AM | #4 | |
One thing to look into would be what happens if you kill a unit with it that does not leave a corpse, such as a wisp (or a regular unit killed by an artillery attack, but that doesn't apply here since we're doing the killing with mana burn): those units are removed from memory pretty much immediately when they die. However, the spell event should fire before the damage event, so even when such units are killed by the spell the function GetUnitTypeId should return the correct value where you use it. Still, this is the only way I can think of it being unit-dependant so it's worth checking out. Another thing to consider is if the caster had almost no hp at the time of the switch and then switched to a unit that has much smaller max hp. If for example the caster had 1/100hp and switched to a unit with 20maxhp, its life would now be set to 0.2hp which would kill it immediately. Quote:
|
| 03-21-2010, 02:28 AM | #5 | |||||
Quote:
Quote:
Quote:
Alright, locations removed. I'm not much into using them anyway, and also that BJ forces me to create locations even when its code needs reals, so... yeah, it's the right thing to do. Quote:
Quote:
What else can I tell you? Uhm... thanks. |
| 03-21-2010, 01:53 PM | #6 | |
Quote:
|
| 03-21-2010, 05:07 PM | #7 | |
Quote:
Anyway, just tested it, and yes, it returns the correct value even if the unit with that id is long since dead. Also, units probably won't get removed from memory immediately, but after their Death animation (or corpse explosion or something like that) if they don't leave any corpse, if this supposition is right I'm already safe. (but I can't test it now) |
