These are all fine ideas. Take a look at
for a document explaining the basics, and
for a dialogue file that does most of the things you’re talking about. It’s fairly straightforward to implement this stuff… I found the hardest part wasn’t learning JSON, which is super easy markup language stuff, but navigating git (the tool used for merging your creations into the base game) that made it hard. If you want to do the jSON legwork, I’d be happy helping you get it on git.
While I am grateful for the suggestions and help. I really wanted to build ideas and not get too in depth with the programming elements again. I gave up on that path a long time ago. Story on the otherhand is always something I can bang out and ask folks to add to it for polish.
If anyone wants to use my ideas. Feel free and do so. If not. I’m the wrong one to try and write coding. Some folks will be surgeons and find it a decent path. I would be the arse that leaves half the kit in the poor patient. This is my coding perspective.
On that note. anyone can ask me for writing and ideas. I am not always online, but I will get back to you with whatever you want to write. =D
Again, JSON isn’t coding.
Nevertheless, this is not how you intend to contribute. That’s fine - people have different strengths. But in the future, please don’t complain about how improving NPCs are last on everyone’s agenda without mentioning that you didn’t care to make the effort to improve them, either.
How would one go about adding a new mission? I can see the dialogue options in the json, but it looks like TALK_MISSION_LIST is populated somewhere in the code (looks like npctalk.cpp is involved, but I imagine it’s more than that). Plus there’s the actual mission effects that somehow need to be implemented. For instance, the canned food fetch quest idea should put the retrieved food items into the storage room in the center (or alternatively delete provided items and spawn new ones in the storage room.) . Then there is the mission-specific dialogue, which does not seem to be in the same json file. I’ve not looked over the code base beyond a quick scan, but some pointers to where to look might help get something working.
In my experience the mission code is pretty messy. The dialogue that initially enables the mission is in JSON. I haven’t found all the mission dialogue in the cpp files yet… Going to have to pretty soon though :-/
Someone who knows the code well enough should really put a quick-builder thread, with details on how to relatively quickly add new stuff. Something like:
If you want to add a new mission:
- Add new mission title in
- Add new mission dialogue in
- add new mission goal in
- etc.
If you want to add a new building:
- create file in
- set spawn details in
- etc.
Would help new people get into helping the project if there was an instruction list for the simpler stuff.
Missions are defined in data/json/npcs/missiondef.json and data/json/npcs/npcs.json.
There’s a bunch of hard-coded parsing behind the scenes, but I’m pretty sure you can add a new quests without adding new code.
Each type of NPC in npcs.json can have a “mission_offered” string, like
"mission_offered" : "MISSION_OLD_GUARD_REP_1"
Each mission is defined in missiondef.json, like so:
{
"id": "MISSION_OLD_GUARD_REP_1",
"type": "mission_definition",
"name": "Kill Bandits",
"goal": "MGOAL_ASSASSINATE",
"dialogue": {
"describe": "We need help...",
"offer": "I don't like sending untested men into the field but if you have stayed alive so far you might have some skills. There are at least a pair of bandits squatting in a local cabin, anyone who preys upon civilians meets a quick end... execute both of them for their crimes. Complete this and the Old Guard will consider you an asset in the region.",
"accepted": "Contractor, I welcome you aboard.",
"rejected": "The States will remain a wasteland unless good men choose to save it.",
"advice": "They might suspect you are coming, keep an eye out for traps.",
"inquire": "Have you completed your mission?",
"success": "The Old Guard thanks you for eliminating the criminals. You won't be forgotten.",
"success_lie": "What good does this do us?",
"failure": "It was a lost cause anyways..."
}
}
The important bits here are the “name”, which is what is displayed in your Missions list, the dialogue, which I think is more or less self-explanatory, and the goal. Goals are semi-harded from this list:
MGOAL_FIND_ANY_ITEM, MGOAL_FIND_ITEM - find some item or items
MGOAL_GO_TO_TYPE - move to a specific type of location
MGOAL_KILL_MONSTER - kill a specific monster
MGOAL_ASSASSINATE - kill a specific NPC
MGOAL_KILL_MONSTER_SPEC - kill a bunch of monsters
I don’t think you can currently implement anything but MGOAL_GO_TO_TYPE or MGOAL_FIND_ITEM without some C++ support for the “start” function. I’m working to fix that, but stuff takes time.
However, you can implement fetch quests! This is the scavenger quest from the Tacoma Commune:
{
"id": "MISSION_RANCH_SCAVENGER_4",
"type": "mission_definition",
"name": "Make 12 Molotov Cocktails",
"goal": "MGOAL_FIND_ITEM",
"difficulty": 5,
"value": 50000,
"item": "molotov",
"count": 12,
"dialogue": { blah blah blah }
}
there’s technically a start function, but all it does it build up the Tacoma Commune - it’s not strictly relevant to the quest.
I think you can also implement MGOAL_GO_TO_TYPE but you’d have to experiment.
I’m pretty sure the dialogue bits are just standard dynamic lines for npcs, which are heavily documented in doc/NPCs.md.
I’ll try to add a “how to contribute” doc/thread, though it’d would mostly be pointers to other, existing documentation.
Thanks for the breakdown! Maybe my next dialogue step then will be to set up some new overmap terrain types and associated NPC quests to go there.
First pass (general overview, setup, and recipes) here:
I’ll add more as I have time.
Is there a way to specify a category of items for a retrieval quest? The ones I’ve been noticing so far seem to be for a single specific item. But for the merchant canned food quest I’m working on, I would like any canned food to qualify, as there’s no reason to prefer one over another. Also, how many cans seems good for a fetch quest?
“item” needs to be a single item. Fortunately for you, canned foods are actually instances of the “can_food” container item with different contents, so I think the mission will take “can_food” just fine. Opened cans are “can_food_unsealed” so the player won’t be able to turn in empty cans.
I can add an "items": [ "item1_id", "item2_id", ... ]
list option, but I don’t want to do that right now because I’m trying to move some more of mission_start into JSON.
Canned food is pretty common, so 12 for a minor quest, 30 for a major quest? I mean, the Evac center expects you to turn in 25 plutonium cells and they don’t give you the keys to the place or anything.
30 cans it is. 12 is just too few, as my real goal is to make the evac center storage room look more full, and 12 cans just won’t do that. Might increase it if it still happens to look empty after I add in the quest-end trigger to populate that room.
Seems fine. Do you happen to have a way to place all the loot onto those shelves? Would be really cool after several missions to see the room rather full up.
Not sure if you or anyone would know how to make entering the room a trigger to have the guards warn you. Then attack you if you took items or entered a second time
Turns out that “can_food” also accepts empty tin cans. Any idea how to make it only accept full tin cans?
I’d have to go fix some issues in the mission code and I have a different big project I’m working on right now. Ping me in a week or two.
Can you give me a TLDR of where and what changes are needed? I might be able to change things around if I have a bit of guidance around what needs to be done.
Sure! src/mission.cpp’s is_complete() currently has this bit:
case MGOAL_FIND_ITEM: {
inventory tmp_inv = u.crafting_inventory();
// TODO: check for count_by_charges and use appropriate player::has_* function
if( !tmp_inv.has_amount( type->item_id, item_count ) ) {
return tmp_inv.has_amount( type->item_id, 1 ) && tmp_inv.has_charges( type->item_id, item_count );
}
if( npc_id != -1 && npc_id != _npc_id ) {
return false;
}
}
return true;
so you’ll want to add some logic to:
- tell the mission code that for this mission, empty containers aren’t acceptable
- include that check in the above logic.
For the first bit, you’d add
bool no_empties = false;
to struct mission_type
in mission.h, and
assign( jo, was_loaded, "no_empties", no_empties" );
to mission_type::load
in missiondef.cpp.
For the second bit, you’d add something here like:
if( type->no_empties ) {
// whatever logic detects empty stuff
}
which I think involves finding the actual items in the inventory and checking their content.
Please debug carefully because I am making educated guesses here and may not be describing a fully correct solution and I’m also probably skipping some bits that seem obvious to me but may confuse you since you don’t know the code as well.
That seems like a bit of a hacky way to fix the issue. Thinking it might be better to add an MGOAL_FIND_ITEM_GROUP mission type, and then just define a list of items in item_groups.json, which would make it more reusable. Wouldn’t be restricted to a particular container type, but could define arbitrary lists for later missions, in case someone wants a more eclectic group of acceptable items.
Confusingly there already exists a cannedfood item group, but it contains things that are not cans, like toastems. So I’ll have to define a new item list too for this mission.
Sure, go with the better solution.