diff options
| author | historia <[not public]> | 2026-06-25 15:40:48 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-06-25 15:40:48 -0400 |
| commit | abd612c15799f604e671e83dc7c410ed2b44185f (patch) | |
| tree | 0597ca92350de73aac2a7cf26b2f2d6595dac0cc /internal/game/action_steal.go | |
| parent | 2725e2927a1595c7b100d942d1f14146252adeb7 (diff) | |
| download | thehouseoficarus-abd612c15799f604e671e83dc7c410ed2b44185f.tar.gz | |
slop refactor
Diffstat (limited to 'internal/game/action_steal.go')
| -rw-r--r-- | internal/game/action_steal.go | 477 |
1 files changed, 0 insertions, 477 deletions
diff --git a/internal/game/action_steal.go b/internal/game/action_steal.go deleted file mode 100644 index 65c684c..0000000 --- a/internal/game/action_steal.go +++ /dev/null @@ -1,477 +0,0 @@ -package game - -import ( - "fmt" - "math/rand" - "sort" - "strconv" - "strings" - - "thehouseoficarus/internal/action" - "thehouseoficarus/internal/combat" - "thehouseoficarus/internal/engine" - "thehouseoficarus/internal/net" - "thehouseoficarus/internal/object" - "thehouseoficarus/internal/player" - "thehouseoficarus/internal/world" -) - -func (g *Game) executeSteal(sess *net.Session, args []string, rawInput string) { - p := sess.Player - g.cancelAction(p) - if len(args) == 0 { - g.doSteal(sess, "") - } else { - g.doSteal(sess, strings.Join(args, " ")) - } -} - -var stallGuardTalk = &action.TalkConfig{ - Nodes: map[string]action.TalkNode{ - "start": { - Message: "Caught you red-handed! You have three options, thief.", - Options: []action.TalkOption{ - {Text: "\"I'll pay a fine. (500 credits)\"", Goto: "bribe", Condition: &action.Condition{MinCredits: 500}}, - {Text: "\"Take me to jail.\"", Goto: "jail"}, - {Text: "\"You'll have to catch me first!\"", Goto: "fight"}, - }, - }, - "bribe": { - Message: "Smart choice. Hand over 500 credits and we'll forget this happened.", - Action: &action.NodeAction{Cost: 500}, - Options: []action.TalkOption{{Text: "\"Fine, take it.\"", End: true}}, - }, - "jail": { - Message: "Off to the detention cell with you!", - Action: &action.NodeAction{Teleport: 162}, - Options: []action.TalkOption{{Text: "(You are dragged away)", End: true}}, - }, - "fight": { - Message: "Then defend yourself!", - Action: &action.NodeAction{SetFlags: map[string]any{"guard_hostile": true}}, - Options: []action.TalkOption{{Text: "(The guard attacks!)", End: true}}, - }, - }, -} - -var stealSuccess = action.SuccessFormula{ - Base: 0.5, - PerLevel: 0.03, - Cap: 0.95, -} - -func (g *Game) doSteal(sess *net.Session, input string) { - p := sess.Player - - if combat.GetCombat(p.Name) != nil { - sess.WriteLine("You can't do that during combat!") - return - } - - g.cancelAction(p) - - targetType, mob, objDef, errMsg := g.resolveStealTarget(sess, p, input) - if errMsg != "" { - sess.WriteLine(errMsg) - return - } - - g.startSteal(sess, p, targetType, mob, objDef) -} - -func (g *Game) resolveStealTarget(sess *net.Session, p *player.Player, input string) (targetType string, mob *world.MobInstance, objDef *object.ObjectDef, errMsg string) { - input = strings.ToLower(strings.TrimSpace(input)) - instanceIdx := -1 - searchName := input - - if dotPos := strings.Index(input, "."); dotPos > 0 { - if n, err := strconv.Atoi(input[:dotPos]); err == nil && n > 0 { - instanceIdx = n - 1 - searchName = input[dotPos+1:] - } - } - - roomMobs := g.MobStore.MobsInRoom(p.RoomID) - var stealMobs []*world.MobInstance - for _, m := range roomMobs { - if m.StealTable != "" { - stealMobs = append(stealMobs, m) - } - } - - roomObjs := g.World.AllObjInstances(p.RoomID) - var stealObjs []*object.ObjectDef - for _, st := range roomObjs { - def, err := g.ObjectStore.Load(st.DefID) - if err != nil || def.StealTable == "" { - continue - } - stealObjs = append(stealObjs, def) - } - - if input == "" { - if len(stealMobs) == 0 && len(stealObjs) == 0 { - return "", nil, nil, "There's nothing here to steal from." - } - - uniqueMobDefs := make(map[string]bool) - for _, m := range stealMobs { - uniqueMobDefs[m.DefID] = true - } - - if len(stealMobs) > 0 && len(stealObjs) == 0 { - if len(uniqueMobDefs) <= 1 { - return "mob", stealMobs[0], nil, "" - } - } - if len(stealObjs) > 0 && len(stealMobs) == 0 { - uniqueObjDefs := make(map[string]bool) - for _, o := range stealObjs { - uniqueObjDefs[o.ID] = true - } - if len(uniqueObjDefs) <= 1 { - return "object", nil, stealObjs[0], "" - } - } - return "", nil, nil, "Steal from what?" - } - - var matchingMobs []*world.MobInstance - for _, m := range stealMobs { - if m.MatchQuality(searchName) >= world.MatchPrefix { - matchingMobs = append(matchingMobs, m) - } - } - sort.Slice(matchingMobs, func(i, j int) bool { - return matchingMobs[i].InstanceID < matchingMobs[j].InstanceID - }) - - if len(matchingMobs) > 0 { - uniqueDefs := make(map[string]bool) - for _, m := range matchingMobs { - uniqueDefs[m.DefID] = true - } - if len(uniqueDefs) > 1 && instanceIdx < 0 { - return "", nil, nil, "Which one?" - } - if instanceIdx >= 0 && instanceIdx < len(matchingMobs) { - return "mob", matchingMobs[instanceIdx], nil, "" - } - if len(matchingMobs) == 1 { - return "mob", matchingMobs[0], nil, "" - } - for i := range matchingMobs { - if instanceIdx == i || instanceIdx < 0 { - return "mob", matchingMobs[i], nil, "" - } - } - } - - var matchingObjs []*object.ObjectDef - for _, o := range stealObjs { - if object.WordPrefixMatch(searchName, o.Name) { - matchingObjs = append(matchingObjs, o) - } - } - if len(matchingObjs) > 1 { - return "", nil, nil, "Which one?" - } - if len(matchingObjs) == 1 { - return "object", nil, matchingObjs[0], "" - } - - return "", nil, nil, "There's nothing here to steal from." -} - -func (g *Game) startSteal(sess *net.Session, p *player.Player, targetType string, mob *world.MobInstance, objDef *object.ObjectDef) { - var stealTable string - var stealLevel int - var stealXP int - var stealSpeed float64 - var targetName string - var targetID string - var mobInstanceID string - var objDefID string - var guardMob string - guardWatching := false - - if targetType == "mob" { - stealTable = mob.StealTable - stealLevel = mob.StealLevel - stealXP = mob.StealXP - stealSpeed = mob.StealSpeed - targetName = mob.Name - targetID = mob.InstanceID - mobInstanceID = mob.InstanceID - - if stealTable == "" { - sess.WriteLine(fmt.Sprintf("You can't steal from the %s.", targetName)) - return - } - if thievingLevel := p.Level(player.Thieving); stealLevel > 0 && thievingLevel < stealLevel { - sess.WriteLine(fmt.Sprintf("You need level %d thieving to steal from the %s.", stealLevel, targetName)) - return - } - if mob.HP <= 0 { - sess.WriteLine("That is already dead.") - return - } - if combat.IsMobInCombat(mob.InstanceID) { - sess.WriteLine(fmt.Sprintf("The %s is busy.", targetName)) - return - } - } else { - stealTable = objDef.StealTable - stealLevel = objDef.StealLevel - stealXP = objDef.StealXP - stealSpeed = objDef.StealSpeed - targetName = objDef.Name - targetID = objDef.ID - objDefID = objDef.ID - guardMob = objDef.GuardMob - - if stealTable == "" { - sess.WriteLine(fmt.Sprintf("You can't steal from the %s.", targetName)) - return - } - if thievingLevel := p.Level(player.Thieving); stealLevel > 0 && thievingLevel < stealLevel { - sess.WriteLine(fmt.Sprintf("You need level %d thieving to steal from the %s.", stealLevel, targetName)) - return - } - - if guardMob != "" { - guard := g.findGuardInRoom(p.RoomID, guardMob) - if guard != nil { - timerKey := fmt.Sprintf("%d:%s", p.RoomID, objDefID) - if _, exists := g.guardWatchTimers[timerKey]; !exists { - g.guardWatchTimers[timerKey] = 0 - } - guardWatching = g.isGuardWatching(p.RoomID, objDefID) - } - } - } - - if p.FirstFreeSlot() == -1 { - sess.WriteLine("Your inventory is too full!") - return - } - - sess.WriteLine(fmt.Sprintf("You attempt to steal from the %s...", targetName)) - - g.broadcastAction(sess, "\n%s glances around the room.", p.Name) - - p.Action = &action.Action{ - Type: action.TypeSteal, - TargetID: targetID, - TargetName: targetName, - WaitLeft: engine.ToTicks(stealSpeed), - Data: &action.StealData{ - TargetType: targetType, - StealTable: stealTable, - StealLevel: stealLevel, - StealXP: stealXP, - StealSpeed: stealSpeed, - TargetName: targetName, - MobInstanceID: mobInstanceID, - ObjDefID: objDefID, - GuardMob: guardMob, - GuardWatching: guardWatching, - }, - } -} - -func (g *Game) advanceSteal(sess *net.Session, p *player.Player) { - d := p.Action.Data.(*action.StealData) - targetType := d.TargetType - stealTable := d.StealTable - stealLevel := d.StealLevel - stealXP := d.StealXP - stealSpeed := d.StealSpeed - targetName := d.TargetName - guardMob := d.GuardMob - guardWatching := d.GuardWatching - - if targetType == "mob" { - mobInstanceID := d.MobInstanceID - mob := g.MobStore.GetInstance(mobInstanceID) - if mob == nil || mob.HP <= 0 || mob.RoomID != p.RoomID { - sess.WriteLine("Your target is gone.") - g.cancelAction(p) - return - } - if combat.IsMobInCombat(mob.InstanceID) { - sess.WriteLine(fmt.Sprintf("The %s is busy.", targetName)) - g.cancelAction(p) - return - } - d.StealLevel = mob.StealLevel - d.StealXP = mob.StealXP - d.StealSpeed = mob.StealSpeed - stealLevel = mob.StealLevel - stealXP = mob.StealXP - stealSpeed = mob.StealSpeed - } else { - objDefID := d.ObjDefID - found := false - for _, st := range g.World.AllObjInstances(p.RoomID) { - if st.DefID == objDefID && !st.Depleted { - found = true - break - } - } - if !found { - sess.WriteLine("Your target is gone.") - g.cancelAction(p) - return - } - objDef, err := g.ObjectStore.Load(objDefID) - if err == nil { - d.StealLevel = objDef.StealLevel - d.StealXP = objDef.StealXP - d.StealSpeed = objDef.StealSpeed - stealLevel = objDef.StealLevel - stealXP = objDef.StealXP - stealSpeed = objDef.StealSpeed - d.GuardMob = objDef.GuardMob - guardMob = objDef.GuardMob - - if guardMob != "" { - guard := g.findGuardInRoom(p.RoomID, guardMob) - if guard != nil { - timerKey := fmt.Sprintf("%d:%s", p.RoomID, objDefID) - if _, exists := g.guardWatchTimers[timerKey]; !exists { - g.guardWatchTimers[timerKey] = 0 - } - guardWatching = g.isGuardWatching(p.RoomID, objDefID) - d.GuardWatching = guardWatching - } - } - } - } - - level := p.Level(player.Thieving) - chance := action.SuccessChance(stealSuccess, level, stealLevel) - if guardWatching { - chance *= 0.5 - if chance < 0.05 { - chance = 0.05 - } - } - - if rand.Float64() < chance { - dt, err := action.LoadDropTable(g.DataDir, stealTable) - if err != nil || len(dt.Drops) == 0 { - sess.WriteLine("You steal nothing of value.") - } else { - drop := action.ResolveDrop(g.DataDir, dt.Drops) - if drop == nil || drop.ItemID == "" { - sess.WriteLine("You steal nothing of value.") - } else { - g.giveStealLoot(sess, p, drop) - } - } - - if stealXP > 0 { - g.awardSkillXP(sess, p, player.Thieving, stealXP) - } - - g.AccountStore.SaveCharacter(p) - - if p.FirstFreeSlot() == -1 { - sess.WriteLine("Your inventory is full.") - g.cancelAction(p) - return - } - - p.Action.WaitLeft = engine.ToTicks(stealSpeed) - } else { - if targetType == "mob" { - mobInstanceID := d.MobInstanceID - mob := g.MobStore.GetInstance(mobInstanceID) - sess.WriteLine(fmt.Sprintf("The %s notices you! They attack!", targetName)) - g.cancelAction(p) - if mob != nil && mob.HP > 0 { - g.startCombat(sess, p, mob) - } - } else { - if guardMob != "" && guardWatching { - guard := g.findGuardInRoom(p.RoomID, guardMob) - if guard != nil { - sess.WriteLine("You fumble and the Guard spots you!") - g.cancelAction(p) - g.startStealGuardTalk(sess, p, guard) - return - } - } - sess.WriteLine("You fail to steal anything.") - p.Action.WaitLeft = engine.ToTicks(stealSpeed) - } - } -} - -func (g *Game) giveStealLoot(sess *net.Session, p *player.Player, drop *action.DropEntry) { - qty := drop.Quantity - if qty <= 0 { - qty = 1 - } - - if drop.ItemID == "credits" { - p.Credits += qty - sess.WriteLine(g.colorize(sess, "credits_pickup", fmt.Sprintf("You steal %d credits.", qty))) - return - } - - name := drop.ItemID - lootDef, _ := g.ItemStore.Load(drop.ItemID) - if lootDef != nil { - name = lootDef.Name - } - - freeSlot := p.FirstFreeSlot() - if freeSlot == -1 { - g.World.AddGroundItem(p.RoomID, drop.ItemID, qty) - sess.WriteLine(fmt.Sprintf("You steal %s but your inventory is full. It falls to the ground.", g.itemColorize(sess, lootDef, name))) - return - } - - p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: drop.ItemID, Quantity: qty}) - sess.WriteLine(fmt.Sprintf("You steal %s.", g.itemColorize(sess, lootDef, name))) -} - -func (g *Game) findGuardInRoom(roomID int, guardDefID string) *world.MobInstance { - mobs := g.MobStore.MobsInRoom(roomID) - for _, m := range mobs { - if m.DefID == guardDefID && m.HP > 0 { - return m - } - } - return nil -} - -const guardWatchDuration = 8 -const guardLookAwayDuration = 4 -const guardCycleLength = guardWatchDuration + guardLookAwayDuration - -func (g *Game) isGuardWatching(roomID int, objDefID string) bool { - key := fmt.Sprintf("%d:%s", roomID, objDefID) - counter := g.guardWatchTimers[key] - return counter%guardCycleLength < guardWatchDuration -} - -func (g *Game) startStealGuardTalk(sess *net.Session, p *player.Player, guardMob *world.MobInstance) { - cfg := stallGuardTalk - node, ok := cfg.Nodes["start"] - if !ok { - sess.WriteLine("The Guard glares at you but says nothing.") - return - } - - p.Action = &action.Action{ - Type: "talk", - TargetID: guardMob.DefID, - TargetName: guardMob.Name, - Data: &action.TalkData{Node: "start", Cfg: cfg, StealGuard: true}, - } - - g.showTalkNode(sess, node) -} |
