It's my first effort to use structs, and it's not working. I think there's something I'm not understanding about how to interact with structs from outside of them. In the below code, I'm getting an error at the line "if m.missileInRangeOfTarget then", with the error being "Undeclared variable Missile". Even though the struct is included in the same library and above the line where the error occurred, it looks like I'm only able to interact with the struct's static functions and variables. If someone could tell me where I've gone wrong with my attempts to integrate the struct into my code, I'd appreciate it.
To explain the code, it's a system for managing projectiles. I have a hashtable which contains all of the projectiles which are currently in the system, indexed using the childkey of the table. Every interval, the positions of those projectiles get updated, and if they're within range of their targets, they jump to their target, inflict their effects, and destroy themselves. When a projectile is removed from the system, its place in the hashtable is filled by the highest-index missile still in the system, and the highest index in the hashtable is scrubbed - this is to keep the indicies of the hashtable consecutive for the sake of the looping.
I expect that the code has a number of other bugs outside of the problem I'm currently having, but once I have the format down I can probably handle those.
To explain the code, it's a system for managing projectiles. I have a hashtable which contains all of the projectiles which are currently in the system, indexed using the childkey of the table. Every interval, the positions of those projectiles get updated, and if they're within range of their targets, they jump to their target, inflict their effects, and destroy themselves. When a projectile is removed from the system, its place in the hashtable is filled by the highest-index missile still in the system, and the highest index in the hashtable is scrubbed - this is to keep the indicies of the hashtable consecutive for the sake of the looping.
I expect that the code has a number of other bugs outside of the problem I'm currently having, but once I have the format down I can probably handle those.
Code:
library missileSystem initializer onInit
globals
private hashtable missileHashtable = InitHashtable()
private timer t
private real updateInterval = Missile.getInterval
endglobals
struct Missile
private real targetX = 0
private real targetY = 0
private real velocity = 1000
private real damage = 0
private boolean tracking = true
private unit targetUnit
private unit projectileUnit
private unit sourceUnit
private attacktype attackType
private static real interval = 0.02
private real connectRange = 100.
readonly static integer numberOfMissiles = 0
private boolean stun = false
private boolean stunDuration
public static method incrementNumberOfMissiles takes nothing returns nothing
set numberOfMissiles = numberOfMissiles + 1
endmethod
public static method decrementNumberOfMissiles takes nothing returns nothing
set numberOfMissiles = numberOfMissiles - 1
endmethod
public static method getInterval takes nothing returns real
return interval
endmethod
public static method create takes unit source, unit target, real dmg, attacktype atktype, integer projectileUnitTypeID returns Missile
local Missile this = Missile.allocate()
set this.damage = dmg
set this.targetX = GetUnitX(target)
set this.targetY = GetUnitY(target)
set this.sourceUnit = source
set this.targetUnit = target
set this.attackType = atktype
set this.projectileUnit = CreateUnit(GetOwningPlayer(source), projectileUnitTypeID, GetUnitX(source), GetUnitY(source), GetUnitFacing(source))
call incrementNumberOfMissiles()
return this
endmethod
public method destroy takes nothing returns nothing
call this.deallocate()
call decrementNumberOfMissiles()
endmethod
public method reachTarget takes nothing returns nothing
// this won't work with non-tracking projectiles
call SetUnitPosition(this.projectileUnit, getTargetX(), getTargetY())
call UnitDamageTarget(this.sourceUnit, this.targetUnit, this.damage, true, true, this.attackType, null, null)
call KillUnit(this.projectileUnit)
endmethod
private method getTargetX takes nothing returns real
if this.tracking then
return GetUnitX(this.targetUnit)
else
return this.targetX
endif
endmethod
private method getTargetY takes nothing returns real
if this.tracking then
return GetUnitY(this.targetUnit)
else
return this.targetY
endif
endmethod
public method move takes nothing returns nothing
call SetUnitPositionLoc(this.projectileUnit, PolarProjectionBJ(GetUnitLoc(this.projectileUnit), this.velocity*interval, AngleBetweenPoints(GetUnitLoc(this.projectileUnit), Location(getTargetX(), getTargetY()))))
endmethod
public method missileInRangeOfTarget takes nothing returns boolean
return IsUnitInRange(this.projectileUnit, this.targetUnit, connectRange)
endmethod
endstruct
function update takes nothing returns nothing
local integer index = 0
local Missile m
local integer indexOfLandedMissile
loop
exitwhen index == Missile.numberOfMissiles
set m = LoadInteger(missileHashtable, GetHandleId(t), index)
if m.missileInRangeOfTarget then
call m.reachTarget()
call SaveInteger(missileHashtable, GetHandleId(t), index, LoadInteger(missileHashtable, GetHandleId(t), Missile.numberOfMissiles))
call RemoveSavedInteger(missileHashtable, GetHandleId(t), Missile.numberOfMissiles)
call m.destroy()
else
call m.move()
set index = index+1
endif
endloop
set m = null
endfunction
function createMissile takes unit source, unit target, real damage, attacktype attackType, integer projectileUnitTypeID returns nothing
local Missile m = Missile.create(source, target, damage, attackType, projectileUnitTypeID)
call SaveHashtableHandle(missileHashtable, GetHandleId(t), Missile.numberOfMissiles-1, m)
set m = null
endfunction
private function OnInit takes nothing returns nothing
set t = CreateTimer()
call TimerStart(t, updateInterval, true, function update)
endfunction
endlibrary