| 02-05-2008, 03:24 AM | #1 |
Okay, I have an ability that detects on attack and does a critical strike. The % is adjusted based on the attacked unit's health. It works perfectly fine like so: JASS:scope FluidCriticalStrike globals private constant integer AID_FLUID_CRITICAL_STRIKE='A001' private constant string EFFECT_FLUID_CRITICAL_STRIKE="Abilities\\Spells\\Other\\Stampede\\StampedeMissileDeath.mdl" endglobals struct FCS trigger t triggercondition b triggeraction a unit attacker private method textTag takes real dmg, real x, real y returns nothing local texttag t=CreateTextTag() call SetTextTagText(t, I2S(R2I(dmg))+"!",0.024) call SetTextTagPos(t,x,y,0) call SetTextTagColor(t,255,0,0,255) call SetTextTagVelocity(t,0,0.04) call SetTextTagFadepoint(t,1.2) call SetTextTagLifespan(t,4.5) call SetTextTagPermanent(t,false) call SetTextTagVisibility(t,true) set t=null endmethod public method Damage takes unit a, unit u, real dmg returns nothing set dmg=dmg*(1.4+GetUnitAbilityLevel(a,AID_FLUID_CRITICAL_STRIKE)*.4) call UnitDamageTarget(a, u, dmg, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, null) call this.textTag(dmg,GetUnitX(a),GetUnitY(a)) if EFFECT_FLUID_CRITICAL_STRIKE != "" then call DestroyEffect(AddSpecialEffectTarget(EFFECT_FLUID_CRITICAL_STRIKE,u,"chest")) endif endmethod endstruct private function DamageConditions takes nothing returns boolean local FCS fcs=H2I(GetTriggeringTrigger()) return GetEventDamageSource()==fcs.attacker endfunction private function DamageActions takes nothing returns nothing local trigger trig=GetTriggeringTrigger() local FCS fcs=H2I(trig) call TriggerRemoveCondition(trig,fcs.b) call TriggerRemoveAction(trig,fcs.a) call DestroyTrigger(trig) set fcs.t=null call fcs.Damage(GetEventDamageSource(),GetTriggerUnit(),GetEventDamage()) set trig=null endfunction private function Conditions takes nothing returns boolean return GetUnitAbilityLevel(GetAttacker(),AID_FLUID_CRITICAL_STRIKE) > 0 and not IsUnitType(GetTriggerUnit(), UNIT_TYPE_STRUCTURE) endfunction private function Actions takes nothing returns nothing local unit u=GetTriggerUnit() local real hp=GetUnitState(u,UNIT_STATE_LIFE) / GetUnitState(u,UNIT_STATE_MAX_LIFE) local integer chance=GetUnitAbilityLevel(GetAttacker(),AID_FLUID_CRITICAL_STRIKE) local trigger trig local boolexpr be local FCS fcs=FCS.create() if hp<0.25 then set chance=30 + chance * 15 elseif hp>0.50 then set chance=10 + chance * 5 else set chance=20 + chance * 10 endif if chance>=GetRandomInt(1,100) then set trig=CreateTrigger() set fcs.attacker=GetAttacker() set fcs.t=trig call TriggerRegisterUnitEvent(trig, u, EVENT_UNIT_DAMAGED) set be=Condition(function DamageConditions) set fcs.b=TriggerAddCondition(trig,be) call DestroyBoolExpr(be) set be=null set fcs.a=TriggerAddAction(trig, function DamageActions) set trig=null endif set u=null endfunction public function InitTrig takes nothing returns nothing local trigger trig=CreateTrigger() call TriggerRegisterAnyUnitEventBJ(trig, EVENT_PLAYER_UNIT_ATTACKED) call TriggerAddCondition(trig, Condition(function Conditions)) call TriggerAddAction(trig, function Actions) call Preload(EFFECT_FLUID_CRITICAL_STRIKE) endfunction endscope However, I tried moving a few things around, and it causes warcraft to crash, as well as the text doesn't display: JASS:scope FluidCriticalStrike globals private constant integer AID_FLUID_CRITICAL_STRIKE='A001' private constant string EFFECT_FLUID_CRITICAL_STRIKE="Abilities\\Spells\\Other\\Stampede\\StampedeMissileDeath.mdl" endglobals struct FCS trigger t triggercondition b triggeraction a unit attacker texttag txttag=CreateTextTag() private method textTag takes real dmg, real x, real y returns nothing call SetTextTagText(.txttag, I2S(R2I(dmg))+"!",0.024) call SetTextTagPos(.txttag,x,y,0) call SetTextTagColor(.txttag,255,0,0,255) call SetTextTagVelocity(.txttag,0,0.04) call SetTextTagFadepoint(.txttag,1.2) call SetTextTagLifespan(.txttag,4.5) call SetTextTagPermanent(.txttag,false) call SetTextTagVisibility(.txttag,true) endmethod public method Damage takes unit a, unit u, real dmg returns nothing call this.destroy() set dmg=dmg*(1.4+GetUnitAbilityLevel(a,AID_FLUID_CRITICAL_STRIKE)*.4) call UnitDamageTarget(a, u, dmg, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, null) call this.textTag(dmg,GetUnitX(a),GetUnitY(a)) if EFFECT_FLUID_CRITICAL_STRIKE != "" then call DestroyEffect(AddSpecialEffectTarget(EFFECT_FLUID_CRITICAL_STRIKE,u,"chest")) endif endmethod public method onDestroy takes nothing returns nothing call TriggerRemoveCondition(.t,.b) call TriggerRemoveAction(.t,.a) call DestroyTrigger(.t) set .t=null set .attacker=null set .txttag=null endmethod endstruct private function DamageConditions takes nothing returns boolean local FCS fcs=H2I(GetTriggeringTrigger()) return GetEventDamageSource()==fcs.attacker endfunction private function DamageActions takes nothing returns nothing local FCS fcs=H2I(GetTriggeringTrigger()) call fcs.Damage(GetEventDamageSource(),GetTriggerUnit(),GetEventDamage()) endfunction private function Conditions takes nothing returns boolean return GetUnitAbilityLevel(GetAttacker(),AID_FLUID_CRITICAL_STRIKE) > 0 and not IsUnitType(GetTriggerUnit(), UNIT_TYPE_STRUCTURE) endfunction private function Actions takes nothing returns nothing local unit u=GetTriggerUnit() local real hp=GetUnitState(u,UNIT_STATE_LIFE) / GetUnitState(u,UNIT_STATE_MAX_LIFE) local integer chance=GetUnitAbilityLevel(GetAttacker(),AID_FLUID_CRITICAL_STRIKE) local trigger trig local boolexpr be local FCS fcs=FCS.create() if hp<0.25 then set chance=30 + chance * 15 elseif hp>0.50 then set chance=10 + chance * 5 else set chance=20 + chance * 10 endif if chance>=GetRandomInt(1,100) then set trig=CreateTrigger() set fcs.attacker=GetAttacker() set fcs.t=trig call TriggerRegisterUnitEvent(trig, u, EVENT_UNIT_DAMAGED) set be=Condition(function DamageConditions) set fcs.b=TriggerAddCondition(trig,be) call DestroyBoolExpr(be) set be=null set fcs.a=TriggerAddAction(trig, function DamageActions) set trig=null endif set u=null endfunction public function InitTrig takes nothing returns nothing local trigger trig=CreateTrigger() call TriggerRegisterAnyUnitEventBJ(trig, EVENT_PLAYER_UNIT_ATTACKED) call TriggerAddCondition(trig, Condition(function Conditions)) call TriggerAddAction(trig, function Actions) call Preload(EFFECT_FLUID_CRITICAL_STRIKE) endfunction endscope 1. What am I doing incorrectly with the onDestroy? 2. Why is it wrong? 3. Why doesn't the blasted texttag work? 4. Why is it that aside from integers and reals, my variables do not seem to work properly when called from a method like .variable? A string didn't work, but when I made an integer and then did an I2S(.integer), it displayed fine. I am guessing this is the same problem as question 3. Edit: I thought my integers and reals were working, but I always use 0 as my default value. No matter the value of .integer, it would display 0. So they aren't working either. This leads me to believe that not a single variable of this struct is working, which is the cause of all my other problems. Yet, parts of it have to work outside of the methods, because the trigger still works as intended except for my blasted DamageConditions. |
| 02-05-2008, 05:01 AM | #2 |
The crash is almost certainly caused by DamageTarget activating the trigger which calls DamageTarget, causing an infinite loop. You don't appear to be attaching the struct to the trigger at all. You need to use Handle Vars or CS_Cache or ABC. You don't need to create a seperate trig variable, you can just do set fcs.t = CreateTrigger() straight off. Also, you don't need to destroy boolexpr because they're saved in a lookup table. |
| 02-05-2008, 05:48 AM | #3 |
I realized I'm not attaching it to the trigger. I was just on my way here to edit my post to say so but you had already posted. BTW, I don't have to use a system, it is normally just easier, plus using a system gives consistency. I've used my own methods for all my past attaching, but this one is just giving me a bugger of a time. So I'm going to use Cohadar's ABC. I've read several posts in different places by different people to bloody destroy them. So I'm going to! :) Edit: Forgot to post my code which still crashes: Edit2: It works now. I had a small logic error: JASS:scope FluidCriticalStrike globals private constant integer AID_FLUID_CRITICAL_STRIKE='A001' private constant string EFFECT_FLUID_CRITICAL_STRIKE="Abilities\\Spells\\Other\\Stampede\\StampedeMissileDeath.mdl" endglobals struct CritStrike trigger trig=CreateTrigger() triggercondition c triggeraction a unit attacker unit target texttag tag=CreateTextTag() private method textTag takes real dmg returns nothing call SetTextTagText(.tag,I2S(R2I(dmg))+"!",0.024) call SetTextTagPos(.tag,GetUnitX(.attacker),GetUnitY(.attacker),0) call SetTextTagColor(.tag,255,0,0,255) call SetTextTagVelocity(.tag,0,0.04) call SetTextTagFadepoint(.tag,1.2) call SetTextTagLifespan(.tag,4.5) call SetTextTagPermanent(.tag,false) call SetTextTagVisibility(.tag,true) endmethod private method onDestroy takes nothing returns nothing call ClearTriggerStructA(.trig) call TriggerRemoveCondition(.trig,.c) call TriggerRemoveAction(.trig,.a) call DestroyTrigger(.trig) endmethod public method Damage takes real dmg returns nothing set .target=GetTriggerUnit() call this.destroy() call UnitDamageTarget(.attacker,.target,dmg,true,false,ATTACK_TYPE_NORMAL,DAMAGE_TYPE_NORMAL,null) call this.textTag(dmg) if EFFECT_FLUID_CRITICAL_STRIKE != "" then call DestroyEffect(AddSpecialEffectTarget(EFFECT_FLUID_CRITICAL_STRIKE,.target,"chest")) endif endmethod endstruct private function DamageConditions takes nothing returns boolean local CritStrike data=GetTriggerStructA(GetTriggeringTrigger()) return GetEventDamageSource()==data.attacker endfunction private function DamageActions takes nothing returns nothing local CritStrike data=GetTriggerStructA(GetTriggeringTrigger()) call data.Damage(GetEventDamage()*(1.4+GetUnitAbilityLevel(data.attacker,AID_FLUID_CRITICAL_STRIKE)*.4)) endfunction private function Conditions takes nothing returns boolean local real hp=GetUnitState(GetTriggerUnit(),UNIT_STATE_LIFE) / GetUnitState(GetTriggerUnit(),UNIT_STATE_MAX_LIFE) local real chance=GetUnitAbilityLevel(GetAttacker(),AID_FLUID_CRITICAL_STRIKE) if hp<0.25 then set chance=.3 + chance * .15 elseif hp>0.50 then set chance=.1 + chance * .05 else set chance=.2 + chance * .1 endif return chance>=GetRandomInt(0,1) and GetUnitAbilityLevel(GetAttacker(),AID_FLUID_CRITICAL_STRIKE) > 0 and not IsUnitType(GetTriggerUnit(),UNIT_TYPE_STRUCTURE) endfunction private function Actions takes nothing returns nothing local boolexpr be local CritStrike data=CritStrike.create() set data.attacker=GetAttacker() call SetTriggerStructA(data.trig,data) call TriggerRegisterUnitEvent(data.trig,GetTriggerUnit(),EVENT_UNIT_DAMAGED) set be=Condition(function DamageConditions) set data.c=TriggerAddCondition(data.trig,be) call DestroyBoolExpr(be) set be=null set data.a=TriggerAddAction(data.trig,function DamageActions) endfunction public function InitTrig takes nothing returns nothing local trigger trig=CreateTrigger() call TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_UNIT_ATTACKED) call TriggerAddCondition(trig,Condition(function Conditions)) call TriggerAddAction(trig,function Actions) call Preload(EFFECT_FLUID_CRITICAL_STRIKE) endfunction endscope |
