Mortar Team Detection Does Not Work

Tyman2007

Ya Rly >.
Reaction score
74
I have this spell here, and it's supposed to detect if a mortar team is nearby. If a mortar team is not, then the trigger is not ran. I also made it an option to turn off the check so the player may cast it whenever they please, so I implemented a [ljass]static if[/ljass], but obviously I did it wrong because I'm away from the mortar team and it does not say anything.

I added in a debug message to display that there is no mortar team present.
The message is never displayed, so I'm thinking that it's probably in my custom
"GetUnitsInRange" function.

Here's the trigger so far.
JASS:
library FireRocket initializer Init requires TimerUtils

    globals
        private constant real CALLBACK = 0.03725 //How often the move is repeated
        private constant real INIT_DIST = 150 //Missile spawn distance from caster
        
        private constant boolean REQ_MT = true //Requires mortar team to be close?
        private constant real MT_DIST = 250 //Within what range of the mortar team?
        private constant integer MT_ID = 'hmtm' //Rawcode of Mortar Team
    endglobals
    
    private constant function Degtorad takes nothing returns real
        return 3.1415926535897932384626433832 / 180
    endfunction
    
    private constant function filter takes nothing returns boolean
        return IsUnitType(GetFilterUnit(),UNIT_TYPE_DEAD) == false and /*
        */     GetUnitTypeId(GetFilterUnit()) == MT_ID
    endfunction
    
    private function GetUnitsInRange takes unit u returns group
        local group g = CreateGroup()
        call GroupEnumUnitsInRange(g, GetUnitX(u), GetUnitY(u), MT_DIST, function filter)
        return g
    endfunction
    
    private struct Data
        player p
        unit u
        real r
        
        real x
        real y
        
        real x2
        real y2
        
        real x3
        real y3
        
        real f
        
        static method create takes unit u returns Data
            local Data d = Data.allocate()
            
            set d.u = u
            set d.p = GetOwningPlayer(u)
        
            set d.x = GetUnitX(u)
            set d.y = GetUnitY(u)
        
            set d.f = GetUnitFacing(u)
        
            set d.x2 = d.x + INIT_DIST * Cos(d.f * Degtorad())
            set d.y2 = d.y + INIT_DIST * Sin(d.f * Degtorad())
            
            return d
        endmethod
    endstruct

    private function Conditions takes nothing returns boolean
        return GetSpellAbilityId() == 'A000'
    endfunction
    
    private function CallBack takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local Data d = GetTimerData(t)
        
        call d.destroy()
        call ReleaseTimer(t)
    endfunction

    private function Actions takes nothing returns nothing
        local timer t = NewTimer()
        local unit u = GetTriggerUnit()
        local Data d = Data.create(u)
        local group g
        
        static if (REQ_MT) then
            set g = GetUnitsInRange(d.u)
            if FirstOfGroup(g) == null then
                call BJDebugMsg("Error: No Mortar Team Detected")
                return nothing
            endif
        endif
        
        call PauseUnit(d.u, true)
        
        call SetTimerData(t, d)
        call TimerStart(t, CALLBACK, true, function CallBack)
    endfunction

    private function Init takes nothing returns nothing
        local trigger trig = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ( trig, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddCondition( trig, Condition( function Conditions ) )
        call TriggerAddAction( trig, function Actions )
    endfunction

endlibrary


All helpful posts can and will be readily appreciated on sight :p
 

Sgqvur

FullOfUltimateTruthsAndEt ernalPrinciples, i.e shi
Reaction score
62
Perhaps instead of [lJASS]IsUnitType(GetFilterUnit(),UNIT_TYPE_DEAD) == false[/lJASS]

[lJASS]GetWidgetLife(GetFilterUnit()) > 0.405[/lJASS]
 

BlackRose

Forum User
Reaction score
239
Erm. It works correctly? (after I removed that [ljass]nothing[/ljass] on the [ljass]return[/ljass]).

Here's a fixed up code:

JASS:
library FireRocket initializer Init requires TimerUtils

    globals
        private constant real CALLBACK   = 0.03725 // How often the move is repeated
        private constant real INIT_DIST  = 150     // Missile spawn distance from caster
        
        private constant boolean REQ_MT = true   // Requires mortar team to be close?
        private constant real MT_DIST   = 250    // Within what range of the mortar team?
        private constant integer MT_ID  = 'hmtm' // Rawcode of Mortar Team
    endglobals
    
    // A bit silly this function isn't it? You have a global.
    // bj_DEGTORAD - it works fine.
    
    //private constant function Degtorad takes nothing returns real
    //    return 3.1415926535897932384626433832 / 180
    //endfunction

    globals
        private unit tempUnit    = null // You call GetFilterUnit() more than once.
        private group ENUM_GROUP = CreateGroup() // Dynamic groups are bad.
    endglobals
    
    // UnitAlive is better. More efficient or something?
    
    native UnitAlive takes unit id returns boolean
    
    private /*constant*/ function filter takes nothing returns boolean
        set tempUnit = GetFilterUnit()
        return UnitAlive( tempUnit ) and /*     // Living
        */     GetUnitTypeId(tempUnit) == MT_ID // Is a mortar
    endfunction
    
    
    // This function is somewhat useless. You can use it directly. Also you never clear the leak.
    //private function GetUnitsInRange takes unit u returns group
    //    local group g = CreateGroup()
    //    call GroupEnumUnitsInRange(g, GetUnitX(u), GetUnitY(u), MT_DIST, function filter)
    //    return g
    //endfunction
    
    private struct Data
        player p
        unit u
        real r
        
        real x
        real y
        
        real x2
        real y2
        
        real x3
        real y3
        
        real f
        
        // Changed all "Data" to "thistype", as "thistype" returns the struct name.
        static method create takes unit u returns thistype 
            local thistype d = thistype.allocate()
            
            set d.u = u
            set d.p = GetOwningPlayer(u)
        
            set d.x = GetUnitX(u)
            set d.y = GetUnitY(u)
        
            set d.f = GetUnitFacing(u)
        
            set d.x2 = d.x + INIT_DIST * Cos(d.f * bj_DEGTORAD) // Changed from function call to global.
            set d.y2 = d.y + INIT_DIST * Sin(d.f * bj_DEGTORAD) // You could set d.f to GetUnitFacing() * bj_DEGTORAD. But I don't think 
                                                                // it's that much if a problem.
            
            return d
        endmethod
    endstruct

    // You can actually inline the conditions with the actions.
    private function Conditions takes nothing returns boolean
        return GetSpellAbilityId() == 'A000'
    endfunction
    
    // Having the callback as a method in the struct is better encapsulation.
    private function CallBack takes nothing returns nothing
        local timer t = GetExpiredTimer()
        local Data d = GetTimerData(t)
        
        call d.destroy()
        call ReleaseTimer(t) // Why not just have the timer part of the struct?
    endfunction

    private function Actions takes nothing returns nothing
        local timer t // = NewTimer()
        local unit u  = GetTriggerUnit()
        local Data d  // = Data.create(u)
        
        static if (REQ_MT) then
            call GroupEnumUnitsInRange( ENUM_GROUP, GetUnitX(u), GetUnitY(u), MT_DIST, function filter) // Using the function directly.
            if FirstOfGroup(ENUM_GROUP) == null then
                call GroupClear( ENUM_GROUP )
                call BJDebugMsg( "Error: No Mortar Team Detected" )
                set u = null
                return //nothing // It's a simple "return". Nothing else.
            endif
        endif
        
        // You're declaring them but not using them as when no Mortar Team is found.
        set d = Data.create()
        set t = NewTimer()
        
        call PauseUnit(d.u, true)
        call SetTimerData(t, d)
        call TimerStart(t, CALLBACK, true, function CallBack)
        
        set t = null
        set u = null
    endfunction

    private function Init takes nothing returns nothing
        local trigger trig = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ( trig, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddCondition( trig, Condition( function Conditions ) )
        call TriggerAddAction( trig, function Actions )
    endfunction

endlibrary
 

Tyman2007

Ya Rly >.
Reaction score
74
hmm.. yeah I kindof wanted it to skip the remaining actions.. but I forgot that there's a function that does that :p thanks I guess for reminding me indirectly! :p
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top