Skip to content

Commit

Permalink
Add "What everyone knows" context
Browse files Browse the repository at this point in the history
  • Loading branch information
cswendrowski committed Jun 30, 2024
1 parent 76d3269 commit ffdd69e
Show file tree
Hide file tree
Showing 9 changed files with 51 additions and 20 deletions.
8 changes: 5 additions & 3 deletions scripts/apps/ActoriNpcConfiguration.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ export default class ActoriNpcConfiguration extends FormApplication {
const config = this.actor.flags["intelligent-npcs"] ?? {};

if ( foundry.utils.isEmpty(config) ) {
config["summary"] = "You are a generic NPC named Bob.";
config["summary"] = "A generic NPC named Bob.";
config["whatEveryoneKnows"] = "You don't know anything about this person beyond what you can glean from their appearance.";
config["appearance"] = "Farmer attire";
}

Expand Down Expand Up @@ -59,8 +60,8 @@ export default class ActoriNpcConfiguration extends FormApplication {
const selectedPageConfig = page?.flags["intelligent-npcs"] ?? {};

const hasMessageHistory = config["messageHistory"] && config["messageHistory"].length > 0;
const hasDifferentMemory = config["memory"] && config["memory"].length > 0
&& config["memory"] !== selectedPageConfig["memory"];
const hasDifferentMemory = config.memory?.length > 0
&& config.memory !== selectedPageConfig.memory;
const hasDifferentName = (this.actor && page) ? this.actor.name !== page.name : false;

const canSwap = (pageId === "none") || !(hasMessageHistory || hasDifferentMemory || hasDifferentName);
Expand Down Expand Up @@ -238,6 +239,7 @@ export default class ActoriNpcConfiguration extends FormApplication {

// Clear the customizations
await this.actor.setFlag("intelligent-npcs", "summary", "");
await this.actor.setFlag("intelligent-npcs", "whatEveryoneKnows", "");
await this.actor.setFlag("intelligent-npcs", "appearance", "");
await this.actor.setFlag("intelligent-npcs", "messageHistory", []);
await this.actor.setFlag("intelligent-npcs", "memory", "");
Expand Down
1 change: 1 addition & 0 deletions scripts/apps/IntelligentNpcsBrowser.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ export default class IntelligentNpcsBrowser extends Application {
"img": img,
"personality": npc.fields.personality,
"summary": npc.fields.summary,
"whatEveryoneKnows": npc.fields.whatEveryoneKnows,
"airtableId": npc.id,
}
});
Expand Down
9 changes: 6 additions & 3 deletions scripts/hooks/createChatMessage.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,14 @@ export async function getConfig(npc) {
...selectedPageConfig
};
if ( actorConfig.summary ) config.summary = actorConfig.summary;
if ( actorConfig.whatEveryoneKnows ) config.whatEveryoneKnows = actorConfig.whatEveryoneKnows;
if ( actorConfig.appearance ) config.appearance = actorConfig.appearance;
if ( actorConfig.messageHistory ) config.messageHistory = actorConfig.messageHistory;
if ( actorConfig.memory ) config.memory = actorConfig.memory;

if ( page.name !== npc.name ) {
config.summary = config.summary.replace(new RegExp(page.name, "g"), npc.name);
config.whatEveryoneKnows = config.whatEveryoneKnows.replace(new RegExp(page.name, "g"), npc.name);
config.appearance = config.appearance.replace(new RegExp(page.name, "g"), npc.name);
config.background = config.background.replace(new RegExp(page.name, "g"), npc.name);
config.personality = config.personality.replace(new RegExp(page.name, "g"), npc.name);
Expand All @@ -117,7 +119,7 @@ async function chatCompletion(npc, message, scene) {
// If the speaker has a summary, load it
const speakerToken = scene.tokens.get(message.speaker.token);
const speakerConfig = await getConfig(speakerToken?.actor);
const speakerSummary = speakerConfig?.summary ?? "";
const speakerWhatEveryoneKnows = speakerConfig?.whatEveryoneKnows ?? "";
const speakerAppearance = speakerConfig?.appearance ?? "";

// Get the subarea context if it exists
Expand All @@ -129,7 +131,7 @@ async function chatCompletion(npc, message, scene) {
"message": message.content,
"tokenNames": allTokenNames,
"speaker": message.speaker.alias ?? (message.user.isGM ? "GM" : "Unknown"),
"speakerSummary": speakerSummary,
"speakerSummary": speakerWhatEveryoneKnows,
"speakerAppearance": speakerAppearance,
"sceneContext": sceneContext + "\n\n" + subareaContext,
"worldContext": worldContext,
Expand Down Expand Up @@ -320,7 +322,8 @@ export async function createChatMessage(message, options, userId) {
// If the target is not an AI, return
const aiNpcs = scene.tokens.filter(t => t.actor?.flags["intelligent-npcs"]?.enabled === true).map(t => t.actor._id);
const speakerIsTarget = targetedNpc._id === message.speaker.actor;
if (!aiNpcs.includes(targetedNpc._id) || speakerIsTarget) return;
const hidden = targetedNpc?.token?.hidden || targetedToken?.document?.hidden;
if ( !aiNpcs.includes(targetedNpc._id) || speakerIsTarget || hidden ) return;

// get the message history from the npc flags
const messageHistory = targetedNpc.getFlag("intelligent-npcs", "messageHistory") || [];
Expand Down
4 changes: 4 additions & 0 deletions styles/intelligent-npcs.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion styles/intelligent-npcs.css.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions styles/intelligent-npcs.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
#client-settings {
select[name='intelligent-npcs.model'] {
width: 100%;
}
}

.chat-message {
.message-header {
.message-sender {
Expand Down
8 changes: 4 additions & 4 deletions templates/actor-inpc-configuration.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@

<fieldset>
<legend>Public</legend>
<p class="notes">These fields override any journal selected, and will be read by Intelligent NPCs, so don't include any info that others shouldn't generally know</p>
<p class="notes">These fields override any journal selected, and will be read by other Intelligent NPCs, so don't include any info that others shouldn't generally know</p>

<div class="form-group-stacked">
<label>Summary</label>
<textarea class="form-control" rows=2 name="summary" placeholder="{{actor.name}} is a generic person who is well known for existing." maxlength="500">{{config.summary}}</textarea>
<p class="notes">A quick summary of what others generally know about this person. Write in third person. Overrides the Journal details if set. Max length: 500 characters</p>
<label>What Everyone Knows</label>
<textarea class="form-control" rows="4" name="whatEveryoneKnows" placeholder="{{actor.name}} is a generic person who is well known for existing." maxlength="500">{{config.whatEveryoneKnows}}</textarea>
<p class="notes">A quick summary of what others generally know about this person. Write in third person. Max length: 500 characters</p>
</div>

<div class="form-group-stacked">
Expand Down
18 changes: 12 additions & 6 deletions templates/journal/page-inpc-edit.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,32 @@
<h2><input type="text" name="name" value="{{journal.name}}"></h2>
</div>

<div class="form-group-stacked" style="margin: 1rem;">
<label>Summary</label>
<textarea class="form-control" rows="4" name="summary" placeholder="{{journal.name}} is a generic NPC usable in any setting">{{config.summary}}</textarea>
<p class="notes">A quick summary of this NPC for human reference. Intelligent NPCs do not read this field.</p>
</div>

<fieldset>
<legend>Public</legend>
<p class="notes">These fields will be read by Intelligent NPCs, so don't include any info that others shouldn't generally know. These fields should be written in third person.</p>
<legend>Public Info</legend>
<p class="notes">These fields will be read by other Intelligent NPCs, so don't include any info that others shouldn't generally know. These fields should be written in third person.</p>

<div class="form-group-stacked">
<label>Summary</label>
<textarea class="form-control" rows="4" name="summary" placeholder="{{actor.name}} is a generic person who is well known for existing." maxlength="500">{{config.summary}}</textarea>
<label>What Everyone Knows</label>
<textarea class="form-control" rows="4" name="whatEveryoneKnows" placeholder="{{journal.name}} is a generic person who is well known for existing." maxlength="500">{{config.whatEveryoneKnows}}</textarea>
<p class="notes">A quick summary of what others generally know about this person. Write in third person. Max length: 500 characters</p>
</div>

<div class="form-group-stacked">
<label>Appearance</label>
<textarea class="form-control" rows="4" name="appearance" placeholder="{{actor.name}} wears standard street wear." maxlength="500">{{config.appearance}}</textarea>
<textarea class="form-control" rows="4" name="appearance" placeholder="{{journal.name}} wears standard street wear." maxlength="500">{{config.appearance}}</textarea>
<p class="notes">What this character looks like to others. Write in third person. Max length: 500 characters</p>
</div>
</fieldset>


<fieldset>
<legend>Personality</legend>
<legend>Private Info</legend>
<p class="notes">The following fields should be written in first person.</p>

<div class="form-group-stacked">
Expand Down
15 changes: 12 additions & 3 deletions templates/journal/page-inpc-view.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,24 @@

<h2>Summary</h2>
<p>{{config.summary}}</p>

<h2>Appearance</h2>
<p>{{config.appearance}}</p>
</div>
</div>

<hr>

<h1>Public Info</h1>

<h2>What Everyone Knows</h2>
<p>{{config.whatEveryoneKnows}}</p>

<h2>Appearance</h2>
<p>{{config.appearance}}</p>

{{#if user.isGM}}
<hr>

<h1>Private Info</h1>

<h2>Background</h2>
<p>{{config.background}}</p>

Expand Down

0 comments on commit ffdd69e

Please sign in to comment.