Secondary Objective

From WiCWiki

Jump to: navigation, search


  • When you finished this lesson you will have your first secondary objective, one with a counter.

Secondary Objectives

A secondary objective is almost the same as a primary objective at least when it comes to code. According to our own WiC-rules a secondary will never make you lose a mission, they should always be voluntary. As with primary objectives you will see the secondary objectives in the objective browser, with a camera or a picture, with markers and text.


One difference is that the event string containing the “myDescription” variable won’t stay on the screen as the primary objectives does.


In this example we will use the DestroyAA secondary from the example map because it is an objective with a counter. A counter is not exclusive for secondary objective you can use it on primary objectives as well.

A counter is very useful when you have more than one thing that needs to be done in an objective. If you look at the image of the browser the myDescription contains a counter “(0/3)”. The counter is incremented for each completed task. This won’t be written in the juice file, it will be calculated from the python code.

When we want to change the counter, increase or decrease, we use the method AddToCounter like this.

mapvars.objTest.AddToCounter( 1 )

In our test map, europeTest in the secondary objective, we don’t use this. The main reason for that is that we remove the objectives sub marker each time an enemy dies. We use the method

RemoveSubMarker( aSubName, aTarget, aAutoCounter = False, aUnit = -1, aPlayerId = 1) (which we will cover soon in this chapter) instead with the flag aAutoCounter set to True. This means it will take care of the counters incensement itself. If you for example have a counter without sub markers it is a better idea to use the AddToCounter( 1 ).

The value you send in is how much you want to change the counter with; the value can be either positive or negative.

Every time the counter is incremented, you will see a new event string appear with the new values i.e. when you’ve killed the first AA the event string will look like this.


In the juice file it looks pretty much the same as the primary objective. The only thing that is different is that the secondary objective is listed between the “mySecondaryObjectives” curly brackets instead of “myPrimaryObjectives”.

    Objective DestroyAA
        myDescription "Destroy the AA."
        myLongDescription "To complete this objective you must destroy all three AA."
        myOptionalImage <empty>
        myDontShowInPOLFlag 0
        myOnClickPythonClientFunction ObjCamDestroyAA
        myOnClickPythonServerFunction <empty>
        myVisualisationText "Destroy the AA."

Secondary objectives in Python

As with primary objectives you should add a variable in the file.

This code should go in the file, for example in the EventNameSetup function.

mapvars.objDestroyAA = Objective( 'DestroyAA', None, 'secondary', 3 )

-The first parameter is the name you gave the objective in the juice file.

-The second parameter is the coordinates for the marker, but it can’t handle more than one target and we need three for this example so we will leave it empty for now and add markers in a while.

-The third parameter is what kind of objective it is and because it is a secondary objective, we’ll write ‘secondary’.

-The fourth and last parameter is the counter, in this case since there is 3 anti airs to be destroyed, so it is set to 3.

The next step is to add the secondary objective to make it active and visible. You do exactly as with primary objectives. To add it to an action queue it will look like this and it should be in the EventNameStart function.

queDestroyAA.AddObjective( mapvars. objDestroyAA )

If you don’t use the queue you add an objective like this.

mapvars. objDestroyAA.AddObjective()

Because we have a counter and we want to have objective markers on every AA. We add the objective markers like this. You can add the markers before or after the objective is added.

Add markers on the right places with a queue like this for example…

queDestroyAAStart.AddObjectiveMarker( mapvars.objDestroyAA, 1, 'areaAASpawn1' )
queDestroyAAStart.AddObjectiveMarker( mapvars.objDestroyAA, 2, 'areaAASpawn2' )
queDestroyAAStart.AddObjectiveMarker( mapvars.objDestroyAA, 3, 'areaAASpawn3' )

..or without queue.

mapvars.objDestroyAA.AddSubMarker( 1, 'areaAASpawn1' )
mapvars.objDestroyAA.AddSubMarker( 2, 'areaAASpawn2' )
mapvars.objDestroyAA.AddSubMarker( 3, 'areaAASpawn3' )

-If you use the queue the first parameter is which objective you are adding markers to.

-The second parameter if you use a queue or the first parameter if you don’t use a queue is a reference, a name or an ID number or whatever you like, as long as you know and you can trigger on it later, everyone is happy.

-The last parameter is the markers target. You can use almost whatever you like, an area, a tree, or a unit (but that is the units’ position “right now” so if it moves, the marker stays)

Trigger a secondary objective

As with primary objectives you can trigger a secondary objective on almost everything. In this example we trigger the secondary objectives event on when the player have fortified a command point. Feel free to trigger your secondary on anything you want, just make sure you have all areas, units and have added the objective before.

RE_OnCommandPointFortifiedEx( [ 'PP_Mansion1', 'PP_Mansion2' ], TEAM_NATO, 1, Action( PostEvent, 'DestroyAAStart' ), False, True ) 

