| 02-24-2009, 09:52 AM | #1 |
This supposed to do this: When a unit with an ability damages an enemy by attack, for each unit within X range of the stricken unit will be generated a dummy that will attack collateral unit for Y duration or until the collateral unit or generating unit dies. UPDATE: This is what happens, more precisely: 1) Dummies do not get removed most of the time, generally. * by BJDebugMsg(), I have found out that the Fire instances' duration meters get reset whenever they expire... 2) Dummies are able to propagate themselves (FIRE_CAN_PROPAGATE = true) on their own targets (even when FIRE_CAN_STACK = false). This has something to do with the above problem, I think; dummies continue to propagate themselves but they are themselves no longer registered as dummies so there will be no stacking impediments. What's wrong? JASS:library Wildfire initializer Init requires DamageEvent //IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII// //IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII// // -- Configuration -- globals constant integer WILDFIRE_ABILITY_ID = 'A000' private constant integer FIRE_UNIT_ID = 'O002' private constant boolean FIRE_CAN_STACK = false private constant boolean FIRE_CAN_PROPAGATE = true private constant real FIRE_LIGHT_DISTANCE = 200.00 private constant real FIRE_MONITOR_INTERVAL_DURATION = 0.05 endglobals private constant function GetProcPercentChance takes integer level returns integer return 100//level * 10 endfunction private constant function GetSpreadAreaRadius takes integer level returns real return 200.00 + level * 100.00 endfunction private constant function GetFireDuration takes integer level returns real return 4.00 + level * 2.00 endfunction //IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII// //IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII// // -- Script Operation Functions -- globals private group gUG = CreateGroup() private player gP = null endglobals private function IsAbility takes nothing returns boolean return IsEventDamageAttack() and GetUnitAbilityLevel(GetDamagingUnit(), WILDFIRE_ABILITY_ID) > 0 and IsUnitEnemy(GetDamagedUnit(), GetOwningPlayer(GetDamagingUnit())) and GetRandomInt(1, 100) <= GetProcPercentChance(GetUnitAbilityLevel(GetDamagingUnit(), WILDFIRE_ABILITY_ID)) endfunction private keyword Fire private function ValidateTarget takes nothing returns boolean local boolean BOOL = GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE) > 0.00 and IsUnitType(GetFilterUnit(), UNIT_TYPE_GROUND) and IsUnitEnemy(GetFilterUnit(), gP) if FIRE_CAN_STACK == false then set BOOL = BOOL and Fire.IsUnitOnFire(GetFilterUnit()) == false endif return BOOL endfunction private struct Fire[8191] private unit u private unit uFire private unit uTarget private real rDuration private boolean boolLit = false public static method Create takes unit u, player owner, real x, real y, real facing, integer heroLevel, unit target, integer level, real duration returns nothing if Fire.intCountInst < 8191 then set Fire.Inst[Fire.intCountInst] = Fire.allocate() set Fire.Inst[Fire.intCountInst].u = u set Fire.Inst[Fire.intCountInst].uFire = CreateUnit(owner, FIRE_UNIT_ID, x, y, facing) call SetHeroLevel(Fire.Inst[Fire.intCountInst].uFire, heroLevel, false) if FIRE_CAN_PROPAGATE then call UnitAddAbility(Fire.Inst[Fire.intCountInst].uFire, WILDFIRE_ABILITY_ID) call SetUnitAbilityLevel(Fire.Inst[Fire.intCountInst].uFire, WILDFIRE_ABILITY_ID, level) endif set Fire.Inst[Fire.intCountInst].uTarget = target set Fire.Inst[Fire.intCountInst].rDuration = duration set Fire.Inst[Fire.intCountInst].intInstIndex = Fire.intCountInst set Fire.intCountInst = Fire.intCountInst + 1 call Fire.ManageTimer(true) call IssueTargetOrder(Fire.Inst[Fire.intCountInst - 1].uFire, "attack", target) endif endmethod private method Destroy takes nothing returns nothing call RemoveUnit(.uFire) set Fire.intCountInst = Fire.intCountInst - 1 set Fire.Inst[Fire.intCountInst].intInstIndex = .intInstIndex set this = 0 set Fire.Inst[.intInstIndex] = Fire.Inst[Fire.intCountInst] set Fire.Inst[Fire.intCountInst] = 0 call Fire.ManageTimer(false) endmethod private integer intInstIndex private static Fire array Inst[8191] private static integer intCountInst = 0 private static method MonitorAll takes nothing returns nothing local integer INT_Index = 0 local boolean BOOL_InFireLightRange local real R_Angle loop exitwhen INT_Index == Fire.intCountInst if GetUnitState(Fire.Inst[INT_Index].u, UNIT_STATE_LIFE) > 0.00 and GetUnitState(Fire.Inst[INT_Index].uTarget, UNIT_STATE_LIFE) > 1.00 then set Fire.Inst[INT_Index].rDuration = Fire.Inst[INT_Index].rDuration - FIRE_MONITOR_INTERVAL_DURATION if Fire.Inst[INT_Index].rDuration > 0.00 then set BOOL_InFireLightRange = IsUnitInRange(Fire.Inst[INT_Index].uFire, Fire.Inst[INT_Index].uTarget, FIRE_LIGHT_DISTANCE) if Fire.Inst[INT_Index].boolLit == false and BOOL_InFireLightRange then set Fire.Inst[INT_Index].boolLit = true endif if Fire.Inst[INT_Index].boolLit and BOOL_InFireLightRange == false then set R_Angle = Atan2(GetUnitY(Fire.Inst[INT_Index].uFire) - GetUnitY(Fire.Inst[INT_Index].uTarget), GetUnitX(Fire.Inst[INT_Index].uFire) - GetUnitX(Fire.Inst[INT_Index].uTarget)) call SetUnitX(Fire.Inst[INT_Index].uFire, GetUnitX(Fire.Inst[INT_Index].uTarget) + FIRE_LIGHT_DISTANCE * Cos(R_Angle)) call SetUnitY(Fire.Inst[INT_Index].uFire, GetUnitY(Fire.Inst[INT_Index].uTarget) + FIRE_LIGHT_DISTANCE * Sin(R_Angle)) call SetUnitFacing(Fire.Inst[INT_Index].uFire, (R_Angle * bj_RADTODEG) + 180.00) endif call IssueTargetOrder(Fire.Inst[INT_Index].uFire, "attack", Fire.Inst[INT_Index].uTarget) else call Fire.Inst[INT_Index].Destroy() set INT_Index = INT_Index - 1 endif else call Fire.Inst[INT_Index].Destroy() set INT_Index = INT_Index - 1 endif set INT_Index = INT_Index + 1 endloop endmethod private static timer tim = CreateTimer() private static method ManageTimer takes boolean add returns nothing if Fire.intCountInst == 0 then call PauseTimer(Fire.tim) elseif add and Fire.intCountInst == 1 then call TimerStart(Fire.tim, FIRE_MONITOR_INTERVAL_DURATION, true, function Fire.MonitorAll) endif endmethod public static method IsUnitOnFire takes unit target returns boolean local integer INT_Index = 0 loop exitwhen INT_Index == Fire.intCountInst if Fire.Inst[INT_Index].uTarget == target then return true endif set INT_Index = INT_Index + 1 endloop return false endmethod endstruct private function ApplyAbility takes nothing returns nothing local unit U = GetDamagingUnit() local integer INT_HeroLevel = GetHeroLevel(U) local integer INT_Level = GetUnitAbilityLevel(U, WILDFIRE_ABILITY_ID) local unit U_Target = GetTriggerUnit() local real R_XTarget = GetUnitX(U_Target) local real R_YTarget = GetUnitY(U_Target) local real R_Duration = GetFireDuration(INT_Level) set gP = GetOwningPlayer(U) call GroupEnumUnitsInRange(gUG, R_XTarget, R_YTarget, GetSpreadAreaRadius(INT_Level), Filter(function ValidateTarget)) loop set U_Target = FirstOfGroup(gUG) exitwhen U_Target == null call Fire.Create(U, gP, R_XTarget, R_YTarget, bj_RADTODEG * Atan2(GetUnitY(U_Target) - R_YTarget, GetUnitX(U_Target) - R_XTarget), INT_HeroLevel, U_Target, INT_Level, R_Duration) call GroupRemoveUnit(gUG, U_Target) endloop set U = null set gP = null set U_Target = null call GroupClear(gUG) endfunction private function Init takes nothing returns nothing local trigger TRIG = CreateTrigger() call TriggerRegisterDamageEvent(TRIG) call TriggerAddCondition(TRIG, Condition(function IsAbility)) call TriggerAddAction(TRIG, function ApplyAbility) set TRIG = null endfunction endlibrary |
| 03-01-2009, 10:15 AM | #2 |
bump |
| 03-02-2009, 10:33 AM | #3 |
nobody? |
| 03-02-2009, 10:42 AM | #4 |
JASS:private struct Fire[8191] |
