HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Need help fixing a trigger

08-30-2007, 10:00 PM#1
Karawasa
An unexpected problem occurred while modifying an event for a trigger. Before going into details, let me first post the code.

Collapse JASS:
//Implementation: *copy dummy unit over, and make a passive ability and add it to units so they know they get it(though this code does not)
//                *paste this code into a trigger called Meteor
//                *configure the options given, as well as alter dummy unit to your liking(height, size, projectile for attack, etc.) and viola!
//Documentation: This should work a whole lot better, most of the config is in the dummy unit itself, not here

scope Meteor

globals
    //config options
    private constant integer unit1_id = 'h01B' //tower 1 id
    private constant integer unit2_id = 'h02A' //tower 2 id
    private constant integer dum1_id = 'e006' //dummy unit 1 id
    private constant integer dum2_id = 'e005' //dummy unit 2 id
    private constant real sub_int = 1. //interval to create meteors at (how often they occur in seconds)
    private constant real area = 500. //area in which the meteor may fall to, around the tower

    //needed variables
    private timer subT = CreateTimer()
    private group mainG = CreateGroup()
    private boolean timer_on = false        
endglobals

//get correct dummy
private function get_dummy takes integer towerid returns integer
    if towerid==unit1_id then
        return dum1_id
    else
        return dum2_id
    endif
endfunction

//create meteor for all available towers  
private function Meteor_Create takes nothing returns nothing
    local unit u = GetEnumUnit()
    local integer id = get_dummy(GetUnitTypeId(u))
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    local unit meteor = CreateUnit(GetOwningPlayer(u),id,x,y,0.)
    
    call IssuePointOrder(meteor,"attackground",x+GetRandomReal(50.,area)*Cos(GetRandomReal(0.,360.)*bj_DEGTORAD),y+GetRandomReal(50.,area)*Sin(GetRandomReal(0.,360.)*bj_DEGTORAD))
    call UnitApplyTimedLife(meteor,'BTLF',1.)
    
    set u = null
    set meteor = null        
endfunction
//remove dead towers/allow meteors to be created for alive ones
private function Meteor_Actions2 takes nothing returns nothing    
    //call Msg("Runnin",Player(0))
    if FirstOfGroup(mainG)!=null then
        //call Msg("Go",Player(0))
        call ForGroup(mainG,function Meteor_Create)
    else
        call PauseTimer(subT)
        set timer_on = false
    endif 
endfunction 
//remove dead towers from main group
function Meteor_Death_Conditions takes nothing returns boolean
    local unit u = GetTriggerUnit()
    
    if GetUnitTypeId(u)==unit1_id or GetUnitTypeId(u)==unit2_id then
        //call Msg("Removed",Player(0))
        call GroupRemoveUnit(mainG,u)
    endif
    
    set u = null
    return false
endfunction  
//add entering towers to check
function Meteor_Conditions takes nothing returns boolean
    return GetUnitTypeId(GetTriggerUnit())==unit1_id or GetUnitTypeId(GetTriggerUnit())==unit2_id
endfunction
function Meteor_Actions takes nothing returns nothing
    //call Msg("Added",Player(0))
    call GroupAddUnit(mainG,GetTriggerUnit())
    if timer_on==false then
        call TimerStart(subT,sub_int,true,function Meteor_Actions2)
        set timer_on = true
    endif         
endfunction

endscope

//===========================================================================
function InitTrig_Meteor takes nothing returns nothing
    local trigger trig = CreateTrigger()
    
    //call TriggerRegisterEnterRectSimple(trig,bj_mapInitialPlayableArea)
    call TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_UNIT_UPGRADE_FINISH)
    call TriggerAddCondition(trig,Condition(function Meteor_Conditions)) 
    call TriggerAddAction(trig,function Meteor_Actions)
    
    set trig = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_UNIT_DEATH)
    call TriggerAddCondition(trig,Condition(function Meteor_Death_Conditions))
    
    set trig = null  
endfunction

You will notice that this was the event first used:

Collapse JASS:
call TriggerRegisterEnterRectSimple(trig,bj_mapInitialPlayableArea)

It was changed because units that enter play via an upgrade do not fire this trigger, thus, it didn't work with the towers it should have. This is what it became:

Collapse JASS:
call TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_UNIT_UPGRADE_FINISH)

