Mission Objectives

This page describes how to use mission objectives in missions, including defining them in the Sequence mission table subscript and using functions to update them.

## Mission Table Sequence subscript tables

### missionObjectiveDefine

The `missionObjectiveDefine` table defines the precise details about objectives, such as objective markers for areas, NPCs and gimmicks, iDroid VI photos, subgoals, enemy routes on the map, target area CP music, mission tasks and forced spy search on specific enemy soldiers. An objective can also simply be an empty table, as a dummy objective that can be the parent of another objective in the objective tree, so when the parent is shown, its child objective that does have something like a marker will be disabled.

#### packLabel

The `packLabel` parameter in the objective will restrict the objective from being updated if the current packLabel isn't the one specified in it.

```
this.missionObjectiveDefine = {
    mission\_target\_cp = {
		packLabel = { "afterSahelanTestDemo" },
        --...
    },
}

```

#### announceLog

The `announceLog` parameter in the objective will print a message in the announce log. The parameter is not a `langId`, instead it uses a string key of a `langId` value string from `TppUI`'s `ANNOUNCE_LOG_TYPE` table.

```
this.missionObjectiveDefine = {
	announce\_eliminateTarget = {
		announceLog = "eliminateTarget",
	},
}

```

#### gameObjectName and gimmickId

The `gameObjectName` or `gimmickId` parameters will place a marker on the given game object or gimmick with the following parameters as arguments using the function `TppMarker.Enable(gameObjectId,...)`. The `gameObjectName` can be a TppMarkerLocatorSystem game object or an NPC like a soldier or a hostage, and if you're using a `gimmickId`, it will be the name of the gimmick in the `mvars.gim_identifierParamTable` table, meaning either a vanilla gimmick set up in the location's scripts, or a custom one, though you'll have to push to that table yourself somehow.

```
this.missionObjectiveDefine = {
    default\_area\_slopedTown = {
        --EITHER:
        --Name of the marker, soldier, etc. gameobject
        gameObjectName = "s10020\_marker\_slopedTown",
        --OR:
        --Name of the gimmick in mvars.gim\_identifierParamTable
        gimmickId = "lab\_cntn001",

        --TppMarker.Enable arguments:
        visibleArea = 5, --Marker's area size, 0 is default if unassigned
        goalType = "none", --Goal type, "none" is default if unassigned
        viewType = "all", --Visible on map or game world or both, "map" is default if unassigned
        randomRange = 3, --Level of random area, randomized offset, 0 by default if unassigned
        setImportant = true, --Yellow/important marker, will make the target marker visible in the world
        setNew = true, --Mark as a new marker on the map or not
        langId = "marker\_info\_mission\_targetArea", --Lang id of the marker
        goalLangId = "marker\_info\_mission\_targetArea", --Lang id of the goal
        mapRadioName = "s0020\_mprg0020", --Radio label on the map marker
        setInterrogation = true, --Interrogation bool, true by default?
    },
}

```

#### photoId

The `photoId` parameter will add a photo to the iDroid mission info section. Its additional parameters are a little backwards, though: if `addFirst` is true, it will use the vertical photo. If `addSecond` is false, it will use a horizontal photo. There is also a seemingly unused (non-functional, orphaned) `isComplete` parameter.

The photo index is generated into this `.ftex` texture path:

`"/Assets/tpp/ui/texture/Photo/tpp/[%05d missionCode]]/mb_photo_[%05d missionCode]_[%03 photoId].ftex"`

Add `"_1.ftex"` as a suffix for the vertical photo texture version. The generated example would be: `"/Assets/tpp/ui/texture/Photo/tpp/10020/mb_photo_10020_010.ftex"`

```
this.missionObjectiveDefine = {
	default\_photo\_target\_a = {
		photoId	= 10, --Photo index:
		addFirst = true,--If true, use a vertical photo. False if unassigned
        addSecond = false, --If false, use a horizontal photo. Confusing, I know. False if unassigned
        isComplete = false, --Unused flag that doesn't do anything
		photoRadioName = "s0093\_mirg0010", --Photo radio label
	},
}

```

#### hudPhotoId

The `hudPhotoId` parameter will show the previously defined `photoId`, the vertical version of it, on the right side of the screen.

```
this.missionObjectiveDefine = {
	hud\_10 = {
        --Vertical photo index to show on the screen when the objective is shown
		hudPhotoId = 10,
	},
}

```

#### subGoalId

The `subGoalId` parameter will change the subgoal `langId` and if the subgoal is above 0, print the new subgoal in the announcement log.

The subgoal index is generated into this `langId`:

`"subgoal_mission_[%02 locationCode]_[%05 missionCode]_[%02 subGoalId]"`

An output example would be:

`"subgoal_mission_10_10020_02"`

```
this.missionObjectiveDefine = {
	on\_subGoal\_missionComplete = {
        --The subgoal index to use when the objective is shown.
		subGoalId = 2,
	},
}

```

#### showEnemyRoutePoints

The `showEnemyRoutePoints` parameter will show on the map a route made out of the given list of `Vector3` coordinates. Strangely, the line is drawn in backwards order from the ones listed, as in the first point will be the one that has an arrow pointing outward.

