JASS:
scope BobOmb initializer OnInit
globals
private real explosionRadius=200.
private real blueHeroTargetRadius=450.
private real blueTargetRadius=450.
private real bobOmbTempReal=0.
private unit bobOmbTempUnit=null
endglobals
private struct BobOmbAI
private static unit tempUnit
private static real tempReal
private static real tempDur
location walkTo
real damage
real stunDuration
real boomTimer
real offsetAngle
unit bobomb
unit latchUnit
boolean isLatched
boolean timedLife
private static method damageCondition takes nothing returns boolean
return IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(thistype.tempUnit))==true and IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE)==false and IsUnitDeadBJ(GetFilterUnit())==false
endmethod
private static method isHero takes nothing returns boolean
return IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(thistype.tempUnit)) and IsUnitType(GetFilterUnit(), UNIT_TYPE_HERO)==true and IsUnitDeadBJ(GetFilterUnit())==false
endmethod
private static method explode takes nothing returns nothing
call Damage_Spell(thistype.tempUnit, GetEnumUnit(), thistype.tempReal)
if(thistype.tempDur!=0.)then
call stun(GetEnumUnit(), thistype.tempDur)
endif
endmethod
private method destroy takes nothing returns nothing
call .deallocate()
set .bobomb=null
set .latchUnit=null
call RemoveLocation(.walkTo)
endmethod
private method periodic takes nothing returns nothing
local location l=GetUnitLoc(.bobomb)
local location l2=null
local group g
call DisplayTextToForce(bj_FORCE_ALL_PLAYERS, GetUnitName(.bobomb))
if(GetUnitTypeId(.bobomb)==039;h002039; or GetUnitTypeId(.bobomb)==039;h003039;)then//red or green bobomb
//if not moving, get it moving
if(GetUnitCurrentOrder(.bobomb)!=OrderId("move"))then
call IssuePointOrder(.bobomb, "move", GetLocationX(.walkTo), GetLocationY(.walkTo))
endif
//if the bobomb has reached its destination, explode
if(DistanceBetweenPoints(l, walkTo) < 50)then
set thistype.tempUnit=.bobomb
set g=GetUnitsInRangeOfLocMatching(explosionRadius, l, Condition(function thistype.damageCondition))
set thistype.tempReal=.damage
set thistype.tempDur=.stunDuration
call ForGroup(g, function thistype.explode)
call KillUnit(.bobomb)
call .stopPeriodic()
call .destroy()
endif
else
if(GetUnitTypeId(.bobomb)==039;h004039; and Jump.isOn(.bobomb)==false)then//blue bobomb
//blue bobombs explode 5 seconds after they land
set .boomTimer=.boomTimer+T32_PERIOD
if(.boomTimer >=5.)then
call DisplayTextToForce(bj_FORCE_ALL_PLAYERS, "boom")
set thistype.tempUnit=.bobomb
set g=GetUnitsInRangeOfLocMatching(explosionRadius, l, Condition(function thistype.damageCondition))
set thistype.tempReal=.damage
call ForGroup(g, function thistype.explode)
call KillUnit(.bobomb)
call .stopPeriodic()
call .destroy()
endif
//blue bobombs look for a nearby enemy when they land, prioritizing heroes
if(.isLatched==false and .latchUnit==null)then
call DisplayTextToForce(bj_FORCE_ALL_PLAYERS, "finding latchee")
set g = GetUnitsInRangeOfLocMatching(blueHeroTargetRadius, l, Condition(function thistype.isHero))
if(CountUnitsInGroup(g) == 0)then
call DestroyGroup(g)
set g = GetUnitsInRangeOfLocMatching(blueTargetRadius, l, Condition(function thistype.damageCondition))
endif
if(CountUnitsInGroup(g)>0)then
set .latchUnit=FirstOfGroup(g)
endif
else
//if the blue bobomb hasn't attached to the unit it wants to attach to, chase it down
if(.isLatched==false)then
if(GetUnitCurrentOrder(.bobomb)!=OrderId("move"))then
call DisplayTextToForce(bj_FORCE_ALL_PLAYERS, "chasing latchee")
call IssuePointOrder(.bobomb, "move", GetUnitX(.latchUnit), GetUnitY(.latchUnit))
endif
//if the unit it wishes to attach to dies or leaves the bobomb's vision, look for a new unit
if(IsUnitVisible(.latchUnit, GetOwningPlayer(.bobomb))==false or IsUnitDeadBJ(.latchUnit))then
set .isLatched=false
set .latchUnit=null
else
//otherwise, check if the bobomb is close enough to the target and if so latch to it
set l2=GetUnitLoc(.latchUnit)
if(DistanceBetweenPoints(l, l2) <= 50.)then
call DisplayTextToForce(bj_FORCE_ALL_PLAYERS, "latch")
set .isLatched=true
set .boomTimer=0.
set .offsetAngle=AngleBetweenPoints(l2, l)//eye candy stuff
call PauseUnit(.bobomb, true)
endif
endif
else
//if the bobomb is latched then coninuously move it with the unit it is latched to
set l2=GetUnitLoc(.latchUnit)
call RemoveLocation(l)
set l=PolarProjectionBJ(l2, 50., .offsetAngle)
call MoveUnit(.bobomb, l2)
call DisplayTextToForce(bj_FORCE_ALL_PLAYERS, "attached")
endif
endif
endif
endif
call RemoveLocation(l)
call RemoveLocation(l2)
call DestroyGroup(g)
endmethod
implement T32x
static method create takes unit bb, location wt, real damage, real stunDuration returns thistype
local thistype bbai = BobOmbAI.allocate()
set bbai.walkTo=wt
set bbai.damage=damage
set bbai.stunDuration=stunDuration
set bbai.isLatched=false
set bbai.bobomb=bb
set bbai.timedLife=false
set bbai.boomTimer=0.
call bbai.startPeriodic()
return bbai
endmethod
endstruct
private function RedBombActions takes nothing returns nothing
local location l=GetUnitLoc(GetTriggerUnit())
local location lTar=GetSpellTargetLoc()
local real level = I2R(GetUnitAbilityLevel(GetTriggerUnit(), 039;rbob039;))
//used elsewhere
set BobOmbStruct[GetTriggerUnit()].redBombs=BobOmbStruct[GetTriggerUnit()].redBombs-1
if(BobOmbStruct[GetTriggerUnit()].redBombs > 0)then
call refreshAbil(GetTriggerUnit(), 039;rbob039;)
endif
//end used elsewhere
set bj_lastCreatedUnit = CreateUnit(GetOwningPlayer(GetTriggerUnit()), 039;h002039;, GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()), AngleBetweenPoints(l, lTar))
call SetUnitColor(bj_lastCreatedUnit, GetPlayerColor(Player(0)))
call BobOmbAI.create(bj_lastCreatedUnit, lTar, 50.*level+2.*GetHeroInt(GetTriggerUnit(), true), .35+.15*level)
call RemoveLocation(l)
endfunction
private function GreenBombActions takes nothing returns nothing
local location l=GetUnitLoc(GetTriggerUnit())
local location lTar=GetSpellTargetLoc()
local real level = I2R(GetUnitAbilityLevel(GetTriggerUnit(), 039;A08G039;))
//used elsewhere
set BobOmbStruct[GetTriggerUnit()].greenBombs=BobOmbStruct[GetTriggerUnit()].greenBombs-1
if(BobOmbStruct[GetTriggerUnit()].greenBombs > 0)then
call refreshAbil(GetTriggerUnit(), 039;A08G039;)
endif
//end used elsewhere
set bj_lastCreatedUnit = CreateUnit(GetOwningPlayer(GetTriggerUnit()), 039;h003039;, GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()), AngleBetweenPoints(l, lTar))
call SetUnitColor(bj_lastCreatedUnit, GetPlayerColor(Player(6)))
call BobOmbAI.create(bj_lastCreatedUnit, lTar, 50 + 25.*level+(.5 + .5*level)*GetHeroInt(GetTriggerUnit(), true), 0)
call RemoveLocation(l)
endfunction
private function BlueBombActions takes nothing returns nothing
local location l=GetUnitLoc(GetTriggerUnit())
local location lTar=GetSpellTargetLoc()
local real level = I2R(GetUnitAbilityLevel(GetTriggerUnit(), 039;A095039;))
//used elsewhere
set BobOmbStruct[GetTriggerUnit()].blueBombs=BobOmbStruct[GetTriggerUnit()].blueBombs-1
if(BobOmbStruct[GetTriggerUnit()].blueBombs > 0)then
call refreshAbil(GetTriggerUnit(), 039;A095039;)
endif
//end used elsewhere
set bj_lastCreatedUnit = CreateUnit(GetOwningPlayer(GetTriggerUnit()), 039;h004039;, GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()), AngleBetweenPoints(l, lTar))
call SetUnitColor(bj_lastCreatedUnit, GetPlayerColor(Player(1)))
call Jump.apply(bj_lastCreatedUnit, .75, false, false, lTar, DistanceBetweenPoints(l, lTar)*.75, "", "walk", 1)
call BobOmbAI.create(bj_lastCreatedUnit, lTar, 25. + 75.*level + 1.5*GetHeroInt(GetTriggerUnit(), true), 0)
call RemoveLocation(l)
endfunction
private function OnInit takes nothing returns nothing
call TriggerAddAction(GT_RegisterStartsEffectEvent(CreateTrigger(), 039;rbob039;), function RedBombActions)//h002
call TriggerAddAction(GT_RegisterStartsEffectEvent(CreateTrigger(), 039;A08G039;), function GreenBombActions)//h003
call TriggerAddAction(GT_RegisterStartsEffectEvent(CreateTrigger(), 039;A095039;), function BlueBombActions)//h004
endfunction
endscope
Well, this is for a bob-omb character (as you may tell from the title). As odd as it may sound this character's powers make other bob-ombs (red, green, or blue) that do various things.
Red - runs to the destination then explodes and stuns
Green - runs to the destination and explodes
Blue - gets lobbed (tossed through the air) then attaches to the nearest enemy, prioritizing heroes, and blows up 5 seconds after landing
It pretty much all works (still have some testing to do) but I ran across an error that I'm sure is basic with structs. It seems that the BobOmbAI.bobomb variable is getting.... I dunno how to say it, temporarily overwritten? Each bob-omb works on its own but when thrown in conjunction things get screwy.
If I throw a red and a green bob-omb, or 2 reds or 2 greens, then they will only explode when all the red or green bob-ombs have stopped moving rather than as soon as they get where they're headed. The output shows that the bobomb will be the second one I throw until all stop then it quickly runs through all the stopped bobombs.
If I throw 2 or more blue bob-ombs then it depends when I throw them. If I throw the second blue before the first one lands, then they will both wait till their 5 second timers are up before exploding simultaneously. But if I wait for the first to land before throwing the second, then their 5 second timers work just fine.
Any and all help appreciated. Please forgive this noob for his lazy/bad coding and critique what you can as you will.