Skip to content

Expand Script Ordering, Item Interactions, Containers, and Roundtime Support - #40

Open
Plateaus wants to merge 51 commits into
jonradoff:mainfrom
Plateaus:feature/script-ordering-events
Open

Plateaus wants to merge 51 commits into
jonradoff:mainfrom
Plateaus:feature/script-ordering-events

Conversation

@Plateaus

Copy link
Copy Markdown

Huge release here.

This PR significantly expands the LOFP engine’s support for the original script system and corrects command ordering so original game scripts can intercept actions before built-in behavior occurs.

The overall goal is to reproduce original LOFP behavior from the .SCR data rather than hard-code individual rooms or items.

Summary

  • Script execution and command ordering

    • Reworked item interaction handling so IFPREVERB executes before normal command behavior.
    • CLEARVERB now correctly prevents the normal command from continuing when a script has handled or cancelled the action.
    • IFVERB executes after IFPREVERB when the preverb does not block the command.
    • Script-generated player, room, and GM messages are preserved and returned through command results.
    • Script-triggered movement is preserved when an item interaction changes rooms.
    • Expanded script handling across room items and player-held items rather than limiting scripts to room objects.
    • Added/expanded handling for script-driven verbs including TOUCH, CONCENTRATE, SMELL, SEARCH, GET, DROP, PUT, and existing generic item-interaction verbs.
  • Player item scripting

    • Reworked generic item interaction so actual inventory objects are used rather than operating on disposable copies.
    • Player items in inventory, worn equipment, and wielded equipment can participate in script interactions.
    • A temporary RoomItem script context is created when necessary because the legacy script engine operates on room-item-style values.
    • Changes to ITEMVAL1 through ITEMVAL5 are copied back to the real InventoryItem.
    • Player state is saved after script execution so script-controlled item values persist between commands.
    • Matching supports item adjectives including Adj1 and Adj3.
    • This fixes stateful scripted objects such as the evil circlet, whose internal ITEMVAL state must survive one command and affect later commands.
  • GET ordering and scripted scenery

    • Changed GET so the requested object is resolved before normal pickup restrictions are applied.
    • IFPREVERB GET now runs before rejecting an item because it is fixed, extremely heavy, a portal, manuscript, etc.
    • This allows the original scripts to make normally un-gettable scenery respond to GET.
    • CLEARVERB from a GET script stops normal pickup.
    • Normal fixed/weight/portal restrictions are applied only after the script has declined to handle the action.
    • Preserved player changes made by GET scripts.
    • Preserved handling for NEWPUT cases where a script changes the room item slice while GET is executing.
  • DROP scripting

    • Inventory-item IFPREVERB DROP executes before ordinary dropping.
    • Scripts can remove or transform the item themselves and use CLEARVERB to stop the normal inventory-to-room transfer.
    • This supports original behavior such as scripted items disappearing or changing when dropped.
    • Player changes made by DROP scripts are persisted.
  • Money dropping and pickup

    • Added explicit handling for dropping currency amounts such as gold, silver, and copper.
    • Dropped currency becomes room MONEY items rather than ordinary inventory objects.
    • Currency quantities are deducted from the appropriate player denomination.
    • Dropped money broadcasts an appropriate room message.
    • Money room items convert back into player currency when picked up.
    • Currency normalization carries copper into silver and silver into gold as appropriate.
  • PUT and IFPREVERB2

    • Expanded PUT handling around the original two-object script model.
    • Object char.status GMCP sent with wrong gender #1 is the item being put.
    • Object GMCP core.hello message sent wrong way #2 is the destination.
    • Scripts are given a chance to intercept PUT before ordinary container logic.
    • This allows IFPREVERB2 PUT to work on scripted destinations that are not necessarily ordinary containers, such as special scenery objects.
    • CLEARVERB stops ordinary PUT when the script handled the action.
  • IN and ON containers

    • Expanded container support from only IN to both IN and ON.
    • PUT <item> IN <container> and PUT <item> ON <container> are parsed separately.
    • Explicit CONTAINER IN / CONTAINER ON definitions must match the requested relationship.
    • Legacy generic containers continue to behave as IN containers.
    • Carried-container PUT behavior continues to use IN.
    • ON containers do not require an OPEN state.
    • IN containers still enforce open/closed state.
    • Capacity and interior-volume checks work for both forms.
    • Different full-container messages are produced for IN versus ON.
    • Room PUT items continue to use the existing IsPut / PutIn representation, with the destination definition determining whether the relationship is IN or ON.
    • Added room-change notification when items are placed into room containers.
  • LOOK and container presentation

    • Normalized LOOK AT <thing> so the target is resolved like examining the object rather than treating at as part of the noun.
    • Expanded LOOK container behavior to support LOOK IN and LOOK ON.
    • The requested preposition must match the container’s defined relationship.
    • Original room-authored ITEM IN / ITEM ON descriptions take precedence over dynamically generated content lists.
    • Only IN containers require an open state before their contents can be viewed.
    • Empty ON containers report that there is nothing on them rather than saying they are empty.
  • Portable/container contents

    • Container contents continue to transfer into InventoryItem.Contents when a room container is picked up.
    • Child room items are removed from the room after becoming contents of the carried container.
    • Container lookup now recognizes both IN and ON container definitions where appropriate.
  • SEARCH scripting and roundtime

    • Bare SEARCH now checks IFPREVERB SEARCH -1 before performing the built-in search.
    • CLEARVERB lets the room script replace ordinary SEARCH entirely.
    • Normal SEARCH now explicitly sets a five-second roundtime.
    • Both RoundTime and RoundTimeExpiry are maintained for SEARCH.
    • Normal search/player-detection behavior remains in place when no script blocks it.
  • Roundtime enforcement

    • Added roundtime enforcement directly to directional movement.
    • This was necessary because commands such as E, W, etc. call doMove() directly and bypass GO.
    • Movement during active roundtime returns a countdown such as [Wait 5 seconds...].
    • Added the same protection to doGo() for portal/object-based GO actions that do not necessarily use normal directional movement.
    • Script-set roundtime can therefore prevent movement instead of existing only as a displayed variable. - Manually tested SEARCH roundtime: movement was blocked at 5, 3, and 1 seconds and succeeded after expiration.
    • Added script-variable handling so EQUAL ROUNDTIME <seconds> updates the expiry time as well as the script-visible roundtime value.
    • This is intended to support original scripted actions such as the evil circlet’s EQUAL ROUNDTIME 18.
  • CONCENTRATE

    • Routed CONCENTRATE <item> through normal item interaction instead of immediately returning the generic “You concentrate deeply” response.
    • This allows item IFPREVERB / IFVERB CONCENTRATE scripts to execute.
    • The generic response remains the fallback when an item script does not handle the action.
  • SMELL

    • Bare SMELL now checks for a room-level script before falling back to the ordinary emote.
    • Targeted SMELL continues through item interaction.
    • This fixed original room IFVERB SMELL -1 behavior without creating a special implementation for individual rooms.
  • TOUCH / IFTOUCH

    • Connected TOUCH command processing to the script engine’s existing IFTOUCH support.
    • Original item TOUCH scripts can now fire instead of being ignored.
    • Tested against original scripted objects, including alignment checks and CLEARVERB behavior.
  • Scripted state values

    • Expanded script variable/state handling used by original item scripts.
    • ITEMVAL mutations now survive commands on carried items.
    • Added roundtime assignment behavior tied to real expiration timestamps.
    • BODYPOINTS script assignments are clamped to the player’s valid health range instead of allowing healing above maximum Body.
    • Existing script variables such as item values can therefore be used as persistent state machines by original scripts.
  • Evil circlet compatibility work

    • GAZE and CONCENTRATE can reach the circlet’s original scripts while the item is carried/worn.
    • ITEMVAL5 changes persist and affect subsequent commands.
    • EQUAL ROUNDTIME 18 is recognized and updates player roundtime.
    • Script healing through repeated ADD BODYPOINTS is clamped to maximum Body.
    • IFTOUCH, alignment checks, ECHO, POSITION, and CLEARVERB paths were exercised.
    • Delayed PLREVENT / CONTPLREVENT execution is not part of this implementation yet; those actions currently remain future work for true timed multi-stage scripts.
  • Script-first architecture

    • Continued moving command processing toward the original engine model:
      resolve command/target → run matching script → CLEARVERB stops command → otherwise perform built-in behavior.
    • This avoids adding room-specific or item-specific Go hacks when the original .SCR files already contain the intended behavior.
    • GET, DROP, PUT, SEARCH and generic item interactions were brought closer to this ordering.
  • Room/item movement and notifications

    • Preserved script-driven room movement and resulting LOOK output.
    • Preserved old-room departure/new-room arrival messaging.
    • Entry scripts continue to run after scripted movement.
    • Added item add/remove room notifications in newly handled item-transfer paths.
  • Direction and GO handling

    • Roundtime is checked in doMove() so abbreviated/full compass commands cannot bypass it.
    • Roundtime is also checked in doGo() for object/portal movement.
    • Direction fallback between UP/ABOVE and DOWN/BELOW was cleaned up during this work.
  • Parser/game-world support

    • Extended the parser and game-world structures required by the script/container work.
    • Parser boundaries and script block handling were expanded as additional original script constructs were encountered.
    • Added/updated representation needed for room item descriptions and container relationships.
    • These changes support preserving more information from the original .SCR files instead of reimplementing that information in command code.
  • Original script data

    • Small corrections were made to:

      • original/scripts/DEJOBAAN.SC1
      • original/scripts/FAYDINDR.SCR
      • original/scripts/FORESTER.SCR
      • original/scripts/ITEM1.SCR
    • These are tiny changes compared with the engine work: 1–3 changed lines per file.

    • They were committed with the corresponding parser/script compatibility work rather than constituting large rewrites of the original data.

  • Formatting/refactoring

    • A significant portion of the apparent diff size is formatting and restructuring of functions touched while implementing these systems.
    • Several previously compressed Go expressions were expanded by formatting.
    • The functional commit nevertheless contains substantial accumulated engine work and is larger than the original commit title suggests.