How to fail or complete a secondary objective

To fail or complete a secondary objective works as with a primary objective. In this example we put the reactions in variables because we want to remove them if you fail the objective or things like that. In the code example here we’ve removed some of the unnecessary code from the example code files. Feel free to add or remove whatever you like.

Check out the objectives chapter if you are curious to know what ‘RemoveSubMarker’ really does behind the scenes.

mapvars.reactDestroyAAKilled1 = RE_OnEmptyGroup( mapvars.grpDestroyAA1, Action( mapvars.objDestroyAA.RemoveSubMarker, 1, True ) )   
mapvars.reactDestroyAAKilled2 = RE_OnEmptyGroup( mapvars.grpDestroyAA2, Action( mapvars.objDestroyAA.RemoveSubMarker, 2, True ) )    
mapvars.reactDestroyAAKilled3 = RE_OnEmptyGroup( mapvars.grpDestroyAA3, Action( mapvars.objDestroyAA.RemoveSubMarker, 3, True ) )    
queDestroyAAStart = ActionQueue( 'queDestroyAAStart' )
queDestroyAAStart.AddObjective( mapvars.objDestroyAA )

# Check if any AA has been killed before we received the objective. This is important. If 
# you don’t you might have created a serious show stopper because the objective won’t trigger until all the 
# AA’s are dead and the reaction won’t listen to already killed ones. 
queDestroyAAStart.AddFunction( PostGroupSize, mapvars.grpDestroyAA1 )
queDestroyAAStart.AddFunction( PostGroupSize, mapvars.grpDestroyAA2 )
queDestroyAAStart.AddFunction( PostGroupSize, mapvars.grpDestroyAA3 )
queDestroyAAStart.Execute( )

# When all three AA have been destroyed complete the objective and we’ll give the player #a free helicopter.
queDestroyAAComplete = ActionQueue( 'queDestroyAAComplete' )
queDestroyAAComplete.AddObjectiveCompleted( mapvars.objDestroyAA )
queDestroyAAComplete.AddFunction( allunits.PlayerAward )
queDestroyAAComplete.AddEventString( 'myNewUnits' )

# Create a reaction that waits for the objective class to post when all AA’s are dead.
RE_OnCustomEvent( mapvars.objDestroyAA.GetPostEvent(), Action( queDestroyAAComplete.Execute ) )

Check our test map, in the europeTest maps file for more code and more secondary objective examples.


Changed files in this chapter:


Changes in the file.

def RescueArtySetup( aKickStart = False ):

    [More code here.]

    mapvars.objRescueArty = Objective( 'RescueArty', 'areaArtySpawn', 'secondary' )   

    [More code here.]                           

def RescueArtyStart( ):

    [More code here.]

    queRescueArtyStart.AddMessageBox( 'e1_4', 104 )
    queRescueArtyStart.AddObjective( mapvars.objRescueArty )
    queRescueArtyStart.AddFunction( Delay, 30, Action( allunits.RescueArtyAttack ) )

    [More code here.]   

    queRescueArtyComplete.AddMessageBox( 'e1_5', 105 )
    queRescueArtyComplete.AddObjectiveCompleted( mapvars.objRescueArty )
    RE_OnCustomEvent( 'RescueArtyRuDead',[ Action( RemoveReaction, mapvars.reactRescueArtyFail ), Action( queRescueArtyComplete.Execute)] )

    [More code here.]

    queRescueArtyFail.AddMessageBox( 'e1_6', 106 )
    queRescueArtyFail.AddObjectiveFailed( mapvars.objRescueArty )
    RE_OnCustomEvent( 'RescueArtyDead', [ Action( RemoveReaction, mapvars.reactRescueArtyComplete ), Action( queRescueArtyFail.Execute ) ] )

    [More code here.]

Changes in the file.

#-------------------------  RescueArty  -------------------------   

objRescueArty = None

[More variables here.]

Changes in the europeTest.juice file.

If you open europeTest.juice in the ‘JuiceMaker’ tool you will find mySecondaryObjectives under mySinglePlayerData -> mySinglePlayerMissionStats -> mySecondaryObjectives.

    Objective RescueArty
        myDescription "Keep the Nato artillery alive."
        myLongDescription "Keep the Nato artillery alive.\n\nTo complete this objective you must destroy the Russian attacker on the artillery.\\You will fail the mission if the Russians manage to destroy the artillery."
        myOptionalImage <empty>
        myDontShowInPOLFlag 0
        myOnClickPythonClientFunction ObjCamRescueArty
        myOnClickPythonServerFunction <empty>
        myVisualisationText "Keep the Nato artillery alive."
Chapter 11b: The Unittypes List < > Chapter 13: Tactical Aid
Personal tools
User Created Content