• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[Solved] Missile Management System (Structs)

Status
Not open for further replies.
Level 2
Joined
Jan 8, 2018
Messages
12
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.

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
 
Level 2
Joined
Jan 8, 2018
Messages
12
Wow, I can't believe I didn't catch that. I guess sometimes you do just need another pair of eyes. Thanks.
 
Status
Not open for further replies.
Top