What is the problem? When the appropriate unit finishes upgrading, the game fatal errors with message a brief moment after (i.e. when the trigger would fire).

Any help would be appreciated.
08-31-2007, 12:22 AM#2
Pyrogasm
Mightn't it be that the functions should be public functions? It seems to me that functions in scopes that aren't private are declared as public instead of just having no public/private keyword.

Additionally, it would be better to just make them all private functions and then just reference them correctly:
Collapse JASS:
//Implementation: *copy dummy unit over, and make a passive ability and add it to units so they know they get it(though this code does not)
//                *paste this code into a trigger called Meteor
//                *configure the options given, as well as alter dummy unit to your liking(height, size, projectile for attack, etc.) and viola!
//Documentation: This should work a whole lot better, most of the config is in the dummy unit itself, not here

scope Meteor

globals
    //config options
    private constant integer unit1_id = 'h01B' //tower 1 id
    private constant integer unit2_id = 'h02A' //tower 2 id
    private constant integer dum1_id = 'e006' //dummy unit 1 id
    private constant integer dum2_id = 'e005' //dummy unit 2 id
    private constant real sub_int = 1. //interval to create meteors at (how often they occur in seconds)
    private constant real area = 500. //area in which the meteor may fall to, around the tower

    //needed variables
    private timer subT = CreateTimer()
    private group mainG = CreateGroup()
    private boolean timer_on = false        
endglobals

//get correct dummy
private function get_dummy takes integer towerid returns integer
    if towerid==unit1_id then
        return dum1_id
    else
        return dum2_id
    endif
endfunction

//create meteor for all available towers  
private function Meteor_Create takes nothing returns nothing
    local unit u = GetEnumUnit()
    local integer id = get_dummy(GetUnitTypeId(u))
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    local unit meteor = CreateUnit(GetOwningPlayer(u),id,x,y,0.)
    
    call IssuePointOrder(meteor,"attackground",x+GetRandomReal(50.,area)*Cos(GetRandomReal(0.,360.)*bj_DEGTORAD),y+GetRandomReal(50.,area)*Sin(GetRandomReal(0.,360.)*bj_DEGTORAD))
    call UnitApplyTimedLife(meteor,'BTLF',1.)
    
    set u = null
    set meteor = null        
endfunction
//remove dead towers/allow meteors to be created for alive ones
private function Meteor_Actions2 takes nothing returns nothing    
    //call Msg("Runnin",Player(0))
    if FirstOfGroup(mainG)!=null then
        //call Msg("Go",Player(0))
        call ForGroup(mainG,function Meteor_Create)
    else
        call PauseTimer(subT)
        set timer_on = false
    endif 
endfunction 
//remove dead towers from main group
private function Meteor_Death_Conditions takes nothing returns boolean
    local unit u = GetTriggerUnit()
    
    if GetUnitTypeId(u)==unit1_id or GetUnitTypeId(u)==unit2_id then
        //call Msg("Removed",Player(0))
        call GroupRemoveUnit(mainG,u)
    endif
    
    set u = null
    return false
endfunction  
//add entering towers to check
private function Meteor_Conditions takes nothing returns boolean
    return GetUnitTypeId(GetTriggerUnit())==unit1_id or GetUnitTypeId(GetTriggerUnit())==unit2_id
endfunction
private function Meteor_Actions takes nothing returns nothing
    //call Msg("Added",Player(0))
    call GroupAddUnit(mainG,GetTriggerUnit())
    if timer_on==false then
        call TimerStart(subT,sub_int,true,function Meteor_Actions2)
        set timer_on = true
    endif         
endfunction

endscope

//===========================================================================
function InitTrig_Meteor takes nothing returns nothing
    local trigger trig = CreateTrigger()
    
    //call TriggerRegisterEnterRectSimple(trig,bj_mapInitialPlayableArea)
    call TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_UNIT_UPGRADE_FINISH)
    call TriggerAddCondition(trig,Condition(function Meteor_Meteor_Conditions)) 
    call TriggerAddAction(trig,function Meteor_Meteor_Actions)
    
    set trig = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_UNIT_DEATH)
    call TriggerAddCondition(trig,Condition(function Meteor_Meteor_Death_Conditions))
    
    set trig = null  
endfunction
08-31-2007, 09:40 PM#3
Karawasa
Your code does not save, is it suitable for vJASS?

