Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Missions: Move some start functions into JSON #27037

Merged
merged 3 commits into from
Dec 15, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 31 additions & 16 deletions data/json/npcs/missiondef.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@
"goal": "MGOAL_GO_TO_TYPE",
"difficulty": 2,
"value": 50000,
"start": "open_sarcophagus",
"start": {
"effect": [ "follow", { "u_buy_item": "sarcophagus_access_code" } ],
"target_om_ter": { "om_ter": "haz_sar", "reveal_rad": 3 }
},
"origins": [ "ORIGIN_SECONDARY" ],
"destination": "haz_sar_b1",
"dialogue": {
Expand Down Expand Up @@ -215,7 +218,10 @@
"difficulty": 2,
"value": 150000,
"item": "black_box_transcript",
"start": "reveal_lab_black_box",
"start": {
"effect": { "u_buy_item": "black_box" },
"target_om_ter": { "om_ter": "lab", "reveal_rad": 3 }
},
"origins": [ "ORIGIN_SECONDARY" ],
"followup": "MISSION_EXPLORE_SARCOPHAGUS",
"dialogue": {
Expand Down Expand Up @@ -281,7 +287,7 @@
"difficulty": 2,
"value": 140000,
"item": "record_accounting",
"start": "reveal_office_tower",
"start": { "reveal_om_ter": "office_tower_1" },
"origins": [ "ORIGIN_OPENER_NPC", "ORIGIN_ANY_NPC" ],
"followup": "MISSION_GET_SAFE_BOX",
"dialogue": {
Expand All @@ -304,7 +310,7 @@
"difficulty": 2,
"value": 60000,
"item": "record_patient",
"start": "reveal_doctors_office",
"start": { "reveal_om_ter": [ "office_doctor", "hospital_2" ] },
"origins": [ "ORIGIN_OPENER_NPC", "ORIGIN_ANY_NPC" ],
"followup": "MISSION_REACH_FEMA_CAMP",
"dialogue": {
Expand All @@ -327,7 +333,7 @@
"difficulty": 2,
"value": 50000,
"item": "record_weather",
"start": "reveal_weather_station",
"start": { "reveal_om_ter": "station_radio" },
"origins": [ "ORIGIN_OPENER_NPC", "ORIGIN_ANY_NPC" ],
"dialogue": {
"describe": "I wonder if a retreat might exist...",
Expand All @@ -349,7 +355,7 @@
"difficulty": 2,
"value": 100000,
"item": "small_relic",
"start": "reveal_cathedral",
"start": { "reveal_om_ter": [ "cathedral_1", "museum" ] },
"origins": [ "ORIGIN_OPENER_NPC", "ORIGIN_ANY_NPC" ],
"followup": "MISSION_RECOVER_PRIEST_DIARY",
"dialogue": {
Expand Down Expand Up @@ -418,7 +424,10 @@
"difficulty": 8,
"value": 250000,
"item": "software_blood_data",
"start": "reveal_hospital",
"start": {
"effect": [ { "u_buy_item": "vacutainer" }, { "u_buy_item": "usb_drive" } ],
"target_om_ter": { "om_ter": "hospital_2", "reveal_rad": 3 }
},
"origins": [ "ORIGIN_SECONDARY" ],
"dialogue": {
"describe": "It could be very informative to perform an analysis of zombie blood...",
Expand All @@ -440,7 +449,7 @@
"difficulty": 2,
"value": 150000,
"item": "etched_skull",
"start": "point_cabin_strange",
"start": { "target_om_ter": { "om_ter": "cabin_strange", "reveal_rad": 3 } },
"origins": [ "ORIGIN_SECONDARY" ],
"followup": "MISSION_INVESTIGATE_PRISON_VISIONARY",
"dialogue": {
Expand All @@ -463,7 +472,7 @@
"difficulty": 2,
"value": 150000,
"item": "visions_solitude",
"start": "point_prison",
"start": { "target_om_ter": { "om_ter": "prison_1_5", "reveal_rad": 3 } },
"origins": [ "ORIGIN_SECONDARY" ],
"dialogue": {
"describe": "St. Michael the archangel defend me in battle...",
Expand All @@ -486,7 +495,7 @@
"value": 0,
"urgent": true,
"item": "badge_deputy",
"start": "join",
"start": { "effect": "follow" },
"origins": [ "ORIGIN_SECONDARY" ],
"dialogue": {
"describe": "Well damn, you must be the guys here to pick me up...",
Expand All @@ -509,7 +518,7 @@
"monster_kill_goal": 100,
"difficulty": 5,
"value": 250000,
"start": "join",
"start": { "effect": "follow" },
"end": "leave",
"origins": [ "ORIGIN_SECONDARY" ],
"followup": "MISSION_KILL_HORDE_MASTER",
Expand Down Expand Up @@ -646,8 +655,8 @@
"goal": "MGOAL_KILL_MONSTER_TYPE",
"difficulty": 5,
"value": 250000,
"start": "kill_20_nightmares",
"monster_type": "mon_charred_nightmare",
"start": { "target_om_ter": { "om_ter": "necropolis_c_44", "zlevel": -2 } },
"monster_kill_goal": 20,
"origins": [ "ORIGIN_SECONDARY" ],
"dialogue": {
Expand All @@ -670,7 +679,10 @@
"difficulty": 2,
"value": 250000,
"item": "radio_repeater_mod",
"start": "radio_repeater",
"start": {
"effect": { "u_buy_item": "repeater_mod_guide" },
"target_om_ter": { "om_ter": "necropolis_c_23", "reveal_rad": 3, "zlevel": -2 }
},
"origins": [ "ORIGIN_SECONDARY" ],
"followup": "MISSION_OLD_GUARD_NEC_COMMO_2",
"dialogue": {
Expand Down Expand Up @@ -1722,7 +1734,7 @@
"goal": "MGOAL_GO_TO_TYPE",
"difficulty": 2,
"value": 60000,
"start": "join",
"start": { "effect": "follow" },
"end": "leave",
"origins": [ "ORIGIN_SECONDARY" ],
"destination": "farm",
Expand All @@ -1745,7 +1757,7 @@
"goal": "MGOAL_GO_TO_TYPE",
"difficulty": 2,
"value": 60000,
"start": "join",
"start": { "effect": "follow" },
"origins": [ "ORIGIN_SECONDARY" ],
"followup": "MISSION_REACH_FARM_HOUSE",
"destination": "fema",
Expand Down Expand Up @@ -1867,7 +1879,10 @@
"difficulty": 5,
"value": 50000,
"item": "software_blood_data",
"start": "reveal_hospital",
"start": {
"effect": [ { "u_buy_item": "vacutainer" }, { "u_buy_item": "usb_drive" } ],
"target_om_ter": { "om_ter": "hospital_2", "reveal_rad": 3 }
},
"origins": [ "ORIGIN_SECONDARY" ],
"followup": "MISSION_SCIENCE_REP_2",
"dialogue": {
Expand Down
123 changes: 123 additions & 0 deletions doc/MISSIONS_JSON.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# Creating missions

NPCs can assign missions to the player. There is a fairly regular structure for this:

```JSON
{
"id": "MISSION_GET_BLACK_BOX_TRANSCRIPT",
"type": "mission_definition",
"name": "Retrieve Black Box Transcript",
"goal": "MGOAL_FIND_ITEM",
"difficulty": 2,
"value": 150000,
"item": "black_box_transcript",
"start": {
"effect": { "u_buy_item": "black_box" },
"target_om_ter": { "om_ter": "lab", "reveal_rad": 3 }
},
"origins": [ "ORIGIN_SECONDARY" ],
"followup": "MISSION_EXPLORE_SARCOPHAGUS",
"dialogue": {
"describe": "With the black box in hand, we need to find a lab.",
"offer": "Thanks to your searching we've got the black box but now we need to have a look'n-side her. Now, most buildings don't have power anymore but there are a few that might be of use. Have you ever seen one of those science labs that have popped up in the middle of nowhere? Them suckers have a glowing terminal out front so I know they have power somewhere inside'em. If you can get inside and find a computer lab that still works you ought to be able to find out what's in the black box.",
"accepted": "Fuck ya, America!",
"rejected": "Do you have any better ideas?",
"advice": "When I was play'n with the terminal for the one I ran into it kept asking for an ID card. Finding one would be the first order of business.",
"inquire": "How 'bout that black box?",
"success": "America, fuck ya! I was in the guard a few years back so I'm confident I can make heads-or-tails of these transmissions.",
"success_lie": "What?! I out'ta whip you're ass.",
"failure": "Damn, I maybe we can find an egg-head to crack the terminal."
}
}
```

### type
Must always be there and must always be "mission_definition".

### id
The mission id is required, but for new missions, it can be arbitrary. Convention is to start
it with "MISSION" and to use a fairly desriptive name.

### name
The name is also required, and the name is what is displayed in the 'm'issions menu, so please
make it descriptive.

### goal
Must be included, and must be one of these strings:
"MGOAL_GO_TO" - Reach a specific overmap tile
"MGOAL_GO_TO_TYPE" - Reach any instance of a specified overmap tile type
"MGOAL_COMPUTER_TOGGLE" - Activating the correct terminal will complete the mission
"MGOAL_FIND_ITEM" - Find 1 or more items of a given type
"MGOAL_FIND_ANY_ITEM" - Find 1 or more items of a given type, tagged for this mission
"MGOAL_FIND_MONSTER" - Find and retrieve a friendly monster
"MGOAL_FIND_NPC" - Find a specific NPC
"MGOAL_RECRUIT_NPC" - Recruit a specific NPC
"MGOAL_RECRUIT_NPC_CLASS" - Recruit an NPC of a specific class
"MGOAL_ASSASSINATE" - Kill a specific NPC
"MGOAL_KILL_MONSTER" - Kill a specific hostile monster
"MGOAL_KILL_MONSTER_TYPE" - Kill some number of a specific monster type
"MGOAL_KILL_MONSTER_SPEC" - Kill some number of monsters from a specific species

Currently, only "MGOAL_FIND_ITEM", "MGOAL_KILL_MONSTER_TYPE", and "MGOAL_KILL_MONSTER_SPEC"
missions can be fully defined in JSON without requiring C++ code support.

### start
Optional field. If it is present and a string, it must be name of a function in mission_start::
that takes a mission * and performs the start code for the mission. A hardcoded function is
currently necessary to set up any mission other than MGOAL_FIND_ITEM", "MGOAL_KILL_MONSTER_TYPE",
or "MGOAL_KILL_MONSTER_SPEC".

Alternately, if present, it can be an object with any of the following optional fields:

#### effects
This is an effects array, exactly as defined in NPCs.md, and can use any of the values from
effects. In all cases, the NPC involved is the quest giver.

#### reveal_om_ter
This can be a string or a list of strings, all of which must be overmap terrain ids. A randomly
selected overmap terrain tile with that id - or one of the ids from list, randomly selected -
will be revealed, and there is a 1 in 3 chance that the road route to the map tile will also
be revealed.

#### target_om_ter or target_om_ter_random or target_om_ter_random_or_create
Each of these is an object, with a mandatory field of "om_ter" that must be an overmap terrain
id. "target_om_ter_random_or_create" also has mandatory fields of "om_spec" and "om_replace_ter",
which must be an overmap special id and an overmap terrain id, respectively.

All three also have the optional fields of "reveal_rad" which is an number, and "must_see"
which is a boolean. "target_om_ter" has a third optional field of "zlevel", which again is a
number, while the other two have "range", which is also a number.

"target_om_ter" sets the mission target to be the closet terrain of om_ter, optionally the closest
that the player has already seen if "must_see" is true. If "reveal_rad" is 1 or more, it also
reveals the overmap around the target for reveal_rad tiles. The terrain can be at a different
z-level by passing a non-zero value into "zlevel".

"target_om_ter_random" finds all om_ter terrains in "range", defaulting to 5, and sets and
reveals the target to a randomly chosen terrain. "must_see" and "reveal_rad" have the same
meaning.

"target_om_ter_random_or_create" works like "target_om_ter_random", except that if there are
no instances of "om_ter" in range, it creates an instance of "om_spec" on some unseen territory
of type "om_replace_ter" and then reveals and targets that. "om_spec" must include "om_ter".

### monster_species
For "MGOAL_KILL_MONSTER_SPEC", sets the target monster species.

### monster_type
For "MGOAL_KILL_MONSTER_TYPE", sets the target monster type.

### monster_kill_goal
For "MGOAL_KILL_MONSTER_SPEC" and "MGOAL_KILL_MONSTER_TYPE", sets the number of monsters above
the player's current kill count that must be killed to complete the mission.

### dialogue
This is a dictionary of strings. The NPC says these exact strings in response to the player
inquiring about the mission or reporting its completion.

## Adding new missions to NPC dialogue
Any NPC that has missions needs to either:
* Add one of their talk_topic IDs to the list of generic mission reponse IDs in the first
talk_topic of data/json/npcs/TALK_COMMON_MISSION.json
* Have a similar talk_topic with responses that lead to TALK_MISSION_INQUIRE and
TALK_MISSION_LIST_ASSIGNED.
3 changes: 3 additions & 0 deletions doc/NPCs.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ Dialogues work like state machines. They start with a certain topic (the NPC say

Note that it is perfectly fine to have a response that switches the topic back to itself.

NPC missions are controlled by a seperate but related JSON structure and are documented in
MISSIONS_JSON.md.

Two topics are special:
- "TALK_DONE" ends the dialogue immediately.
- "TALK_NONE" goes to the previously talked about topic.
Expand Down
Loading