```
this.missionObjectiveDefine = {
	route\_vip\_field\_arrival = {
        --Show a red route on the map
		showEnemyRoutePoints = {
            groupIndex = 0, --Route index, starts from 0
			width = 200.0, --Route width in meters
            langId = "marker\_target\_forecast\_path", --Lang id for the route
			radioGroupName = "f1000\_mprg0260", --Map radio label for the route
            --Coordinates starting from end arrow (the first point will be pointed at by the path)
			points={
				Vector3( 588.3,0.0,1163.0 ),
				Vector3( 739.0,0.0,1212.0 ),
				Vector3( 929.0,0.0,1261.7 ),
				Vector3( 1161.8,0.0,1408.5 ),
				Vector3( 1247.8,0.0,1733.9 ),
				Vector3( 956.9,0.0,1970.4 ),
				Vector3( 728.8,0.0,1940.4 ),
				Vector3( 455.6,0.0,2165.6 ),
			}
		},
	},
}

```

#### targetBgmCp

The `targetBgmCp` parameter will enable the Target Area Infiltration track to play when infiltrating the specified outpost.

```
this.missionObjectiveDefine = {
    --Enable the Target Area Infiltration track to play for this CP gameobject
	mission\_target\_cp = {
        --CP gameobject name
		targetBgmCp = "afgh\_sovietBase\_cp",
	},
}

```

#### missionTask

The `missionTask` parameter will modify the mission task list. A mission can only have 8 tasks - 0 to 7. A task can also be hidden by default to avoid telling the player what they will have to do later on.

Here's an example of two `missionTask` parameter objectives that first define a normal objective that's shown from the start, and another that clears it:

```
this.missionObjectiveDefine = {
    --Objective example: shown by default
    --Show objective to define the mission task.
	default\_missionTask\_00 = {
        missionTask = {
            --Task index, 0 to 7. Include this index in the external missionTaskList table.
            taskNo = 0,
            --New yellow marker boolean.
            isNew = true,
            --Task completion boolean.
            isComplete = false,
            --Boolean for whether to hide the task or not.
            isFirstHide = false
        },
    },
    --Show objective to clear the mission task.
	clear\_missionTask\_00 = {
        missionTask = {
            taskNo = 0,
            isNew = true,
            isComplete = true
        },
    },
}

```
And here's an example of a set of `missionTask`-using objectives that use a task that's hidden by default, but then is shown, and then completed.

```
this.missionObjectiveDefine = {
    --Objective example: hidden by default
    --Show objective to define the hidden task.
	default\_missionTask\_01 = {
        missionTask = {
            taskNo = 1,
            isNew = true,
            isComplete = false,
            isFirstHide = true
        },
    },
    --Show objective to show the hidden task.
	open\_missionTask\_01 = {
        missionTask = {
            taskNo = 1,
            isNew = true,
            isComplete = false,
            isFirstHide = false
        },
    },
    --Show objective to clear the mission task.
	clear\_missionTask\_00 = {
        missionTask = {
            taskNo = 1,
            isNew = true,
            isComplete = true
        },
    },
}

```

#### spySearch

The `spySearch` parameter will force enable the Enemy FOM marker for an enemy soldier, even if they're far away, set an important yellow New mark on it, and change the marker's `langId`.

```
this.missionObjectiveDefine = {
	route\_vip\_field\_arrival = {
        --Force enable the FOM marker on an enemy soldier on the map
        spySearch = {
            --The soldier locator's name
            gameObjectName = "sol\_vip\_field",
            --Yellow new marker bool
            isNew = true,
            --Lang id for the FOM marker
            langId = "marker\_info\_mission\_target",
        },
    },
}

```

### missionObjectiveTree

The missionObjectiveTree table defines a table of priorities for the previously defined objectives. In short, when an objective is shown, all its children in the tree will be disabled, removed and hidden. Not all objectives have to be on the tree, because not all of them have to be hidden by another marker eventually. The simplest example is often used in `missionTask` objectives:

```
this.missionObjectiveTree = {
	clear\_missionTask\_00 = {
		default\_missionTask\_00 = {},
	},
	clear\_missionTask\_01 = {
		open\_missionTask\_01 = {
			default\_missionTask\_01 = {},
		},
	},
}

```
Here we have two task branches: the deeper you go into them, the earlier the objective is. The `default` one defines the objective as not yet cleared, and the `clear` one updates it to be marked as cleared. In the second one, an in-between is introduced: since the `default` one defines it as being hidden by default, the `open` one shows it, and afterward, the `clear` one marks it as clear. With markers, it looks often like this:

```
this.missionObjectiveTree = {
	missionClear = {
		marker\_target = {
			marker\_area\_targetVagueLocationMarker = {
				marker\_area\_targetOutpostMarker = {},
			},
		},
	},
}

```
The deepest one is the vaguest marker, and the one we are given in this hypothetical mission, `marker_area_targetOutpostMarker`, marking the entire outpost our target is in. The next level is `marker_area_targetVagueLocationMarker`, a location within the outpost, but not as precise as it would be if you were to mark the target yourself directly, which is exactly what's up next, `marker_target` - we've marked the target directly. Finally, the highest outer level is `missionClear`, an objective with no markers. We have cleared the mission after eliminating or rescuing the target, so we no longer need any of the markers we had before.