At any rate, I don't think it is anything related to that. The trigger worked fine when it was event - unit enters playable area. What is causing it to crash is the change in events, but I don't get why.
08-31-2007, 10:15 PM#4
moyack
Hmm Pyro, it seems that you're testing your luck :)

You set private to all the functions, so they only will work inside the scope. Because Meteor_Death_Conditions and Meteor_Actions are needed outside of the scope, they must be public or normal functions. I suggest to make them public just for readability.

@Karawasa: My suggestions:
  • If you use scopes, you can shorten the functions names by removing the prefix meteor, the scopes will manage that automatically.

  • Set the trigger functions as public, I suggest this way:
    Collapse JASS:
    scope Meteor
    // the other code goes here. Check the parts where are higlighted in yellow.
    
    //remove dead towers/allow meteors to be created for alive ones
    private function Actions2 takes nothing returns nothing    
        //call Msg("Runnin",Player(0))
        if FirstOfGroup(mainG)!=null then
            //call Msg("Go",Player(0))
            call ForGroup(mainG,function Meteor_Create)
        else
            call PauseTimer(subT)
            set timer_on = false
        endif 
    endfunction 
    
    //remove dead towers from main group
    public function Death_Conditions takes nothing returns boolean
        local unit u = GetTriggerUnit()
        
        if GetUnitTypeId(u)==unit1_id or GetUnitTypeId(u)==unit2_id then
            //call Msg("Removed",Player(0))
            call GroupRemoveUnit(mainG,u)
        endif
        
        set u = null
        return false
    endfunction  
    
    //add entering towers to check
    public function Conditions takes nothing returns boolean
        return GetUnitTypeId(GetTriggerUnit())==unit1_id or GetUnitTypeId(GetTriggerUnit())==unit2_id
    endfunction
    
    public function Actions takes nothing returns nothing
        //call Msg("Added",Player(0))
        call GroupAddUnit(mainG,GetTriggerUnit())
        if timer_on==false then
            call TimerStart(subT,sub_int,true,function Actions2)
            set timer_on = true
        endif         
    endfunction
    
    endscope
    
    //===========================================================================
    function InitTrig_Meteor takes nothing returns nothing
        local trigger trig = CreateTrigger()
        
        //call TriggerRegisterEnterRectSimple(trig,bj_mapInitialPlayableArea)
        call TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_UNIT_UPGRADE_FINISH)
        call TriggerAddCondition(trig,Condition(function Meteor_Conditions)) // <= looks nicer :) 
        call TriggerAddAction(trig,function Meteor_Actions) // <= looks nicer :)
        
        set trig = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_UNIT_DEATH)
        call TriggerAddCondition(trig,Condition(function Meteor_Death_Conditions)) // <= looks nicer :)
        
        set trig = null  
    endfunction

  • If the trigger is not working, I suggest to do the following:
    • Because the failure was when you changed the event type, copy your jass code in notepad.
    • Create a new trigger or delete the current one and redo it.
    • In GUI, set the event with the one you require
    • Convert it to custom text so you can modify the jass code.
    • Adapt it with the useful parts of your previous code and test it.

I hope it helps to solve your problem :)
09-01-2007, 01:14 AM#5
Pyrogasm
Oh... fuck.

I was close; I thought you could reference private functions as long as you prefixed them with the scope name... but apparently you must do it to public functions and it can't be done to privates.

Dur.
09-02-2007, 01:35 AM#6
Karawasa
Neither me nor emjlr3 can figure out why it crashes with the changed event. Nothing in the code stands out. Again, any help would be appreciated.
09-02-2007, 02:05 AM#7
Rising_Dusk
I have a feeling that the upgrade event may fire when you upgrade something like "Iron Swords" upgrades, not when you upgrade structures to new structures.

Try using EVENT_PLAYER_UNIT_CONSTRUCT_FINISH for the event and tell me what happens.
09-02-2007, 02:18 AM#8
Karawasa
I tried the event, it doesn't crash, but it doesn't do anything. I'm pretty sure the event I was using is correct, I believe you are thinking of:

EVENT_PLAYER_UNIT_RESEARCH_FINISH
09-02-2007, 08:12 PM#9
emjlr3
im just going to make it work differently, thnx for the help with names Moyack, it will help me down the road

still no idea why it crashes..., maybe ill try Grim to see the last function call...