Objectives: Difference between revisions

From The DarkMod Wiki
Jump to navigationJump to search
No edit summary
merged in information from Documentation Forum
Line 1: Line 1:
{{Original_Reference|Ishtvan|4121}} ''additions by greebo''
{{Original_Reference|Ishtvan|4121}} ''additions by greebo''


= Overview =
The objectives system exists to determine when the player has completed the mission. At the highest level, a mission consists of a list of objectives to be completed and boolean logic to determine when the mission has succeeded or failed based on which of the objectives are complete. At the objective level, an objective consists of individual components and boolean logic to determine when the objective is completed or failed. At the component level, each component has a type, a specifier, and arguments. These will be explained fully in the components section.
A mapper may add on objectives by setting key/values on a [[target_tdm_addobjectives]] entity and triggering it. If you want to add objectives at the very beginning of the map, put in a target_addobjectives and put that entity in as a target of the [[worldspawn]]. The worldspawn will trigger it on map start.


Objectives consist of overall objectives, objective components, and boolean relationships for failure and success. A map can have any number of overall objectives, and each objective can have any number of components.
= Mission =
Objectives are stored by entities named [[target_tdm_addobjectives]]. When triggered, these entities add objectives to the mission based on their spawnargs. These target entities may be triggered at any time to add objectives during the mission. Typically a target_addobjectives is triggered at mission start by [[worldspawn]] to set up the initial objectives.


== Example ==
Spawnargs governing mission level behavior may be entered on any target_addobjectives. Non-empty spawnargs will be overwritten by the most recently triggered target_addobjectives (FM authors may want to do this if they add an objective later on and want to change the mission success logic to include that objective, for example). The following is a list of the mission-level spawnargs and what they mean:
Objective 1 text: ''"Kidnap Benny and get out to the streets"''


'''Objective 1 Components:'''
== Success/Failure Logic ==
# Benny is KO'd
By default, all mandatory objectives need to be completed for mission success. However, it's possible to define a custom success and failure logic string on an objective entity. Be sure to have this addobjectives entity active at map start so that the logic is parsed right at map load.
# Benny is at the map exit
# Player is at the map exit
# NOT( Benny is dead )


'''Boolean relationship for Obj. 1 COMPLETION:'''
=== Default Logic ===
1 AND 2 AND 3 AND 4
*;<tt>mission_logic_success</tt> (string)
:A string of boolean logic applied to individual objective states to determine if the mission succeeds. AND, OR, NOT and parenthesis are available. The FM author can construct strings using these and the integer index for an objective. For example: "1 OR (NOT(2) AND 3)" would complete the mission if either objective 1 is true, or if 2 is false and 3 is true. By default, a mission succeeds when all mandatory objectives are completed.