Validation

Branch:

feature/script-ordering-events

Commit:

d8da4b3 Add roundtime enforcement and script item persistence fixes

Local HEAD and remote are identical:

d8da4b3 (HEAD -> feature/script-ordering-events, origin/feature/script-ordering-events)

Working tree is clean and the branch is up to date with the remote.

Commit size:

8 files changed, 1649 insertions(+), 610 deletions(-)

Files changed:

engine/internal/engine/engine.go
engine/internal/engine/scripts.go
engine/internal/gameworld/types.go
engine/internal/scriptparser/parser.go
original/scripts/DEJOBAAN.SC1
original/scripts/FAYDINDR.SCR
original/scripts/FORESTER.SCR
original/scripts/ITEM1.SCR

go test ./... passes for the entire Go module, including:

github.com/jonradoff/lofp/internal/engine

go vet ./... reports one outstanding warning:

internal/engine/spells.go:890:3: unreachable code

That warning does not prevent compilation or the tests from passing and is outside the primary script-ordering work in this PR.

Known follow-up work

PLREVENT / CONTPLREVENT still need real delayed script continuation rather than synchronous execution.

The circlet’s scripted 18-second roundtime should still receive an explicit end-to-end test, although normal SEARCH/movement roundtime enforcement has been manually verified.

KILL PLAYER is recognized by the script engine but still needs correct death semantics; current testing showed the rest of the TOUCH script executing without actually reducing the player to a dead state.

Open/closed and locked/unlocked item state ultimately need independent state axes. The original scripts can represent combinations such as CLOSED + UNLOCKED, while the current single State representation cannot fully model both simultaneously.

There is also one movement behavior worth regression-testing: the previous explicit sitting/lying check was removed from doGo() during this accumulated work, so movement while sitting/lying should be confirmed to be blocked through the intended shared movement path.

csanburn1966 and others added 30 commits May 1, 2026 07:52
Run item preverb scripts for GET and DROP
Run item preverb scripts for equipment commands
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants