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/cmd_look.go | |
| parent | 2725e2927a1595c7b100d942d1f14146252adeb7 (diff) | |
| download | thehouseoficarus-abd612c15799f604e671e83dc7c410ed2b44185f.tar.gz | |
slop refactor
Diffstat (limited to 'internal/game/cmd_look.go')
| -rw-r--r-- | internal/game/cmd_look.go | 770 |
1 files changed, 0 insertions, 770 deletions
diff --git a/internal/game/cmd_look.go b/internal/game/cmd_look.go index 5cdc15d..a1ad708 100644 --- a/internal/game/cmd_look.go +++ b/internal/game/cmd_look.go @@ -7,9 +7,7 @@ import ( "strings" "thehouseoficarus/internal/color" - "thehouseoficarus/internal/combat" "thehouseoficarus/internal/net" - "thehouseoficarus/internal/object" "thehouseoficarus/internal/player" "thehouseoficarus/internal/world" ) @@ -50,721 +48,6 @@ func (g *Game) doLook(sess *net.Session) { g.showRoomPlayers(sess, p, room) } -func (g *Game) showRoomName(sess *net.Session, p *player.Player, room *world.Room) { - sess.WriteLines( - "", - fmt.Sprintf("%s (%s)", g.colorize(sess, "room_name", room.Name), g.colorize(sess, "room_number", fmt.Sprintf("#%d", room.ID))), - ) -} - -func (g *Game) showRoomDescription(sess *net.Session, p *player.Player, room *world.Room) []string { - descWidth := p.OptionInt("room_desc_width") - if descWidth <= 0 { - descWidth = 70 - } - rawLines := wrapText(g.roomDescription(sess, room), descWidth) - mode := g.colorMode(sess) - roomDescSpec := g.resolveColor(sess, "room_desc") - lines := make([]string, len(rawLines)) - for i, l := range rawLines { - lines[i] = color.ExpandTagsDefault(mode, roomDescSpec, l) - } - return lines -} - -// roomDescription resolves the room's effective description for this player, -// picking the first conditional variant whose condition passes, else the base -// Description. -func (g *Game) roomDescription(sess *net.Session, room *world.Room) string { - for _, d := range room.Descriptions { - if d.Condition == nil || g.checkCondition(sess, d.Condition) { - return d.Text - } - } - return room.Description -} - -// resolveObjDesc resolves the description an object shows to this player. For an -// object with conditional Descriptions, the first variant whose condition -// passes wins; if none pass the object is reported as not present (false), so -// look falls through as if it were not there. Objects without Descriptions use -// their plain Description and are always present. -func (g *Game) resolveObjDesc(sess *net.Session, def *object.ObjectDef) (string, bool) { - if len(def.Descriptions) == 0 { - return def.Description, true - } - for _, d := range def.Descriptions { - if d.Condition == nil || g.checkCondition(sess, d.Condition) { - return d.Text, true - } - } - return "", false -} - -func (g *Game) showRoomMobs(sess *net.Session, p *player.Player, room *world.Room) []string { - mobs := g.MobStore.MobsInRoom(p.RoomID) - if len(mobs) == 0 { - return nil - } - sort.Slice(mobs, func(i, j int) bool { - iDamaged := mobs[i].HP < mobs[i].MaxHP - jDamaged := mobs[j].HP < mobs[j].MaxHP - if iDamaged != jDamaged { - return iDamaged - } - return mobs[i].InstanceID < mobs[j].InstanceID - }) - var lines []string - lines = append(lines, "") - playerLevel := p.CombatLevel() - for _, m := range mobs { - hp := "" - if m.HP < m.MaxHP { - if m.IsTask() { - pct := 0 - if m.MaxHP > 0 { - pct = (m.MaxHP - m.HP) * 100 / m.MaxHP - } - hp = fmt.Sprintf(" [%d%% complete]", pct) - } else { - hp = fmt.Sprintf(" [%s/%dhp]", color.Render(g.colorMode(sess), color.Parse("167"), fmt.Sprint(m.HP)), m.MaxHP) - } - } - var desc string - if combat.IsMobInCombat(m.InstanceID) { - def, err := g.MobStore.LoadDef(m.DefID) - if err == nil && len(def.CombatDescriptions) > 0 { - target := combat.GetMobTarget(m.InstanceID) - pattern := def.CombatDescriptions[randInt(len(def.CombatDescriptions))] - desc = " " + fmt.Sprintf(pattern, target) - } - } else if m.IdleDescription != "" { - desc = fmt.Sprintf(" %s", m.IdleDescription) - } - displayName := m.Name - if !m.Unique { - displayName = "A " + m.Name - } - mobColor := "mob" - if m.Protected { - mobColor = "protected_mob" - } - mobLevel := mobCombatLevel(m) - levelStr := g.levelColorize(sess, playerLevel, mobLevel, fmt.Sprintf("(level %d)", mobLevel)) - lines = append(lines, fmt.Sprintf("%s %s%s%s", g.colorize(sess, mobColor, displayName), levelStr, hp, desc)) - } - return lines -} - -func (g *Game) showRoomObjects(sess *net.Session, p *player.Player, room *world.Room) []string { - objs := g.World.AllObjInstances(p.RoomID) - if len(objs) == 0 { - return g.showFarmPatches(sess, p) - } - var lines []string - lines = append(lines, "") - grouped := make(map[string]int) - var order []string - for _, o := range objs { - if _, ok := grouped[o.DefID]; !ok { - order = append(order, o.DefID) - } - grouped[o.DefID]++ - } - for _, objID := range order { - count := grouped[objID] - def, err := g.ObjectStore.Load(objID) - if err != nil { - continue - } - - if def.Hidden { - continue - } - - if farmPatchDefIDs[objID] { - continue - } - - type instInfo struct { - idx int - depleted bool - sharedMax int - sharedCur int - respawnIn int - quality int - } - var instances []instInfo - for i := 0; i < count; i++ { - st := g.World.GetObjState(p.RoomID, objID, i) - if st == nil { - continue - } - instances = append(instances, instInfo{ - idx: i + 1, - depleted: st.Depleted, - sharedMax: int(st.SharedMax), - sharedCur: st.SharedTimer, - respawnIn: int(st.DepleteTimer), - quality: int(st.Quality), - }) - } - multi := len(instances) > 1 - showTimers := p.OptionBool("depletion") - - var freshIdxs []int - var timed, depleted []instInfo - for _, ins := range instances { - if ins.depleted { - depleted = append(depleted, ins) - } else if ins.sharedMax > 0 && ins.sharedCur < ins.sharedMax { - timed = append(timed, ins) - } else { - freshIdxs = append(freshIdxs, ins.idx) - } - } - - roomDesc := def.InRoomDescription - if roomDesc != "" { - roomDesc = color.ExpandTags(g.colorMode(sess), roomDesc) - } - coloredName := g.objColorize(sess, def, def.Name) - coloredPlural := g.objColorize(sess, def, def.Name+"s") - - if len(freshIdxs) > 0 { - var line string - if roomDesc != "" { - line = roomDesc - } else if len(freshIdxs) == 1 { - line = fmt.Sprintf("A %s is here.", coloredName) - } else { - line = fmt.Sprintf("%d %s are here.", len(freshIdxs), coloredPlural) - } - var suffix string - if multi && (len(timed) > 0 || len(depleted) > 0) { - suffix = fmt.Sprintf(" [%s]", joinInts(freshIdxs)) - } - qualityTimer := "" - if showTimers && len(instances) > 0 && instances[0].quality > 0 { - qualityTimer = fmt.Sprintf(" (Burning for %d more ticks)", instances[0].quality) - } - lines = append(lines, fmt.Sprintf("%s%s%s", line, suffix, qualityTimer)) - } - - for _, ins := range timed { - var line string - if roomDesc != "" { - line = roomDesc - } else { - line = fmt.Sprintf("A %s is here.", coloredName) - } - tag := "" - if multi { - tag = fmt.Sprintf(" [%d]", ins.idx) - } - timer := "" - if showTimers { - timer = fmt.Sprintf(" (despawn: %d/%d)", ins.sharedCur, ins.sharedMax) - } - lines = append(lines, fmt.Sprintf("%s%s%s", line, tag, timer)) - } - - for _, ins := range depleted { - var line string - if roomDesc != "" { - line = roomDesc - } else { - line = fmt.Sprintf("A %s is here.", coloredName) - } - tag := "" - if multi { - tag = fmt.Sprintf(" [%d]", ins.idx) - } - timer := "" - if showTimers { - timer = fmt.Sprintf(" (respawns in %d ticks)", ins.respawnIn) - } - lines = append(lines, fmt.Sprintf("%s (depleted)%s%s", line, tag, timer)) - } - } - - lines = append(lines, g.showFarmPatches(sess, p)...) - return lines -} - -func (g *Game) showGroundItems(sess *net.Session, p *player.Player, room *world.Room) []string { - ground := g.World.GroundItemsDetailed(p.RoomID) - if len(ground) == 0 { - return nil - } - showDespawn := p.OptionBool("despawn") - showReserve := p.OptionBool("reserve") - - type displayLine struct { - name string - quantity int - colorName string - annotation string - } - - type groupKey struct { - itemID string - despawnTimer int - } - - var lines []displayLine - groups := make(map[groupKey]*displayLine) - var groupOrder []groupKey - - for _, info := range ground { - def, err := g.ItemStore.Load(info.ItemID) - name := info.ItemID - if err == nil { - name = def.Name - } - coloredName := g.itemColorize(sess, def, name) - - if info.ReservedFor != "" { - var parts []string - if showReserve { - parts = append(parts, fmt.Sprintf("reserved for %s %dt", info.ReservedFor, info.ReserveTimer)) - } else { - parts = append(parts, "reserved") - } - if showDespawn && !info.IsSpawn { - parts = append(parts, fmt.Sprintf("despawns %dt", info.DespawnTimer)) - } - annotation := "" - if len(parts) > 0 { - annotation = fmt.Sprintf(" (%s)", strings.Join(parts, ", ")) - } - lines = append(lines, displayLine{ - name: name, - quantity: info.Quantity, - colorName: coloredName, - annotation: annotation, - }) - continue - } - - timerKey := -1 - if showDespawn && !info.IsSpawn { - timerKey = info.DespawnTimer - } - key := groupKey{itemID: info.ItemID, despawnTimer: timerKey} - - if existing, ok := groups[key]; ok { - existing.quantity += info.Quantity - } else { - annotation := "" - if showDespawn && !info.IsSpawn { - annotation = fmt.Sprintf(" (despawns %dt)", info.DespawnTimer) - } - dl := &displayLine{ - name: name, - quantity: info.Quantity, - colorName: coloredName, - annotation: annotation, - } - groups[key] = dl - groupOrder = append(groupOrder, key) - } - } - - for _, key := range groupOrder { - lines = append(lines, *groups[key]) - } - - sort.Slice(lines, func(i, j int) bool { - return strings.ToLower(lines[i].name) < strings.ToLower(lines[j].name) - }) - - var out []string - out = append(out, "") - out = append(out, "On the ground:") - - type fmtLine struct { - prefix string - annotation string - } - var fmtLines []fmtLine - maxPrefix := 0 - - for _, dl := range lines { - prefix := "" - if dl.quantity > 1 { - prefix = fmt.Sprintf(" %d x %s", dl.quantity, dl.colorName) - } else { - prefix = fmt.Sprintf(" %s", dl.colorName) - } - if visibleLen(prefix) > maxPrefix { - maxPrefix = visibleLen(prefix) - } - fmtLines = append(fmtLines, fmtLine{prefix, dl.annotation}) - } - - for _, l := range fmtLines { - if l.annotation != "" { - pad := maxPrefix + 1 + (len(l.prefix) - visibleLen(l.prefix)) - out = append(out, fmt.Sprintf("%-*s%s", pad, l.prefix, l.annotation)) - } else { - out = append(out, l.prefix) - } - } - return out -} - -func (g *Game) showRoomExits(sess *net.Session, p *player.Player, room *world.Room) { - if len(room.Exits) > 0 { - sess.WriteLine("") - if p.OptionBool("exits") { - sess.WriteLine("Exits:") - type exitLine struct { - dir string - targetName string - } - var lines []exitLine - maxDirLen := 0 - for _, dir := range world.ExitOrder { - exitDef, ok := room.Exits[dir] - if !ok { - continue - } - coloredDir := g.colorize(sess, "exit_direction", string(dir)) - targetRoom, err := g.World.LoadRoom(exitDef.Room) - targetName := g.colorize(sess, "room_number", fmt.Sprintf("#%d", exitDef.Room)) - if err == nil { - targetName = g.colorize(sess, "exit_name", targetRoom.Name) - } - if exitDef.Condition != nil && !g.checkCondition(sess, exitDef.Condition) { - targetName += " (blocked)" - } - lines = append(lines, exitLine{coloredDir, targetName}) - if visibleLen(coloredDir) > maxDirLen { - maxDirLen = visibleLen(coloredDir) - } - } - for _, l := range lines { - pad := maxDirLen + (len(l.dir) - visibleLen(l.dir)) - sess.WriteLine(fmt.Sprintf(" %-*s - %s", pad, l.dir, l.targetName)) - } - } else { - sess.Write("Exits: ") - first := true - for _, dir := range world.ExitOrder { - if _, ok := room.Exits[dir]; ok { - if !first { - sess.Write(", ") - } - sess.Write(g.colorize(sess, "exit_direction", string(dir))) - first = false - } - } - sess.WriteLine("") - } - } -} - -func (g *Game) showRoomPlayers(sess *net.Session, p *player.Player, room *world.Room) { - others := g.Hub.PlayersInRoom(p.RoomID) - for _, other := range others { - if other != sess && other.Player != nil { - op := other.Player - line := fmt.Sprintf("\n%s is here", g.colorize(sess, "player_name", op.Name)) - if cs := combat.GetCombat(op.Name); cs != nil { - if mob := g.MobStore.GetInstance(cs.MobID); mob != nil && mob.HP > 0 { - name := mobDisplayName(mob, false) - if idx := mobInstanceIdx(mob, g.MobStore.MobsInRoom(p.RoomID)); idx > 0 { - name += fmt.Sprintf(" [%d]", idx) - } - line += fmt.Sprintf(" (fighting %s)", name) - } - } else if desc := g.playerActionDisplay(op); desc != "" { - line += ", " + desc - } - sess.WriteLine(line + ".") - } - } -} - -func (g *Game) doLookTarget(sess *net.Session, input string) { - p := sess.Player - lower := strings.ToLower(input) - - if exitDir := g.World.ResolveExit(lower); exitDir != "" { - room, err := g.World.LoadRoom(p.RoomID) - if err != nil { - sess.WriteLine("You can't see anything that way.") - return - } - exitDef, ok := room.Exits[exitDir] - if !ok { - sess.WriteLine("You can't see anything that way.") - return - } - if exitDef.Condition != nil && !g.checkCondition(sess, exitDef.Condition) { - msg := exitDef.BlockedMessage - if msg == "" { - msg = fmt.Sprintf("The way %s is blocked.", exitDir) - } - sess.WriteLine(msg) - return - } - g.World.SeedGroundItems(exitDef.Room) - g.seedRoomMobs(exitDef.Room) - origRoom := p.RoomID - p.RoomID = exitDef.Room - g.doLook(sess) - p.RoomID = origRoom - return - } - - var best *world.MobInstance - bestQ := world.MatchNone - for _, m := range g.MobStore.MobsInRoom(p.RoomID) { - q := m.MatchQuality(lower) - if q > bestQ { - bestQ = q - best = m - } - } - if best != nil { - mobColor := "mob" - if best.Protected { - mobColor = "protected_mob" - } - mobLevel := mobCombatLevel(best) - levelStr := g.levelColorize(sess, p.CombatLevel(), mobLevel, fmt.Sprintf("(level %d)", mobLevel)) - sess.WriteLines( - "", - fmt.Sprintf("%s %s", g.colorize(sess, mobColor, best.Name), levelStr), - ) - if best.IdleDescription != "" { - sess.WriteLine(best.IdleDescription) - } - sess.WriteLines( - "", - fmt.Sprintf("Attack: %d", best.Attack), - fmt.Sprintf("Strength: %d", best.Strength), - fmt.Sprintf("Defense: %d", best.Defense), - fmt.Sprintf("HP: %d/%d", best.HP, best.MaxHP), - ) - if best.StabDefense != 0 || best.SlashDefense != 0 || best.CrushDefense != 0 || - best.ScienceDefense != 0 || best.RangedDefense != 0 { - sess.WriteLines( - "", - "Defense bonuses:", - fmt.Sprintf(" Stab: %+d Slash: %+d Crush: %+d", best.StabDefense, best.SlashDefense, best.CrushDefense), - fmt.Sprintf(" Science: %+d Ranged: %+d", best.ScienceDefense, best.RangedDefense), - ) - } - if best.Weakness != "" { - sess.WriteLine(fmt.Sprintf("Weakness: %s", best.Weakness)) - } - return - } - - rawInstances := g.World.FindObjInstances(p.RoomID, lower) - - // Group matched object instances by definition, keeping only those visible - // to this player (an object whose conditional descriptions all fail is - // absent). If more than one distinct object matches, disambiguate. - var presentDefs []string - byDef := map[string][]world.ObjState{} - descByDef := map[string]string{} - for _, ist := range rawInstances { - def, err := g.ObjectStore.Load(ist.DefID) - if err != nil { - continue - } - text, present := g.resolveObjDesc(sess, def) - if !present { - continue - } - if _, seen := byDef[ist.DefID]; !seen { - presentDefs = append(presentDefs, ist.DefID) - descByDef[ist.DefID] = text - } - byDef[ist.DefID] = append(byDef[ist.DefID], ist) - } - - if len(presentDefs) > 1 { - sess.WriteLine("That's ambiguous, which one?") - for _, defID := range presentDefs { - if def, err := g.ObjectStore.Load(defID); err == nil { - sess.WriteLine(fmt.Sprintf(" %s", def.Name)) - } - } - return - } - - if len(presentDefs) == 1 { - instances := byDef[presentDefs[0]] - objDescText := descByDef[presentDefs[0]] - st := &instances[0] - def, _ := g.ObjectStore.Load(st.DefID) - - if st.DefID == "estate_directory" { - g.lookEstateDirectory(sess) - return - } - - sess.WriteLine("") - if len(instances) > 1 { - sess.WriteLine(fmt.Sprintf("%d %ss:", len(instances), def.Name)) - } - - if objDescText != "" && !strings.Contains(objDescText, "{quality}") { - sess.WriteLine(color.ExpandTags(g.colorMode(sess), objDescText)) - } - - if def.Safespot != nil { - realSt := g.World.GetObjState(p.RoomID, st.DefID, st.Index) - if realSt != nil { - levelStr := "intact" - if realSt.SafespotLevel <= 0 { - levelStr = fmt.Sprintf("intact (level %d/%d)", len(def.Safespot.Levels), len(def.Safespot.Levels)) - } else if realSt.SafespotLevel < len(def.Safespot.Levels) { - levelStr = fmt.Sprintf("degraded (level %d/%d)", realSt.SafespotLevel, len(def.Safespot.Levels)) - } else { - levelStr = fmt.Sprintf("intact (level %d/%d)", realSt.SafespotLevel, len(def.Safespot.Levels)) - } - blockInfo := "anything" - if def.Safespot.MaxBlockSize != "" { - blockInfo = fmt.Sprintf("up to %s mobs", def.Safespot.MaxBlockSize) - } - sess.WriteLine(fmt.Sprintf("Safespot: %s — blocks %s", levelStr, blockInfo)) - if len(realSt.SafespotOccupants) > 0 { - sess.WriteLine(fmt.Sprintf("Occupied by: %s", strings.Join(realSt.SafespotOccupants, ", "))) - } - } - } - - if p.OptionBool("depletion") { - for _, ist := range instances { - if ist.Depleted { - if len(instances) > 1 { - sess.WriteLine(fmt.Sprintf("%s %d: depleted, respawns in %d ticks.", def.Name, ist.Index+1, int(ist.DepleteTimer))) - } else { - sess.WriteLine(fmt.Sprintf("Depleted, respawns in %d ticks.", int(ist.DepleteTimer))) - } - } else if ist.SharedMax > 0 && float64(ist.SharedTimer) < ist.SharedMax { - if len(instances) > 1 { - sess.WriteLine(fmt.Sprintf("%s %d: despawn timer %d/%.0f.", def.Name, ist.Index+1, ist.SharedTimer, ist.SharedMax)) - } else { - sess.WriteLine(fmt.Sprintf("Despawn timer: %d/%.0f ticks.", ist.SharedTimer, ist.SharedMax)) - } - } - } - } - for _, ist := range instances { - if ist.Quality > 0 && strings.Contains(def.Description, "{quality}") { - desc := strings.ReplaceAll(def.Description, "{quality}", fmt.Sprintf("%.0f", ist.Quality)) - sess.WriteLine(color.ExpandTags(g.colorMode(sess), desc)) - } - } - - farmSuffix := g.farmObjSuffix(p, st.DefID, st.Index) - if farmSuffix != "" { - sess.WriteLine(farmSuffix) - } - return - } - - ground := g.World.GroundItems(p.RoomID) - for itemID := range ground { - def, err := g.ItemStore.Load(itemID) - if err != nil || !def.MatchesName(input) { - continue - } - sess.WriteLines( - "", - g.itemColorize(sess, def, def.Name), - color.ExpandTags(g.colorMode(sess), def.Description), - fmt.Sprintf("Value: %d credits", def.Value), - ) - g.showItemStats(sess, def) - return - } - - for i := 0; i < 28; i++ { - slot := p.InvSlot(i) - if slot == nil { - continue - } - def, err := g.ItemStore.Load(slot.ItemID) - if err != nil || !def.MatchesName(input) { - continue - } - lines := []string{ - "", - g.itemColorize(sess, def, def.Name), - color.ExpandTags(g.colorMode(sess), def.Description), - fmt.Sprintf("Value: %d credits", def.Value), - } - if slot.MaxQuality > 0 { - lines = append(lines, fmt.Sprintf("Has %d units of butane left.", slot.Quality)) - } - sess.WriteLines(lines...) - g.showItemStats(sess, def) - return - } - - others := g.Hub.PlayersInRoom(p.RoomID) - for _, other := range others { - if other == sess || other.Player == nil { - continue - } - op := other.Player - if strings.ToLower(op.Name) != lower { - continue - } - showPlayerInfo(g, sess, op) - return - } - - sess.WriteLine(fmt.Sprintf("There's no '%s' here.", input)) -} - -func showPlayerInfo(g *Game, sess *net.Session, p *player.Player) { - myP := sess.Player - theirLevel := p.CombatLevel() - levelStr := g.levelColorize(sess, myP.CombatLevel(), theirLevel, fmt.Sprint(theirLevel)) - sess.WriteLines( - "", - p.Name, - fmt.Sprintf("Combat Level: %s", levelStr), - fmt.Sprintf("HP: %d/%d", p.HP, p.MaxHP()), - "", - ) - - for _, s := range player.AllSkills { - level := p.Level(s) - sess.WriteLine(fmt.Sprintf("%-12s Level: %d", s, level)) - } - - sess.WriteLine("") - sess.WriteLine("Equipment:") - for _, slot := range EquipSlots { - itemID, ok := p.Equipment[slot] - if !ok { - continue - } - name := itemID - var itemDef *object.ItemDef - if def, err := g.ItemStore.Load(itemID); err == nil { - name = def.Name - itemDef = def - } - sess.WriteLine(fmt.Sprintf(" %-12s %s", slot, g.itemColorize(sess, itemDef, name))) - } - - if p.Description != "" { - sess.WriteLine("") - sess.WriteLine(p.Description) - } -} - func (g *Game) doExits(sess *net.Session) { p := sess.Player room, err := g.World.LoadRoom(p.RoomID) @@ -898,56 +181,3 @@ func (g *Game) executeLook(sess *net.Session, args []string, rawInput string) { func (g *Game) executeExits(sess *net.Session, args []string, rawInput string) { g.doExits(sess) } - -func (g *Game) showItemStats(sess *net.Session, def *object.ItemDef) { - s := def.Stats - hasAttack := s.StabAttack != 0 || s.SlashAttack != 0 || s.CrushAttack != 0 || - s.ScienceAttack != 0 || s.RangedAttack != 0 - hasDefense := s.StabDefense != 0 || s.SlashDefense != 0 || s.CrushDefense != 0 || - s.ScienceDefense != 0 || s.RangedDefense != 0 - hasOther := s.StrengthBonus != 0 || s.RangedStrength != 0 || - s.ScienceDamage != 0 || s.TechnologyBonus != 0 - - if !hasAttack && !hasDefense && !hasOther { - return - } - - sess.WriteLine("") - if hasAttack || hasDefense { - sess.WriteLine("Attack bonuses: Defense bonuses:") - sess.WriteLine(fmt.Sprintf(" Stab: %+4d Stab: %+4d", s.StabAttack, s.StabDefense)) - sess.WriteLine(fmt.Sprintf(" Slash: %+4d Slash: %+4d", s.SlashAttack, s.SlashDefense)) - sess.WriteLine(fmt.Sprintf(" Crush: %+4d Crush: %+4d", s.CrushAttack, s.CrushDefense)) - sess.WriteLine(fmt.Sprintf(" Science:%+4d Science:%+4d", s.ScienceAttack, s.ScienceDefense)) - sess.WriteLine(fmt.Sprintf(" Ranged: %+4d Ranged: %+4d", s.RangedAttack, s.RangedDefense)) - } - if hasOther { - sess.WriteLine("") - sess.WriteLine("Other bonuses:") - if s.StrengthBonus != 0 { - sess.WriteLine(fmt.Sprintf(" Melee strength: %+d", s.StrengthBonus)) - } - if s.RangedStrength != 0 { - sess.WriteLine(fmt.Sprintf(" Ranged strength: %+d", s.RangedStrength)) - } - if s.ScienceDamage != 0 { - sess.WriteLine(fmt.Sprintf(" Science damage: %+d", s.ScienceDamage)) - } - if s.TechnologyBonus != 0 { - sess.WriteLine(fmt.Sprintf(" Technology: %+d", s.TechnologyBonus)) - } - } - if def.AttackType != "" { - sess.WriteLine(fmt.Sprintf("Attack type: %s", def.AttackType)) - } - if def.Speed > 0 { - sess.WriteLine(fmt.Sprintf("Speed: %.0f", def.Speed)) - } - if len(def.Requirements) > 0 { - sess.WriteLine("") - sess.WriteLine("Requirements:") - for skill, level := range def.Requirements { - sess.WriteLine(fmt.Sprintf(" %s: %d", skill, level)) - } - } -} |
