This is intended to make it easier to define actor-specific action messages. Usage is straightforward:
alice: Person 'Alice' 'Alice'
"She looks like the first person you'd turn to in a problem. "
isProperName = true
isHer = true
;
+NPCActionMessages
okayTakeMsg = '{You/he} carefully take{s} {the dobj/him}. '
;
This defines the NPC Alice and then gives her her own action message object. In this case we just define a single custom message, for okayTakeMsg.
The module defines three classes for message objects:
ActorActionMessages which uses MessageHelper as its base. You probably donāt want to use it unless youāre planning on re-defining all the action messages for an actor
PlayerActionMessages which uses playerActionMessages as its base. This is for player characters
NPCActionMessages which uses npcActionMessages as its base. This is for, obviously, NPCs.
This is all really simple and is only a couple dozen lines of code, but Iāve been doing a lot of NPC scripting stuff and so wanted a modular way to do per-actor and per-āroleā (that is, for characters that are doing a specific activity or are taking part in a specific event) action messages. So here it is.
By āroleā I just mean something thatās changing the characterās behavior in a global (that is, it applies to everything theyāre doing, not just one specific task) but situational and temporary way.
To use a specific example, think of a gambler thatās playing a game of chance and is doing poorly. Maybe they start acting nervous, maybe, angry, or something else depending on the character of the specific gambler. This would influence not just the game-specific actions (like checking their cards or making a bet), but random other actions they might do in the course of a game (having a sip of their drink or whatever).
Instead of putting those situational inflections in conditional code in a single action message object, what Iām doing is using different action message objects.
Itās for anything thatās handled as an action as opposed to being handled as a bespoke script. Say the action is Alice picking up a pebble. In terms of the underlying code, that can look like:
"Alice looks left and right and then surreptitiously
pockets the pebble. ";
pebble.moveInto(alice);
ā¦or it could look likeā¦
newActorAction(alice, Take, pebble);
In the first case you donāt need custom action message objects, because you can just output whatever you want. Even if you do use a message object in this case (to make it easier to localize, for example), you could still just use a one-off message:
modify playerActionMessages
aliceTakesPebble = 'Alice looks left and right and then surreptitiously
pockets the pebble'
;
But on the other hand if youāre doing it the second wayā¦just using TakeAction with an NPCā¦then itāll be using the standard T3/adv3 mechanisms for figuring out what to output for the action. By default the only customization is based on whether the actor taking the action is the player character or an NPC (selecting playerActionMessages or npcActionMessages, respectively).
The module is just intended to make it easier to have more action message objects. One obvious use case is character-specific message objects, but the main idea is just to make it easier to group related messages together (so they can be toggled on and off together).
Allows you to declare message objects on ActorState instances as well as Actor instances
Supports declaring travel messages (sayArriving, sayDeparting, and so on) on the message object
You can already define travel messages on actors and actor states in stock adv3, so the second bit is just intended to make it easier to put everything in one place.
Declaring travel messages when NPC is in AccompanyingState should be the very first thing to do under adv3⦠the ambiguity, to put it mildly, of adv3ās stock
NPC comes with you
should be, frankly, on the top of every TADS3/Adv3 coderās modify listā¦
I was clearly not far enough in my TADS3/adv3 journey to recognize the value of this at the time. I do now! Just spent almost a full day trying to figure out why action messages donāt override cleanly like iobj/dobj messages do. Eventually just
bobActionMessages : npcActionMessages
okayFollowModeMsg = 'Bob eagerly nods his willingness to follow you.
And resists the urge to grab your shirt. '
alreadyFollowModeMsg = '\"Still following,\" says Bob, wondering why
he didn\'t just grab your shirt. '
;
bob : Person 'bob' 'Bob'
"You know, it\'s Bob!"
isProperName = true
isHim = true
// standard Dobj override works fine
cannotKissActorMsg = 'Eww, cooties. '
// initiated action messages by do not work the same, below has NO EFFECT
okayFollowModeMsg = 'Bob grabs your shirt to make sure he is right behind you. '
// instead must do..
getActionMessageObj() { return bobActionMessages; }
;
Apparently havenāt crossed the āsearch the forumā line as robustly as thought. Will be giving this one a try!
I think the secret is that the utility varies inversely with the size and complexity of the module. These little ~100 line modules are nice, easy to understand, useful.
On the other hand Iāve been trying to get back to doing procgen ādungeonā design using the 10k+ line module I wrote for it, and Iām spending more time trying to remember how everything works (and/or adding new features that overlap with features I forgot I added last time I was working on it) than writing new code.
Iāve got a huge amount of work invested in the WIP, and out of all of it I think the code Iāve gotten the most use/re-use out of is a handful of single-line #define macros for type-checking.