The reason we have this tree is because of how much there is to disable or remove from our UI when we've reached the next step in the mission. Since we can also skip some steps, this is useful too.

It can get a bit more complex with multiple objectives with the same children:

```
this.missionObjectiveTree = {
	rv\_missionClear = {
		get\_s10093\_Container\_A = {
			add\_s10093\_Container\_A = {
				add\_lab\_enemy\_map = {
					default\_area\_lab = {},
				},
			},
		},
		get\_s10093\_Container\_B = {
			add\_s10093\_Container\_B = {
				add\_lab\_enemy\_map = {
					default\_area\_lab = {},
				},
			},
		},
		default\_photo\_target\_a	= {},
		default\_photo\_target\_b	= {},
		target\_area\_cp	= {},
		intermediate\_target01 = {},
	},
}

```
The objectives `default_area_lab` and `add_lab_enemy_map` are repeated here, because showing either `add_s10093_Container_A` or `add_s10093_Container_B` should remove those markers. A simplified example would be this:

```
this.missionObjectiveTree = {
    AreaMarker\_A\_ClearVersion = {
        default\_mission\_intel = {},
    },
    AreaMarker\_B\_ClearVersion = {
        default\_mission\_intel = {},
    },
    AreaMarker\_C\_ClearVersion = {
        default\_mission\_intel = {},
    },
    missionTask\_1\_RecoverTarget\_clear = {
        missionTask\_1\_RecoverTarget ={},
        AreaMarker\_A\_ClearVersion = {},
        AreaMarker\_B\_ClearVersion = {},
        AreaMarker\_C\_ClearVersion ={},
        default\_mission\_intel = {},
    },
}

```
Here, the `default_mission_intel` marker is hidden if we get any of the `A`, `B` or `C` `AreaMarkers`. All three are hidden if the mission task is cleared. You can also have it be very simplistic and not bother at all with big trees, and use something like this for everything:

```
this.missionObjectiveTree = {
	clear\_Area\_hosTarget\_flee = {
		Area\_hosTarget\_flee = {},
	},
	clear\_Area\_hosTarget\_convoy = {
		Area\_hosTarget\_convoy = {},
	},
}

```
The `clear_` objectives are actually empty in the definition table; they're there simply to hide their children on this tree.

### missionObjectiveEnum

The missionObjectiveEnum enum is used by the game's code to index around objectives instead of using their names. Every objective in the missionObjectiveDefine table needs to be here.

This is an example of what the game does:

```
this.missionObjectiveEnum = Tpp.Enum{
	"default\_mission\_intel",
	"default\_viewPoint",
	"Arrived\_viewPoint",
    --...
}

```
...and more. But you can completely ignore this weird thing and instead use this method that incredibly easily automates it from a previously defined missionObjectiveDefine.

```
this.missionObjectiveEnum = {}
for objectiveName, objectiveTable in pairs(this.missionObjectiveDefine) do
	if Tpp.IsTypeString(objectiveName) then
		table.insert(this.missionObjectiveEnum,objectiveName)
	end
end
this.missionObjectiveEnum=Tpp.Enum(this.missionObjectiveEnum)

```

## Objective functions

### TppMission.UpdateObjective

The function `TppMission.UpdateObjective(...)` updates the current objectives, with possible parameters like radio calls before or after the objective is updated. There is also an `options` parameter, but none of them seem to do anything.

A simple update of objectives would be this: we're simply defining the mission tasks with these objectives.

```
TppMission.UpdateObjective{
    objectives = {
        "default\_missionTask\_00",
        "default\_missionTask\_01",
        "default\_missionTask\_02",
        "default\_missionTask\_03",
        "default\_missionTask\_04",
    },
}

```
However, even if you want to update one objective, you have to use it in a table.
If we want to update the objective after a specified radio label plays, we can do this:

```
TppMission.UpdateObjective{
    objectives = {
        "default\_area\_field"
    },
    radio = {
        radioGroups = "s0036\_rtrg0010",
    },
}

```
You can also use a table of multiple radio labels as the `radioGroups`, and also use `radioOptions` the same way we can use the second argument in `TppRadio.Play()` for parameters for radio playback, like `delayTime` or `priority`.

```
TppMission.UpdateObjective{
    objectives = {
        "default\_area\_clifftown"
    },
    radio = {
        radioGroups = {
            "s0044\_rtrg0010",
            "s0044\_rtrg0020"
        },
        radioOptions = {
            priority = "strong"
        },
    },
}

```
We can also use `radioSecond` to play a `radioGroups` of either one or multiple radio labels after the objective has already been updated. `radioOptions` applies there as well.

```
TppMission.UpdateObjective{
    objectives = {
        "default\_area\_enemyBase"
    },
    radio = {
        radioGroups = "s0033\_rtrg0010",
    },
    radioSecond = {
        radioGroups = "s0033\_rtrg0011",
    },
}

```