Goal
Module: goal.lua
Overview
The Goal module implements a soccer easter egg. When a ball object enters the LR_Goal boundary — and a specific named marker (_global_soccergoal 0x000b0982) exists in the world — it plays a Fiona voice-over, awards the player 100,000 cash via MrxPmc, and removes the goal from the world (fires only once). This is a small, self-contained example of a boundary-triggered reward.
Inheritance
- Inherits from: none — base/utility module
- Imports:
MrxUtil,MrxVoSequence,MrxPmc
Instance pattern
Not the Inheritable/rich-instance pattern, and not a class-factory either — confirmed from source: a single module-level global table, tEvents = tEvents or {}, with no Create/Delete/setmetatable anywhere. Each activated object gets a small sub-table entry in tEvents, not a full instance object with inherited methods:
tEvents[uGuid]: initialized to{}inOnActivate. Its only stored field is.GoalVO, the handle of theEvent.Boundarysubscription created inSetupGoal, so it can be deleted on deactivate.
tEventsis a module-level global, not per-instance state — every activated object shares the one table, keyed byuGuid. This is fine here because entries are cleaned up inOnDeactivate.
Functions
OnActivate(uGuid)
Called when the goal instance is activated. It logs a debug message and sets up an event to call SetupGoal once the object leaves hibernation.
OnDeactivate(uGuid)
Called when the goal instance is deactivated. It logs a debug message, deletes any associated voice-over events, and cleans up the tEvents table entry for this GUID.
SetupGoal(uBallGuid)
Registers an Event.Boundary subscription (filter {uBallGuid, LR_Goal, "enter"}) so that when the ball crosses into the LR_Goal boundary, the reward fires. Guarded twice: it only registers if Pg.GetGuidByName("LR_Goal") resolves, and the reward body only runs if Pg.GetGuidByName("_global_soccergoal 0x000b0982") also exists. On success it plays VO cue Fiona.va3fio12 via MrxVoSequence.Start, calls MrxPmc.AddCashQty(100000), and Object.Removes the LR_Goal object. The boundary handle is stored in tEvents[uBallGuid].GoalVO.
Events
Event.ObjectHibernation— registered inOnActivatewith filter{uGuid, "awake"}; firesSetupGoalonce the object leaves hibernation. This is a realEvent.Createsubscription.Event.Boundary— registered inSetupGoal(see above) to detect the ball enteringLR_Goal.
Note: OnActivate/OnDeactivate are engine lifecycle callbacks, not event subscriptions.
Notes for modders
- Reward knob:
MrxPmc.AddCashQty(100000)inSetupGoalsets the payout; the VO cue is the literal"Fiona.va3fio12". Both are hardcoded in the closure. - One-shot:
Object.Remove(Pg.GetGuidByName("LR_Goal"))destroys the goal on trigger, so it fires exactly once per session — there is no re-arm path. - Named-object dependency: the effect only works if two named world objects exist — the boundary
LR_Goaland the marker_global_soccergoal 0x000b0982. If either is missing (e.g. renamed in a mod), nothing happens silently.