'''Boolean relationship for Obj. 1 FAILURE:'''
*;<tt>mission_logic_failure</tt> (string)
NOT(4) (If Benny is dead we can't kidnap him alive)
:Boolean logic applied to individual objective component states to determine if the mission has failed. By default, if any mandatory objective fails, the mission fails.


= Objective Attributes and Spawnargs =
=== Difficulty Dependent Logic ===
The above spawnargs apply to all difficulty levels. It's of course possible to override this default for a given difficulty level, by setting these spawnargs. The index N is referring to the difficulty level number (starting from 0 = Easy):
 
*;<tt>mission_logic_success_diff_N</tt> (string)
:Defines the success logic for the difficulty level N (override the default logic), e.g. "1 AND 2 AND 3".
*;<tt>mission_logic_failure_diff_N</tt> (string)
:Defines the failure logic for the difficulty level N (override the default logic). When this condition is fulfilled, the mission has failed.
 
If specific logic is not specified for a certain difficulty level, the default spawnargs (without _diff_*) will be used.
 
= Objectives =
Objectives added by the target_addobjectives each have a unique integer index, starting with objective 1, the first objective. The spawnargs associated with an objective are prefixed in the following manner:
obj<objective index>_<spawnarg name>
Example: ''obj3_desc''
 
The spawnargs (minus prefix) and meanings for objective attributes are listed below. Each objective also includes a list of components and their attributes, which will be covered in the next section.


*;<tt>objN_desc</tt> (string)  
*;<tt>objN_desc</tt> (string)  
:The description of this objective. This is used to display the objective in the GUI - the user will never see the objective number, only this string.
:The description of this objective. This is used to display the objective in the GUI - the user will never see the objective number, only this string. The default value is an empty string.


*;<tt>objN_state</tt> (int) Defines the state of the objective at map start.  
*;<tt>objN_state</tt> (int) Defines the state of the objective at map start.  
:'''Possible Objective States:'''
:'''Possible Objective States:'''
:* OBJ_INCOMPLETE = 0
:* 0 = OBJ_INCOMPLETE
:* OBJ_COMPLETE = 1
:* 1 = OBJ_COMPLETE
:* OBJ_FAILED = 2
:* 2 = OBJ_FAILED
:* OBJ_INVALID = 3
:* 3 = OBJ_INVALID
:Code defaults to 0.
:Code defaults to 0 = incomplete.


*;<tt>objN_mandatory</tt> (1/0)  
*;<tt>objN_mandatory</tt> (1/0)  
:Set to 0 for optional objective that doesn't fail the mission if you fail it. Code defaults to 1.
:Set to 0 for optional objective that doesn't fail the mission if you fail it. Objective must be completed to complete the mission if 1. Code defaults to 1.


*;<tt>objN_irreversible</tt> (1/0)  
*;<tt>objN_irreversible</tt> (1/0)  
Line 41: Line 53:


*;<tt>objN_ongoing</tt> (1/0)  
*;<tt>objN_ongoing</tt> (1/0)  
:Use this for objectives that should remain successful, but won't be checked off until the end of the mission. For example, "don't blackjack more than two people" is successful at the start of the mission, because you haven't blackjacked anyone yet, but when you KO one person and the KO callback is made to the objective system, and the system then sees that only one person has been KO'd, the system needs some way of knowing not to say "Objective Complete" when you KO that first person, i.e., that this is an ongoing objective. Code defaults to 0.
:If true, this objective is not marked as complete and the player is not informed that it's complete until the end of the mission. Typically used for "do not kill" type objectives, because technically they would be complete right from the beginning, but we don't want to mark them off or tell the player they're complete right at the beginning. Could also be used for "have some item with you when you complete the mission." Code defaults to 0.


*;<tt>objN_visible</tt> (1/0)  
*;<tt>objN_visible</tt> (1/0)  
:Whether the objective appears in the player's Objectives GUI. Use invalidated and hidden objectives to queue up objectives for later, or hidden but valid objectives as anothe way of scripting events when the player does a certain thing, since objectives can launch an arbitrary script after they're completed. Code defaults to 1.
:Whether the objective appears in the player's Objectives GUI. Use invalidated and hidden objectives to queue up objectives for later, or hidden but valid objectives as another way of scripting events when the player does a certain thing, since objectives can launch an arbitrary script after they're completed. Code defaults to 1.


*;<tt>objN_difficulty</tt> (integer)
*;<tt>objN_difficulty</tt> (integer)
:This specifies the difficulty level this objectives applies to. When this spawnarg is set (e.g. '''"obj2_difficulty" "1"'''), this objective is only visible at difficulty level 1 (="Hard", remember that difficulty level numbers start with 0). Leave this empty to let the objective apply to all levels.
:Space delimited list of difficulty levels that should include this objective. For example, "2 3" would enable this objective at difficulty levels 2 and 3, but not for other difficulty levels. Default value is empty - the objective applies to all difficulty levels.
:''Note:'' When the objective is not active for a given difficutly, it is invalidated and hidden, but it still exists, so the numbering of the next objective should still increase by 1. E.g., objective 5 only appears on hard difficulty, but you still have to call the next objective objective 6, you can't call it objective 5 only appearing on easy or medium difficulty.


*;<tt>objN_enabling_objs</tt> (space-delimited integers)  
*;<tt>objN_enabling_objs</tt> (space-delimited integers)  
:This is a list of other objectives that must first be completed before this objective can be completed. For example, we shouldn't mark "objective complete" for exiting the mission until all the other mission goals have been completed. An example value for this spawnarg would be "4 6" to let this objective depend on objectives #4 and #6.
:This is a list of objectives which must be completed ''before'' this objective can be completed. For example, we shouldn't mark "objective complete" for exiting the mission until all the other mission goals have been completed. An example value for this spawnarg would be "4 6" to let this objective depend on objectives #4 and #6.


*;<tt>objN_script_complete</tt> (string)
*;<tt>objN_script_complete</tt> (string)
Line 57: Line 70:


*;<tt>objN_logic_success</tt> (string)
*;<tt>objN_logic_success</tt> (string)
:Boolean logic applied to individual objective component states to determine if the objective is complete. The same boolean logic options are available as in the mission-level logic described above. By default, all of the components must be true to complete the objective. In other words, all components are ANDed together (1 AND 2 AND 3...).
*;<tt>objN_logic_failure</tt> (string)
*;<tt>objN_logic_failure</tt> (string)
:The logic string (e.g. "1 AND 3") for the objective completion/failure conditions. Specifies the objective components which need to be fulfilled before this entire objective is completed or considered failed.
:Boolean logic applied to individual objective component states to determine if the objective is failed. By default, if an objective is ongoing, and any opponent becomes false, that objective will fail.


= Objective Component Attributes and Spawnargs =
= Objective Components =
Each objective has an associated list of components and spawnargs defining the attributes of those components. These component spawnargs associated with a given objective are prefixed in the following manner:
obj<objective index>_<component index>_<spawnarg name>
Example: ''obj1_2_state''


Here, the index N defines the objective number and M refers to the component number. Programmers beware that both numbers start with 1.
In the following, the index N defines the objective number and M refers to the component number. Programmers beware that both numbers start from the value 1.


*;<tt>objN_M_state</tt> (1/0)  
*;<tt>objN_M_state</tt> (1/0)  
Line 68: Line 85:


*;<tt>objN_M_player_responsible</tt> (1/0)  
*;<tt>objN_M_player_responsible</tt> (1/0)  
:Defines whether the player should be responsible for this component to complete. Code defaults to 1.
:When true, the player must be responsible for the events that satisfy this component. Events the player is not responsible for are not counted. (e.g., the player kills an AI vs. another AI killing an AI). Code defaults to 1.


*;<tt>objN_M_not</tt> (1/0)  
*;<tt>objN_M_not</tt> (1/0)  
:Code defaults to 0. If this is set, the component is considered NOTed. So if the component is to kill 5 AI, and it's NOTted, it will remain true until 5 AI are killed, then be set to false).
:Code defaults to 0. If true, this component is logically NOTed, so when the conditions described by the type and speifiers are not met, the component state is true, and when they are met, it is false.


*;<tt>objN_M_irreversible</tt> (1/0)  
*;<tt>objN_M_irreversible</tt> (1/0)  
:Defines whether this component state cannot be reverted once it has been changed. Code defaults to 0.
:When the component state changes from its initial state, it will stay in its new state regardless of what happens later. (There is a script event to "unlatch" a latched objective component if needed). Code defaults to 0.


*;<tt>objN_M_type</tt> (string)  
*;<tt>objN_M_type</tt> (string)  
:Defines the type of this objective component.  
:Defines the type of this objective component. See the section [[#Component_Types|Component Types]] below for detailed information.
:'''Possible 'Objective Component' Types:'''
:'''Possible 'Objective Component' Types:'''
:* kill (also includes non-living things being destroyed)
:* kill (also includes non-living things being destroyed)
Line 94: Line 111:
:* distance (distance between the origin of entity X and that of entity Y)
:* distance (distance between the origin of entity X and that of entity Y)


Any component can have up to two specifiers, each of which can carry a value. Here, L refers to the number of the specifier, e.g. ("obj2_1_spec4" "name").
Any component can have up to two specifiers, each of which can carry a value. Here, K refers to the number of the specifier, e.g. ("obj2_1_spec4" "name").
*;<tt>objN_M_specL</tt> (string)  
*;<tt>objN_M_specK</tt> (string)  
:'''Specification Methods:'''
:'''Specification Methods:'''
:Specification methods determine what the objective component is looking for. Does it look at how many AI of a specific team you've KO'd, how many humans, how many overall, or whether you've KO'd an AI with a certain name? Each objective component can have up to two of the following specifiers (Not all components can take two specifiers, and not all specifiers make sense for all component types, future documentation will cover that).
:Specification methods determine what the objective component is looking for. Does it look at how many AI of a specific team you've KO'd, how many humans, how many overall, or whether you've KO'd an AI with a certain name? Each objective component can have up to two of the following specifiers (Not all components can take two specifiers, and not all specifiers make sense for all component types, future documentation will cover that). See the section [[#Specifiers|Specifiers]] below for a detailed description.
:'''The following apply to both AIs and items:'''
:'''The following apply to both AIs and items:'''
:* none
:* none
Line 109: Line 126:
:* ai_team (mapper defined team of the AI)
:* ai_team (mapper defined team of the AI)
:* ai_innocence (For distinguishing noncombatants)
:* ai_innocence (For distinguishing noncombatants)
*;<tt>objN_M_spec_valK</tt>
:Value that the Kth specifier should match in order to count towards this component. (E.g., an entity name if we specify by name.)


*;<tt>objN_M_args</tt> (space-delimited string)  
*;<tt>objN_M_args</tt> (space-delimited string)  
Line 117: Line 137:
:For clocked components like "custom_clocked" this determines how often they are updated. The value is to be set in seconds.
:For clocked components like "custom_clocked" this determines how often they are updated. The value is to be set in seconds.


= Mission Logic =
== Component Types ==
By default, all mandatory objectives need to be completed for mission success. However, it's possible to define a custom success and failure logic string on an objective entity. Be sure to have this addobjectives entity active at map start so that the logic is parsed right at map load.
=== AI-Related Components ===
The following specifiers are termed "Standard AI Specifiers": All specifiers minus the <tt>group</tt> specifier.
 
;*<tt>kill</tt>
:An AI must be killed to satisfy this component.
:'''SDK Name''': COMP_KILL
:'''Number of Specificatons''': 1 (object that must be killed)
:'''Applicable Specifiers''': Standard AI Specifiers
:'''Expected Arguments''': int (number of kills required)
 
;*<tt>ko</tt> (Knockout)
:An AI must be knocked out by any means (gas, blackjack, other).
:'''SDK Name''': COMP_KO
:'''Number of Specificatons''': 1 (AI that must be KO'd)
:'''Applicable Specifiers''': Standard AI Specifiers
:'''Expected Arguments''': int (number of KOs required)
 
;*<tt>ai_find_item</tt>
:''not yet implemented''
:'''SDK Name''': COMP_AI_FIND_ITEM
:'''Number of Specificatons''': --
:'''Applicable Specifiers''': --
:'''Expected Arguments''': --
 
;*<tt>ai_find_body</tt>
:''not yet implemented'' An AI must find a body. Currently, the specifiers apply to the bodies found, and any AI finding the bodies triggers this component. Future revisions might add another specifier for the AI that finds the body.
:'''SDK Name''': COMP_AI_FIND_BODY
:'''Number of Specificatons''': 1 (Type of body that must be found)
:'''Applicable Specifiers''': Standard AI Specifiers
:'''Expected Arguments''': int (number of bodies that must be found)
 
;*<tt>alert</tt>
:True if an AI or type of AI is alerted. Use the player_responsible flag to determine if this should count alerts not caused by the player's actions (e.g., enemy AI being sighted)
:'''SDK Name''': COMP_AI_ALERT
:'''Number of Specificatons''': 1 (AI that must be alerted)
:'''Applicable Specifiers''': Standard AI Specifiers
:'''Expected Arguments''': int (number of alerts required), int (minimum alert level that counts: 1-5 with 5 being the combat state)
 
=== Non-AI Components ===
 
;*<tt>destroy</tt>
:An inanimate item must be destroyed (damage it until its health is lower than zero).
:'''SDK Name''': COMP_DESTROY
:'''Number of Specificatons''': 1 (item to be destroyed)
:'''Applicable Specifiers''': all
:'''Expected Arguments''': int (number of items to be destroyed)
 
;*<tt>item</tt>
:Completed when the player has this inventory item or loot.
:'''SDK Name''': COMP_ITEM
:'''Number of Specificatons''': 1 (item the player must have)
:'''Applicable Specifiers''': All except AI type, team and innocence.
:'''Expected Arguments''': int (number of items to have, 1 by default)
 
;*<tt>pickpocket</tt>
:An inventory item must be taken from a conscious AI. Note that it doesn't matter what happens to the item after it is pickpocketed. It could be destroyed or dropped, but as long as it was originally pickpocketed, it counts.
:'''SDK Name''': COMP_PICKPOCKET
:'''Number of Specificatons''': 1 (Item the player must pickpocket)
:'''Applicable Specifiers''': All except AI type, team and innocence
:'''Expected Arguments''': int (number of items to pickpocket, 1 by default)
 
;*<tt>location</tt> Object in location brush (using info_tdm_objective_location brush)
:A particular item must be in a particular location, defined by an info_objective_location brush. For optimization reasons, the entity or entities to be checked must also have this spawnarg: "objective_ent" set to "1". NOTE: Multiple objects in a single location are not counted up for this component, this is a single-shot objective. If you want the player to put more than one object in a location, you must currently create several of these components, specifying by name, and OR them together in the objective logic.
:'''SDK Name''': COMP_LOCATION
:'''Number of Specificatons''': 2 (object entity to check, location entity to check)
:'''Applicable Specifiers''': For the object to check, all specifiers apply, but multiple objects are not counted up. Typically the objects will be specified by name. For the location to check, it will either be specified by name or by group.
:'''Expected Arguments''': None (if both specifiers match, the objective is completed).
 
;*<tt>info_location</tt> Object in location area (using info_location entities)
:A particular item must be in a particular location, defined by an info_location area (see vanilla D3 documentation for info_location). Multiple objects in a single location are not counted up for this component, this is a single-shot objective. If you want the player to put more than one object in a location, you must currently create several of these components, specifying by name, and OR them together in the objective logic.
:This check is done periodically. Set spawnarg <tt>clock_interval</tt> to the time in seconds between periodic checks.
:'''SDK Name''': COMP_INFO_LOCATION
:'''Number of Specificatons''': 2 (object entity to check, location entity to check)
:'''Applicable Specifiers''': For the object to check, all specifiers apply, but multiple objects are not counted up. Typically the objects will be specified by name. For the location to check, it will either be specified by name or by group.
:'''Expected Arguments''': None (if both specifiers match, the objective is completed).
 
;*<tt>custom</tt>
:This custom objective component is only changed when an external script changes it. Otherwise it does nothing.
:'''SDK Name''': COMP_CUSTOM_ASYNC
:'''Number of Specificatons''': none
:'''Applicable Specifiers''': none
:'''Expected Arguments''': none
 
;*<tt>custom_clocked</tt>
:This component calls a custom script periodically to check some condition. When run, the script is expected to this component true or false based on the custom check. This objective component could also be used as a convenient method to periodically call a script that has nothing to do with objectives.
:Set spawnarg <tt>clock_interval</tt> to the time in seconds between periodic calls of the script.
:'''SDK Name''': COMP_CUSTOM_CLOCKED
:'''Number of Specificatons''': none
:'''Applicable Specifiers''': none
:'''Expected Arguments''': string (name of the script to call periodically)
 
;*<tt>distance</tt>
:Two entities must be sufficiently close to eachother to satisfy this component. The distance check is done between the origin of the first object and that of the second object. If this distance is below the input maximum distance, the component is set to true.
:This check is done periodically. Set spawnarg "clock_interval" to the time in seconds between periodic checks.
:'''SDK Name''': COMP_DISTANCE
:'''Number of Specificatons''': none (see arguments below)
:'''Applicable Specifiers''': none
:'''Expected Arguments''': string (name of first entity), string (name of second entity), int (maximum distance in doom units)
 
== Specifiers ==
;*<tt>none</tt>
:No specifier. Component will be completed as soon as any event of that component type happens. (E.g., if you set a KO component type, with specifier none, it would be set to true as soon as soon as the player KO's anyone). This is the default specifier if none is entered. Not very useful, except for blanket "don't do this" objectives. Even then, it is better to use "overall" described below.
:'''SDK Name''': SPEC_NONE
:'''Specifier Argument Type Expected''': No spec argument needed since we don't have to match anything.
 
;*<tt>name</tt>
:Name of the entity
:'''SDK Name''': SPEC_NAME
:'''Specifier Argument Type Expected''': string
 
;*<tt>overall</tt>
:In the context of inventory item objectives, this refers to overall loot. In the context of AI objectives, this refers to all AI, regardless of team, type, etc.
:'''SDK Name''': SPEC_OVERALL
:'''Specifier Argument Type Expected''': No spec argument needed since we don't have to match anything.
 
;*<tt>Group</tt>
:For inventory items, the item's <tt>inv_name</tt> spawnarg value will be used here. For example, if you want the player to get 5 flashbombs, you would use this with group equal to the <tt>inv_name</tt> of flashbombs. As opposed to getting a specific flashbomb in the map, where you would use the <tt>name</tt> specifier instead. If an inventory item is loot, the loot group is used here instead (e.g., <tt>loot_gold</tt>).
:Group is also used for other component types as a convenient way to group things, such as info_objective_location or info_location entities checked by COMP_LOCATION and COMP_INFO_LOCATION, respectively.
:'''SDK Name''': SPEC_GROUP
:'''Specifier Argument Type Expected''': string
:'''Loot group names:''' <tt>loot_gold</tt>, <tt>loot_goods</tt>, <tt>loot_jewels</tt> and <tt>loot_total</tt>
 
;*<tt>Classname</tt>
:The entityDef classname of the entity. For example: atdm:ai_builder_guard
:'''SDK Name''': SPEC_CLASSNAME
:'''Specifier Argument Type Expected''': string
 
;*<tt>Spawnclass</tt>
: The SDK classname of the entity. For example: idAI
:'''SDK Name''': SPEC_SPAWNCLASS
:'''Specifier Argument Type Expected''': string


*;<tt>mission_logic_success</tt> (string)
;*<tt>ai_type</tt>  
:Defines the success logic, e.g. "1 AND 2 AND 3".
:Type of AI: human, beast, undead, steambot, etc. (reads m_AIType in the SDK, which is set by the "type" spawnarg on idActors. Not sure if this is implemented yet).
*;<tt>mission_logic_failure</tt> (string)
:'''SDK Name''': SPEC_AI_TYPE
:Defines the failure logic. When this condition is fulfilled, the mission has failed.
:'''Specifier Argument Type Expected''': int


The above spawnargs apply to all difficulty levels. It's of course possible to override this default for a given difficulty level, by setting these spawnargs. The index N is referring to the difficulty level number (starting from 0 = Easy):
;*<tt>ai_team</tt>
:The AI's team integer. This can be set up by the mapper to put AI on arbitrary teams. Mapper can also team up AI for objective purposes, and use this team specifier as a fast way of saying "KO any of these 5 AI." Alternatively, one could use the name specifier and put in multiple components for each of those 5 AI, then OR all the components in the objective success logic. Making a new team may save time over that method.
:'''SDK Name''': SPEC_AI_TEAM
:'''Specifier Argument Type Expected''': int


*;<tt>mission_logic_success_diff_N</tt> (string)
;*<tt>ai_innocence</tt>  
:Defines the success logic for the difficulty level N (override the default logic), e.g. "1 AND 2 AND 3".
:Differentiates between combatants and non-combatants. A value of 1 = non-combatant, a value of 0 => non-combatant, or otherwise not deemed "innocent" by the FM author.
*;<tt>mission_logic_failure_diff_N</tt> (string)
:'''SDK Name''': SPEC_AI_INNOCENCE
:Defines the failure logic for the difficulty level N (override the default logic). When this condition is fulfilled, the mission has failed.
:'''Specifier Argument Type Expected''': int (1 = innocent, 0 = not)


= Conclusion =
= Conclusion =

Revision as of 12:39, 13 August 2008

Originally written by Ishtvan on http://forums.thedarkmod.com/topic/4121 additions by greebo

The objectives system exists to determine when the player has completed the mission. At the highest level, a mission consists of a list of objectives to be completed and boolean logic to determine when the mission has succeeded or failed based on which of the objectives are complete. At the objective level, an objective consists of individual components and boolean logic to determine when the objective is completed or failed. At the component level, each component has a type, a specifier, and arguments. These will be explained fully in the components section.

Mission

Objectives are stored by entities named target_tdm_addobjectives. When triggered, these entities add objectives to the mission based on their spawnargs. These target entities may be triggered at any time to add objectives during the mission. Typically a target_addobjectives is triggered at mission start by worldspawn to set up the initial objectives.

Spawnargs governing mission level behavior may be entered on any target_addobjectives. Non-empty spawnargs will be overwritten by the most recently triggered target_addobjectives (FM authors may want to do this if they add an objective later on and want to change the mission success logic to include that objective, for example). The following is a list of the mission-level spawnargs and what they mean:

Success/Failure Logic

By default, all mandatory objectives need to be completed for mission success. However, it's possible to define a custom success and failure logic string on an objective entity. Be sure to have this addobjectives entity active at map start so that the logic is parsed right at map load.

Default Logic

  • mission_logic_success (string)
A string of boolean logic applied to individual objective states to determine if the mission succeeds. AND, OR, NOT and parenthesis are available. The FM author can construct strings using these and the integer index for an objective. For example: "1 OR (NOT(2) AND 3)" would complete the mission if either objective 1 is true, or if 2 is false and 3 is true. By default, a mission succeeds when all mandatory objectives are completed.
  • mission_logic_failure (string)
Boolean logic applied to individual objective component states to determine if the mission has failed. By default, if any mandatory objective fails, the mission fails.

Difficulty Dependent Logic

The above spawnargs apply to all difficulty levels. It's of course possible to override this default for a given difficulty level, by setting these spawnargs. The index N is referring to the difficulty level number (starting from 0 = Easy):

  • mission_logic_success_diff_N (string)
Defines the success logic for the difficulty level N (override the default logic), e.g. "1 AND 2 AND 3".
  • mission_logic_failure_diff_N (string)
Defines the failure logic for the difficulty level N (override the default logic). When this condition is fulfilled, the mission has failed.

If specific logic is not specified for a certain difficulty level, the default spawnargs (without _diff_*) will be used.

Objectives

Objectives added by the target_addobjectives each have a unique integer index, starting with objective 1, the first objective. The spawnargs associated with an objective are prefixed in the following manner:

obj<objective index>_<spawnarg name>

Example: obj3_desc

The spawnargs (minus prefix) and meanings for objective attributes are listed below. Each objective also includes a list of components and their attributes, which will be covered in the next section.

  • objN_desc (string)
The description of this objective. This is used to display the objective in the GUI - the user will never see the objective number, only this string. The default value is an empty string.
  • objN_state (int) Defines the state of the objective at map start.
Possible Objective States:
  • 0 = OBJ_INCOMPLETE
  • 1 = OBJ_COMPLETE
  • 2 = OBJ_FAILED
  • 3 = OBJ_INVALID
Code defaults to 0 = incomplete.
  • objN_mandatory (1/0)
Set to 0 for optional objective that doesn't fail the mission if you fail it. Objective must be completed to complete the mission if 1. Code defaults to 1.
  • objN_irreversible (1/0)
Irreversible objectives lock their state once they're changed to COMPLETE or FAILED. Irreversible components will only change state once and then stay in that state. (Note: There are scriptfunctions to reset irreversible objectives and components if the FM author wants to let them change again for some reason). Code defaults to 0.
  • objN_ongoing (1/0)
If true, this objective is not marked as complete and the player is not informed that it's complete until the end of the mission. Typically used for "do not kill" type objectives, because technically they would be complete right from the beginning, but we don't want to mark them off or tell the player they're complete right at the beginning. Could also be used for "have some item with you when you complete the mission." Code defaults to 0.
  • objN_visible (1/0)
Whether the objective appears in the player's Objectives GUI. Use invalidated and hidden objectives to queue up objectives for later, or hidden but valid objectives as another way of scripting events when the player does a certain thing, since objectives can launch an arbitrary script after they're completed. Code defaults to 1.
  • objN_difficulty (integer)
Space delimited list of difficulty levels that should include this objective. For example, "2 3" would enable this objective at difficulty levels 2 and 3, but not for other difficulty levels. Default value is empty - the objective applies to all difficulty levels.
Note: When the objective is not active for a given difficutly, it is invalidated and hidden, but it still exists, so the numbering of the next objective should still increase by 1. E.g., objective 5 only appears on hard difficulty, but you still have to call the next objective objective 6, you can't call it objective 5 only appearing on easy or medium difficulty.
  • objN_enabling_objs (space-delimited integers)
This is a list of objectives which must be completed before this objective can be completed. For example, we shouldn't mark "objective complete" for exiting the mission until all the other mission goals have been completed. An example value for this spawnarg would be "4 6" to let this objective depend on objectives #4 and #6.
  • objN_script_complete (string)
    objN_script_failed (string)
Name of a script to call when this objective is completed or failed. For example, this could be used in campaigns to set up optional objectives in one mission that effect other missions. This feature could also be used as a general scripting aide if the author wants to set up the conditions for something happening using a hidden objective.
  • objN_logic_success (string)
Boolean logic applied to individual objective component states to determine if the objective is complete. The same boolean logic options are available as in the mission-level logic described above. By default, all of the components must be true to complete the objective. In other words, all components are ANDed together (1 AND 2 AND 3...).
  • objN_logic_failure (string)
Boolean logic applied to individual objective component states to determine if the objective is failed. By default, if an objective is ongoing, and any opponent becomes false, that objective will fail.

Objective Components

Each objective has an associated list of components and spawnargs defining the attributes of those components. These component spawnargs associated with a given objective are prefixed in the following manner:

obj<objective index>_<component index>_<spawnarg name>

Example: obj1_2_state

In the following, the index N defines the objective number and M refers to the component number. Programmers beware that both numbers start from the value 1.

  • objN_M_state (1/0)
Defines the state of the component at map start, which can only be "1" (complete) or "0" (incomplete). Code defaults to 0.
  • objN_M_player_responsible (1/0)
When true, the player must be responsible for the events that satisfy this component. Events the player is not responsible for are not counted. (e.g., the player kills an AI vs. another AI killing an AI). Code defaults to 1.
  • objN_M_not (1/0)
Code defaults to 0. If true, this component is logically NOTed, so when the conditions described by the type and speifiers are not met, the component state is true, and when they are met, it is false.
  • objN_M_irreversible (1/0)
When the component state changes from its initial state, it will stay in its new state regardless of what happens later. (There is a script event to "unlatch" a latched objective component if needed). Code defaults to 0.
  • objN_M_type (string)
Defines the type of this objective component. See the section Component Types below for detailed information.
Possible 'Objective Component' Types:
  • kill (also includes non-living things being destroyed)
  • ko
  • ai_find_item (not implemented)
  • ai_find_body (not implemented)
  • alert
  • destroy (inanimate item destroyed ("killed"))
  • item (picked up or dropped an inventory item)
  • pickpocket (inventory item acquired from conscious AI)
  • location (Item A at location B, where "A" is any entity that must have the key "objective_ent" set to "1" on it, and location B is a special entity info_objective_location. Later on we may support using the D3 location system as well)
  • custom (custom component that is set true/false by a map script)
These components are triggered every N milliseconds by a system clock:
  • custom_clocked (runs a custom map script that should check something and set the objective)
  • info_location (Item A at info_location area B) - TODO: more information needed
  • distance (distance between the origin of entity X and that of entity Y)

Any component can have up to two specifiers, each of which can carry a value. Here, K refers to the number of the specifier, e.g. ("obj2_1_spec4" "name").

  • objN_M_specK (string)
Specification Methods:
Specification methods determine what the objective component is looking for. Does it look at how many AI of a specific team you've KO'd, how many humans, how many overall, or whether you've KO'd an AI with a certain name? Each objective component can have up to two of the following specifiers (Not all components can take two specifiers, and not all specifiers make sense for all component types, future documentation will cover that). See the section Specifiers below for a detailed description.
The following apply to both AIs and items:
  • none
  • name (name of entity)
  • overall (overall count of something: kills, loot, kos, etc)
  • group (inventory group)
  • classname (soft/scripting classname)
  • spawnclass (hard / SDK classname, e.g. "idPlayer")
The following specification methods apply only to AI:
  • ai_type (human, beast, undead, bot, etc)
  • ai_team (mapper defined team of the AI)
  • ai_innocence (For distinguishing noncombatants)
  • objN_M_spec_valK
Value that the Kth specifier should match in order to count towards this component. (E.g., an entity name if we specify by name.)
  • objN_M_args (space-delimited string)
Integer and String Arguments:
A component can have an arbitrary number of int and string arguments that are fed in space delimited lists. The type of component and specifier determines which args it will use and what it will do with them. For example, the first integer arg is often used to determine how many times something can happen, e.g., the player is only allowed 4 KOs, or must get 500 loot. Not all events are counted up though. The only things that are counted up are things in the mission statistics like loot and kills, so everything else is pretty much a one shot deal where it happens once. Future documentation will detail which objective events are counted up and which are one shots.
  • objN_M_clock_interval (float/seconds)
For clocked components like "custom_clocked" this determines how often they are updated. The value is to be set in seconds.

Component Types

AI-Related Components

The following specifiers are termed "Standard AI Specifiers": All specifiers minus the group specifier.

  • kill
An AI must be killed to satisfy this component.
SDK Name: COMP_KILL
Number of Specificatons: 1 (object that must be killed)
Applicable Specifiers: Standard AI Specifiers
Expected Arguments: int (number of kills required)
  • ko (Knockout)
An AI must be knocked out by any means (gas, blackjack, other).
SDK Name: COMP_KO
Number of Specificatons: 1 (AI that must be KO'd)
Applicable Specifiers: Standard AI Specifiers
Expected Arguments: int (number of KOs required)
  • ai_find_item
not yet implemented
SDK Name: COMP_AI_FIND_ITEM
Number of Specificatons: --
Applicable Specifiers: --
Expected Arguments: --
  • ai_find_body
not yet implemented An AI must find a body. Currently, the specifiers apply to the bodies found, and any AI finding the bodies triggers this component. Future revisions might add another specifier for the AI that finds the body.
SDK Name: COMP_AI_FIND_BODY
Number of Specificatons: 1 (Type of body that must be found)
Applicable Specifiers: Standard AI Specifiers
Expected Arguments: int (number of bodies that must be found)
  • alert
True if an AI or type of AI is alerted. Use the player_responsible flag to determine if this should count alerts not caused by the player's actions (e.g., enemy AI being sighted)
SDK Name: COMP_AI_ALERT
Number of Specificatons: 1 (AI that must be alerted)
Applicable Specifiers: Standard AI Specifiers
Expected Arguments: int (number of alerts required), int (minimum alert level that counts: 1-5 with 5 being the combat state)

Non-AI Components

  • destroy
An inanimate item must be destroyed (damage it until its health is lower than zero).
SDK Name: COMP_DESTROY
Number of Specificatons: 1 (item to be destroyed)
Applicable Specifiers: all
Expected Arguments: int (number of items to be destroyed)
  • item
Completed when the player has this inventory item or loot.
SDK Name: COMP_ITEM
Number of Specificatons: 1 (item the player must have)
Applicable Specifiers: All except AI type, team and innocence.
Expected Arguments: int (number of items to have, 1 by default)
  • pickpocket
An inventory item must be taken from a conscious AI. Note that it doesn't matter what happens to the item after it is pickpocketed. It could be destroyed or dropped, but as long as it was originally pickpocketed, it counts.
SDK Name: COMP_PICKPOCKET
Number of Specificatons: 1 (Item the player must pickpocket)
Applicable Specifiers: All except AI type, team and innocence
Expected Arguments: int (number of items to pickpocket, 1 by default)
  • location Object in location brush (using info_tdm_objective_location brush)
A particular item must be in a particular location, defined by an info_objective_location brush. For optimization reasons, the entity or entities to be checked must also have this spawnarg: "objective_ent" set to "1". NOTE: Multiple objects in a single location are not counted up for this component, this is a single-shot objective. If you want the player to put more than one object in a location, you must currently create several of these components, specifying by name, and OR them together in the objective logic.
SDK Name: COMP_LOCATION
Number of Specificatons: 2 (object entity to check, location entity to check)
Applicable Specifiers: For the object to check, all specifiers apply, but multiple objects are not counted up. Typically the objects will be specified by name. For the location to check, it will either be specified by name or by group.
Expected Arguments: None (if both specifiers match, the objective is completed).
  • info_location Object in location area (using info_location entities)
A particular item must be in a particular location, defined by an info_location area (see vanilla D3 documentation for info_location). Multiple objects in a single location are not counted up for this component, this is a single-shot objective. If you want the player to put more than one object in a location, you must currently create several of these components, specifying by name, and OR them together in the objective logic.
This check is done periodically. Set spawnarg clock_interval to the time in seconds between periodic checks.
SDK Name: COMP_INFO_LOCATION
Number of Specificatons: 2 (object entity to check, location entity to check)
Applicable Specifiers: For the object to check, all specifiers apply, but multiple objects are not counted up. Typically the objects will be specified by name. For the location to check, it will either be specified by name or by group.
Expected Arguments: None (if both specifiers match, the objective is completed).
  • custom
This custom objective component is only changed when an external script changes it. Otherwise it does nothing.
SDK Name: COMP_CUSTOM_ASYNC
Number of Specificatons: none
Applicable Specifiers: none
Expected Arguments: none
  • custom_clocked
This component calls a custom script periodically to check some condition. When run, the script is expected to this component true or false based on the custom check. This objective component could also be used as a convenient method to periodically call a script that has nothing to do with objectives.
Set spawnarg clock_interval to the time in seconds between periodic calls of the script.
SDK Name: COMP_CUSTOM_CLOCKED
Number of Specificatons: none
Applicable Specifiers: none
Expected Arguments: string (name of the script to call periodically)
  • distance
Two entities must be sufficiently close to eachother to satisfy this component. The distance check is done between the origin of the first object and that of the second object. If this distance is below the input maximum distance, the component is set to true.
This check is done periodically. Set spawnarg "clock_interval" to the time in seconds between periodic checks.
SDK Name: COMP_DISTANCE
Number of Specificatons: none (see arguments below)
Applicable Specifiers: none
Expected Arguments: string (name of first entity), string (name of second entity), int (maximum distance in doom units)

Specifiers

  • none
No specifier. Component will be completed as soon as any event of that component type happens. (E.g., if you set a KO component type, with specifier none, it would be set to true as soon as soon as the player KO's anyone). This is the default specifier if none is entered. Not very useful, except for blanket "don't do this" objectives. Even then, it is better to use "overall" described below.
SDK Name: SPEC_NONE
Specifier Argument Type Expected: No spec argument needed since we don't have to match anything.
  • name
Name of the entity
SDK Name: SPEC_NAME
Specifier Argument Type Expected: string
  • overall
In the context of inventory item objectives, this refers to overall loot. In the context of AI objectives, this refers to all AI, regardless of team, type, etc.
SDK Name: SPEC_OVERALL
Specifier Argument Type Expected: No spec argument needed since we don't have to match anything.
  • Group
For inventory items, the item's inv_name spawnarg value will be used here. For example, if you want the player to get 5 flashbombs, you would use this with group equal to the inv_name of flashbombs. As opposed to getting a specific flashbomb in the map, where you would use the name specifier instead. If an inventory item is loot, the loot group is used here instead (e.g., loot_gold).
Group is also used for other component types as a convenient way to group things, such as info_objective_location or info_location entities checked by COMP_LOCATION and COMP_INFO_LOCATION, respectively.
SDK Name: SPEC_GROUP
Specifier Argument Type Expected: string
Loot group names: loot_gold, loot_goods, loot_jewels and loot_total
  • Classname
The entityDef classname of the entity. For example: atdm:ai_builder_guard
SDK Name: SPEC_CLASSNAME
Specifier Argument Type Expected: string
  • Spawnclass
The SDK classname of the entity. For example: idAI
SDK Name: SPEC_SPAWNCLASS
Specifier Argument Type Expected: string
  • ai_type
Type of AI: human, beast, undead, steambot, etc. (reads m_AIType in the SDK, which is set by the "type" spawnarg on idActors. Not sure if this is implemented yet).
SDK Name: SPEC_AI_TYPE
Specifier Argument Type Expected: int
  • ai_team
The AI's team integer. This can be set up by the mapper to put AI on arbitrary teams. Mapper can also team up AI for objective purposes, and use this team specifier as a fast way of saying "KO any of these 5 AI." Alternatively, one could use the name specifier and put in multiple components for each of those 5 AI, then OR all the components in the objective success logic. Making a new team may save time over that method.
SDK Name: SPEC_AI_TEAM
Specifier Argument Type Expected: int
  • ai_innocence
Differentiates between combatants and non-combatants. A value of 1 = non-combatant, a value of 0 => non-combatant, or otherwise not deemed "innocent" by the FM author.
SDK Name: SPEC_AI_INNOCENCE
Specifier Argument Type Expected: int (1 = innocent, 0 = not)

Conclusion

Using components that combine component types with up to 2 entity arguments and 2 specifier types, plus objectives that are a boolean combination of those components should hopefully allow for a variety of different objectives.