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

Optional NPC Unique ID: something we've needed for a while. #57419

Open
I-am-Erk opened this issue May 4, 2022 · 4 comments
Open

Optional NPC Unique ID: something we've needed for a while. #57419

I-am-Erk opened this issue May 4, 2022 · 4 comments
Labels
<Bugfix> This is a fix for a bug (or closes open issue) [C++] Changes (can be) made in C++. Previously named `Code` Code: Infrastructure / Style / Static Analysis Code internal infrastructure and style <Enhancement / Feature> New features, or enhancements on existing [JSON] Changes (can be) made in JSON NPC / Factions NPCs, AI, Speech, Factions, Ownership <Suggestion / Discussion> Talk it out before implementing

Comments

@I-am-Erk
Copy link
Contributor

I-am-Erk commented May 4, 2022

Is your feature request related to a problem? Please describe.

We currently don't give NPCs any kind of consistent unique ID aside from their names, which can be randomly generated, not do we track NPCs that should be unique, aside from if we make conditional EoCs for that purpose.

Solution you would like.

Add an optional field "unique_id" to "place_npcs" in mapgen.

      "place_npcs": [
        { "class": "guard", "x": 38, "y": 4, "unique_id": "RC_lobbyguard1" },
        { "class": "guard", "x": 38, "y": 7, "unique_id": "RC_lobbyguard2" },
        { "class": "refugee_beggar2", "x": 55, "y": 2, "unique_id": "dino_dave" }
     ]

The reason to specify this in mapgen, rather than the NPC definition, is illustrated here: Those guards are generated from the same NPC definition, but given different unique IDs, allowing us to do something like have an EoC script cause the lobby guards to react in a specific way. Presently that is not possible, as these guards have randomly generated names. To make it possible we'd have to make each one a unique NPC with the same name every time it spawns, because to target an NPC we must use its name.

If an NPC has a unique ID, some special effects apply:

  • no other NPC with the same unique ID can be placed. if a place_npc command asks for the same unique ID, it fails silently (error in debug mode only)
  • we can target effects to an NPC unique ID using a syntax like:
"effect": [
  "target_unique": { 
    "id": "dino_dave",
    "loaded_only": true,
    "effect": "start_conversation"
  }
]

I think this is all pretty self explanatory. loaded_only defaults to false. If true, the targeted NPC is only affected if they are currently loaded in the reality bubble (another way to handle this would be with a radius option). I'm mostly including this because it can help error trap some things, eg if we have an NPC John_Bailey who can spawn with the same unique ID in the refugee center or in the exodii base, this lets us issue commands to that NPC locally (such as telling him to move somewhere) without having to worry about which location he is currently in.

We do already have syntax to target an NPC by name, but since a unique ID is unique, this requires a lot less troubleshooting and fixing up. It is also much more concise on the JSON end.

Future Directions

Refer to Unique ID in text snippets

Further support for unique IDs might include things like text snippets to refer to a unique ID by their name, even if their name is randomly generated (eg: <name_UID:dino_dave>). This would open the way for more procedurally generated NPCs that can still react to each other. If we do this, we should also start distinguishing NPC's names from their titles, and perhaps giving them a few more names like 'familiar name' and 'polite name' so that we can do things like:

"name": "Dino Dave",
"familiar_name": "Dave",
"polite_name": "Mr. Dave",

Otherwise our snippets will look pretty dumb, like:
"Could you do me a favour and take this note to Dino Dave, Beggar for me?"

Assigning unique ID to non-unique characters

Although this wouldn't do much initially, I think where this tool could really shine is in making random NPC followers start to take on roles. We could follow up with an effect "assign_unique_id". This would allow us to take a randomly generated NPC and slot them into a story role, probably based on their backstory and job, allowing them to become a recurring major character even though they spawned procedurally and their role was adopted through random events. For example, that random doctor you met and spoke to might be assigned a unique ID like "desperate_doctor". From then on, using the snippets system above, we can start having the NPC marked as desperate_doctor respond to specific EoCs and events, interact with the NPC curious_scientist in specific ways, and anything else we'd do with a specific unique NPC. If your desperate doctor died, the unique_id system would allow a new one to get assigned by the same series of events, but otherwise, recruiting another NPC that could have been desperate_doctor would fail to assign the unique ID, keeping them - well, unique.

Describe alternatives you have considered.

This is not strictly necessary at present. We can do all of this with a combination of EoCs and making locations unique instead of NPCs. However, this is one of those bits of infrastructure that we probably will need at some point and that can expand into a number of useful places. Almost every use of this I have currently listed could be done through a combination of unique traits and conditionals, but the amount of JSON coding for it and the room for error is exponentially larger than just recognizing that, overall, we're going to need some way to mark an NPC as unique and refer back to them as such, and since names are random in this game, it's better to do it with an ID token.

Additional context

This code would save a lot of work in random encounters by cutting out a few areas of error checking to ensure a random encounter doesn't pop up twice, but I actually thought of this in the context of trying to write code to move an NPC and realizing that it's currently very hard and error prone because we have to account for the fact that any given NPC might appear twice.

@I-am-Erk I-am-Erk added <Enhancement / Feature> New features, or enhancements on existing NPC / Factions NPCs, AI, Speech, Factions, Ownership <Suggestion / Discussion> Talk it out before implementing [JSON] Changes (can be) made in JSON [C++] Changes (can be) made in C++. Previously named `Code` Code: Infrastructure / Style / Static Analysis Code internal infrastructure and style 0.G Project Freeze labels May 4, 2022
@I-am-Erk I-am-Erk added this to To do in NPC dialog overhaul via automation May 4, 2022
@PatrikLundell
Copy link
Contributor

I think there may be a use for a locally unique ID and/or role ID as well. That would allow you to (eventually) have e.g. bossy guard, nervous guard, and cocky guard assigned to random (or fixed) encounters in some combination where randomly generated individuals take on these roles and their dialogs would be driven by their roles.

@I-am-Erk
Copy link
Contributor Author

I-am-Erk commented May 5, 2022

Yeah that's a good thought, we could have a series of identifier strings. Aside from unique id, the job string could just be what is displayed after the name, eg. james bond, spy would respond to effects targeting job: spy. We could also potentially use a non-unique ID that works like the unique ID in every way except multiple NPCs can have it.

Some of the problem would be that the uniqueness of the unique id helps limit the types of bugs we have to trap

@I-am-Erk I-am-Erk added the <Bugfix> This is a fix for a bug (or closes open issue) label May 5, 2022
@I-am-Erk
Copy link
Contributor Author

I-am-Erk commented May 5, 2022

After discussion with @Ramza13 it's possible we'll try to squeeze this in as a bugfix in this cycle, since it would help solve a lot of potential errors with NPCs.

@I-am-Erk
Copy link
Contributor Author

I-am-Erk commented May 6, 2022

Reviewing concerns with the unique spawn stuff, an initial implementation of this probably is going to need to only target transient NPCs like random spawns. I'm trying to think of a way we can work out the spawning of faction bases in the short term, a non unique ID might be the answer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
<Bugfix> This is a fix for a bug (or closes open issue) [C++] Changes (can be) made in C++. Previously named `Code` Code: Infrastructure / Style / Static Analysis Code internal infrastructure and style <Enhancement / Feature> New features, or enhancements on existing [JSON] Changes (can be) made in JSON NPC / Factions NPCs, AI, Speech, Factions, Ownership <Suggestion / Discussion> Talk it out before implementing
Development

No branches or pull requests

3 participants