package game import ( "fmt" "strings" "thehouseoficarus/internal/net" "thehouseoficarus/internal/player" ) // runEnterSteps evaluates a room's on_enter block for the player. The first // trigger whose Condition passes wins; its Steps run as a scripted sequence // (room-locked, so steps are skipped if the player immediately leaves). func (g *Game) runEnterSteps(sess *net.Session, roomID int) { room, err := g.World.LoadRoom(roomID) if err != nil || len(room.OnEnter) == 0 { return } p := sess.Player if p == nil { return } g.runTrigger(sess, p, room.OnEnter, roomID, nil, true) } // runExitSteps evaluates a room's on_exit block for the player. It fires the // first matching trigger as a non-room-locked sequence using the room being // left as the reference room (broadcasts/spawn resolve to the old room). It is // invoked before the player's RoomID is updated to the destination. func (g *Game) runExitSteps(sess *net.Session, roomID int) { room, err := g.World.LoadRoom(roomID) if err != nil || len(room.OnExit) == 0 { return } p := sess.Player if p == nil { return } g.runTrigger(sess, p, room.OnExit, roomID, nil, false) } // applyFlagMutations sets global and player flags. It is the player-scoped // flag step of applyStep, called once per step that carries set_global_flags // and/or set_player_flags. scopeGlobal sets globals directly in applyStep // instead (so world-scoped cascades don't reach back into this helper). func (g *Game) applyFlagMutations(p *player.Player, setGlobalFlags, setPlayerFlags map[string]any) { g.GlobalFlags.SetAll(setGlobalFlags) if len(setPlayerFlags) > 0 { for k, v := range setPlayerFlags { g.setPlayerFlag(p, k, v) } } } func (g *Game) BroadcastRespawns() { respawns := g.World.FlushObjRespawns() for _, st := range respawns { def, err := g.ObjectStore.Load(st.DefID) if err != nil || !def.IsGatherable() { continue } cfg := def.Gather if cfg.RespawnBroadcast == "" { continue } name := def.Name if idx := st.Index + 1; len(g.World.FindObjInstances(st.RoomID, st.DefID)) > 1 { name += fmt.Sprintf(" [%d]", idx) } msg := strings.ReplaceAll(cfg.RespawnBroadcast, "{name}", name) if g.Hub != nil { for _, sess := range g.Hub.PlayersInRoom(st.RoomID) { sess.WriteLine(g.colorize(sess, "broadcast", msg)) } } } } // isCharLive reports whether the named player is currently connected via the // given session (used by older helpers that still reference it). func (g *Game) isCharLive(name string, sess *net.Session) bool { g.charsMu.Lock() defer g.charsMu.Unlock() return g.loggedInChars[name] == sess }