From 8ee8982b8759bcae116647cc993867f4c8b0a6ce Mon Sep 17 00:00:00 2001 From: workhorse Date: Fri, 19 Jun 2026 20:24:52 -0400 Subject: reorganized items, objects, and rooms in directories. oranized module names. added startup checks. --- internal/game/cmd_trigger.go | 637 +------------------------------------------ 1 file changed, 4 insertions(+), 633 deletions(-) (limited to 'internal/game/cmd_trigger.go') diff --git a/internal/game/cmd_trigger.go b/internal/game/cmd_trigger.go index 89ed397..7d637ca 100644 --- a/internal/game/cmd_trigger.go +++ b/internal/game/cmd_trigger.go @@ -7,9 +7,12 @@ import ( "thehouseoficarus/internal/combat" "thehouseoficarus/internal/net" "thehouseoficarus/internal/player" - "thehouseoficarus/internal/world" ) +func (g *Game) executeTrigger(sess *net.Session, args []string, rawInput string) { + g.doTrigger(sess, strings.Join(args, " ")) +} + func (g *Game) doTrigger(sess *net.Session, input string) { p := sess.Player input = strings.TrimSpace(input) @@ -106,635 +109,3 @@ func (g *Game) triggerCombatMod(sess *net.Session, p *player.Player, mod *ModDef p.AutotriggerMod = mod.ID g.startCombat(sess, p, mob) } - -func (g *Game) triggerTransport(sess *net.Session, p *player.Player, mod *ModDef) { - if combat.GetCombat(p.Name) != nil { - sess.WriteLine("You can't teleport during combat!") - return - } - - if p.Action != nil { - g.cancelAction(p) - } - - g.consumeJunkCost(p, mod) - - sciXP := mod.BaseXP - g.awardSkillXP(sess, p, player.Science, sciXP) - if p.OptionBool("xp_drops") { - sess.WriteLine(g.colorize(sess, "xp", fmt.Sprintf("+%dxp sci", sciXP))) - } - g.AccountStore.SaveCharacter(p) - - if g.Hub != nil { - for _, other := range g.Hub.PlayersInRoom(p.RoomID) { - if other != sess { - other.WriteLine(fmt.Sprintf("\n%s teleports away.", p.Name)) - } - } - } - - sess.WriteLine(fmt.Sprintf("\nYou activate %s...", mod.Name)) - - p.RoomID = mod.Destination - if g.Hub != nil { - g.Hub.LeaveRoom(sess) - g.Hub.EnterRoom(sess, p.RoomID) - } - - room, _ := g.World.LoadRoom(p.RoomID) - destName := fmt.Sprintf("room %d", p.RoomID) - if room != nil { - destName = room.Name - } - sess.WriteLine(fmt.Sprintf("You materialize at %s.", destName)) - g.AccountStore.SaveCharacter(p) - g.doLook(sess) -} - -func (g *Game) triggerProcessing(sess *net.Session, p *player.Player, mod *ModDef, targetArg string) { - if combat.GetCombat(p.Name) != nil { - sess.WriteLine("You can't do that during combat!") - return - } - - if targetArg == "" { - sess.WriteLine(fmt.Sprintf("Usage: trigger %s ", strings.ReplaceAll(mod.ID, "_", " "))) - return - } - - slot, inv := g.findInventoryItem(p, targetArg) - if slot < 0 { - sess.WriteLine("You don't have that item.") - return - } - - itemDef, err := g.ItemStore.Load(inv.ItemID) - if err != nil || itemDef.Value <= 0 { - sess.WriteLine("That item has no value.") - return - } - - if p.Action != nil { - g.cancelAction(p) - } - - g.consumeJunkCost(p, mod) - - creditValue := itemDef.Value - if mod.ID == "low_process" { - creditValue = itemDef.Value / 2 - if creditValue < 1 { - creditValue = 1 - } - } - - if inv.Quantity > 1 { - inv.Quantity-- - } else { - p.SetInvSlot(slot, nil) - } - - p.Credits += creditValue - - sciXP := mod.BaseXP - g.awardSkillXP(sess, p, player.Science, sciXP) - g.AccountStore.SaveCharacter(p) - - sess.WriteLine(fmt.Sprintf("You process the %s. You receive %s credits.", - itemDef.Name, g.colorize(sess, "credits_pickup", fmt.Sprint(creditValue)))) - - if p.OptionBool("xp_drops") { - sess.WriteLine(g.colorize(sess, "xp", fmt.Sprintf("+%dxp sci", sciXP))) - } -} - -func (g *Game) triggerUtility(sess *net.Session, p *player.Player, mod *ModDef, targetArg string) { - switch mod.ID { - case "low_process", "high_process": - g.triggerProcessing(sess, p, mod, targetArg) - case "bones_to_nutrients": - g.triggerBonesToNutrients(sess, p, mod) - case "em_grab": - g.triggerEmGrab(sess, p, mod, targetArg) - case "superheat": - g.triggerSuperheat(sess, p, mod, targetArg) - case "plank_make": - g.triggerPlankMake(sess, p, mod, targetArg) - } -} - -func (g *Game) triggerBonesToNutrients(sess *net.Session, p *player.Player, mod *ModDef) { - if combat.GetCombat(p.Name) != nil { - sess.WriteLine("You can't do that during combat!") - return - } - - boneCount := p.CountItem("bones") - if boneCount == 0 { - sess.WriteLine("You don't have any bones.") - return - } - - if p.Action != nil { - g.cancelAction(p) - } - - g.consumeJunkCost(p, mod) - - for i := 0; i < 28; i++ { - slot := p.InvSlot(i) - if slot != nil && slot.ItemID == "bones" { - slot.ItemID = "nutrient_bar" - } - } - - sciXP := mod.BaseXP * boneCount - g.awardSkillXP(sess, p, player.Science, sciXP) - g.AccountStore.SaveCharacter(p) - - sess.WriteLine(fmt.Sprintf("You convert %d bones into nutrient bars.", boneCount)) - if p.OptionBool("xp_drops") { - sess.WriteLine(g.colorize(sess, "xp", fmt.Sprintf("+%dxp sci", sciXP))) - } -} - -func (g *Game) triggerEmGrab(sess *net.Session, p *player.Player, mod *ModDef, targetArg string) { - if targetArg == "" { - sess.WriteLine("Grab what? Usage: trigger em grab ") - return - } - - if p.FirstFreeSlot() < 0 { - sess.WriteLine("Your inventory is full.") - return - } - - groundItems := g.World.GroundItems(p.RoomID) - var matchedID string - for itemID := range groundItems { - def, _ := g.ItemStore.Load(itemID) - if def != nil && def.MatchesName(targetArg) { - matchedID = itemID - break - } - if strings.HasPrefix(itemID, strings.ToLower(targetArg)) { - matchedID = itemID - break - } - } - - if matchedID == "" { - sess.WriteLine("You don't see that here.") - return - } - - if p.Action != nil { - g.cancelAction(p) - } - - g.consumeJunkCost(p, mod) - - qty := groundItems[matchedID] - g.World.RemoveGroundItem(p.RoomID, matchedID, qty) - - def, _ := g.ItemStore.Load(matchedID) - name := matchedID - if def != nil { - name = def.Name - } - - freeSlot := p.FirstFreeSlot() - p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: matchedID, Quantity: qty}) - - sciXP := mod.BaseXP - g.awardSkillXP(sess, p, player.Science, sciXP) - g.AccountStore.SaveCharacter(p) - - sess.WriteLine(fmt.Sprintf("You magnetically pull the %s toward you.", name)) - if p.OptionBool("xp_drops") { - sess.WriteLine(g.colorize(sess, "xp", fmt.Sprintf("+%dxp sci", sciXP))) - } -} - -func (g *Game) triggerSuperheat(sess *net.Session, p *player.Player, mod *ModDef, targetArg string) { - if combat.GetCombat(p.Name) != nil { - sess.WriteLine("You can't do that during combat!") - return - } - - if targetArg == "" { - sess.WriteLine("Superheat what? Usage: trigger superheat ") - return - } - - slot, inv := g.findInventoryItem(p, targetArg) - if slot < 0 { - sess.WriteLine("You don't have that item.") - return - } - - recipe := g.RecipeStore.FindByInput("smelt", inv.ItemID) - if recipe == nil { - sess.WriteLine("You can't superheat that.") - return - } - - if recipe.Level > 0 && p.Level(player.SkillName(recipe.Skill)) < recipe.Level { - sess.WriteLine(fmt.Sprintf("You need level %d %s to smelt that.", recipe.Level, recipe.Skill)) - return - } - - for _, e := range recipe.Consume { - for _, itemID := range e.Items { - qty := e.Qty - if qty <= 0 { - qty = 1 - } - if p.CountItem(itemID) < qty { - def, _ := g.ItemStore.Load(itemID) - name := itemID - if def != nil { - name = def.Name - } - sess.WriteLine(fmt.Sprintf("You need %d %s.", qty, name)) - return - } - } - } - - if p.Action != nil { - g.cancelAction(p) - } - - g.consumeJunkCost(p, mod) - - for _, e := range recipe.Consume { - for _, itemID := range e.Items { - qty := e.Qty - if qty <= 0 { - qty = 1 - } - p.RemoveItem(itemID, qty) - } - } - - outputQty := recipe.OutputQty - if outputQty <= 0 { - outputQty = 1 - } - placed := false - for i := 0; i < 28; i++ { - slot := p.InvSlot(i) - if slot != nil && slot.ItemID == recipe.Output { - slot.Quantity += outputQty - placed = true - break - } - } - if !placed { - freeSlot := p.FirstFreeSlot() - p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: recipe.Output, Quantity: outputQty}) - } - - sciXP := mod.BaseXP - g.awardSkillXP(sess, p, player.Science, sciXP) - if recipe.XP > 0 { - g.awardSkillXP(sess, p, player.SkillName(recipe.Skill), recipe.XP) - } - g.AccountStore.SaveCharacter(p) - - outputDef, _ := g.ItemStore.Load(recipe.Output) - outputName := recipe.Output - if outputDef != nil { - outputName = outputDef.Name - } - inputDef, _ := g.ItemStore.Load(inv.ItemID) - inputName := inv.ItemID - if inputDef != nil { - inputName = inputDef.Name - } - - sess.WriteLine(fmt.Sprintf("You superheat the %s and produce a %s.", inputName, outputName)) - if p.OptionBool("xp_drops") { - parts := []string{fmt.Sprintf("+%dxp sci", sciXP)} - if recipe.XP > 0 { - parts = append(parts, fmt.Sprintf("+%dxp %s", recipe.XP, player.SkillAbbr[player.SkillName(recipe.Skill)])) - } - sess.WriteLine(g.colorize(sess, "xp", "("+strings.Join(parts, ", ")+")")) - } -} - -func (g *Game) triggerPlankMake(sess *net.Session, p *player.Player, mod *ModDef, targetArg string) { - if combat.GetCombat(p.Name) != nil { - sess.WriteLine("You can't do that during combat!") - return - } - - logTypes := map[string]struct { - plankID string - name string - cost int - }{ - "logs": {"planks", "planks", 3}, - "oak_logs": {"oak_planks", "oak planks", 7}, - "teak_logs": {"teak_planks", "teak planks", 14}, - "mahogany_logs": {"mahogany_planks", "mahogany planks", 28}, - } - - if targetArg != "" { - slot, inv := g.findInventoryItem(p, targetArg) - if slot < 0 { - sess.WriteLine("You don't have that item.") - return - } - info, ok := logTypes[inv.ItemID] - if !ok { - sess.WriteLine("You can't turn that into planks.") - return - } - - if p.Credits < info.cost { - sess.WriteLine(fmt.Sprintf("You need %d credits for Plank Make (70%% of sawmill cost).", info.cost)) - return - } - - if p.Action != nil { - g.cancelAction(p) - } - - g.consumeJunkCost(p, mod) - - p.RemoveItem(inv.ItemID, 1) - p.Credits -= info.cost - - freeSlot := p.FirstFreeSlot() - if freeSlot == -1 { - sess.WriteLine("Your inventory is full.") - return - } - p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: info.plankID, Quantity: 1}) - - sciXP := mod.BaseXP - g.awardSkillXP(sess, p, player.Science, sciXP) - g.awardSkillXP(sess, p, player.Construction, 10) - g.AccountStore.SaveCharacter(p) - - sess.WriteLine(fmt.Sprintf("You convert the log into %s.", info.name)) - if p.OptionBool("xp_drops") { - parts := []string{fmt.Sprintf("+%dxp sci", sciXP), "+10xp con"} - sess.WriteLine(g.colorize(sess, "xp", "("+strings.Join(parts, ", ")+")")) - } - return - } - - for logID, info := range logTypes { - qty := p.CountItem(logID) - if qty == 0 { - continue - } - - totalCost := info.cost * qty - if p.Credits < totalCost { - continue - } - - if p.Action != nil { - g.cancelAction(p) - } - - g.consumeJunkCost(p, mod) - - p.RemoveItem(logID, qty) - p.Credits -= totalCost - - processed := 0 - for i := 0; i < qty; i++ { - freeSlot := p.FirstFreeSlot() - if freeSlot == -1 { - g.World.AddGroundItem(p.RoomID, info.plankID, qty-i) - break - } - p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: info.plankID, Quantity: 1}) - processed++ - } - - sciXP := mod.BaseXP * qty - g.awardSkillXP(sess, p, player.Science, sciXP) - conXP := 10 * qty - g.awardSkillXP(sess, p, player.Construction, conXP) - g.AccountStore.SaveCharacter(p) - - sess.WriteLine(fmt.Sprintf("You convert %d logs into %s for %d credits.", processed, info.name, totalCost)) - if processed < qty { - sess.WriteLine(fmt.Sprintf("Your inventory is full. The remaining %d planks fall to the ground.", qty-processed)) - } - if p.OptionBool("xp_drops") { - parts := []string{fmt.Sprintf("+%dxp sci", sciXP), fmt.Sprintf("+%dxp con", conXP)} - sess.WriteLine(g.colorize(sess, "xp", "("+strings.Join(parts, ", ")+")")) - } - return - } - - sess.WriteLine("You don't have any logs to convert.") -} - -func (g *Game) triggerEnchant(sess *net.Session, p *player.Player, mod *ModDef, targetArg string) { - if chipInfo, ok := chipMap[mod.ID]; ok { - g.triggerChipBolts(sess, p, mod, chipInfo) - return - } - - enchants, ok := enchantMap[mod.ID] - if !ok { - sess.WriteLine("That enchantment has no known recipes.") - return - } - - if targetArg == "" { - sess.WriteLine(fmt.Sprintf("Enchant what? Use: trigger %s ", strings.ReplaceAll(mod.ID, "_", " "))) - return - } - - slot, inv := g.findInventoryItem(p, targetArg) - if slot < 0 { - sess.WriteLine("You don't have that item.") - return - } - - outputID, ok := enchants[inv.ItemID] - if !ok { - sess.WriteLine("You can't enchant that with this mod.") - return - } - - if p.Action != nil { - g.cancelAction(p) - } - - g.consumeJunkCost(p, mod) - - inv.ItemID = outputID - - sciXP := mod.BaseXP - g.awardSkillXP(sess, p, player.Science, sciXP) - g.AccountStore.SaveCharacter(p) - - outputDef, _ := g.ItemStore.Load(outputID) - outputName := outputID - if outputDef != nil { - outputName = outputDef.Name - } - inputDef, _ := g.ItemStore.Load(inv.ItemID) - inputName := inv.ItemID - if inputDef != nil { - inputName = inputDef.Name - } - - sess.WriteLine(fmt.Sprintf("You enchant the %s and it becomes a %s!", inputName, outputName)) - if p.OptionBool("xp_drops") { - sess.WriteLine(g.colorize(sess, "xp", fmt.Sprintf("+%dxp sci", sciXP))) - } -} - -func (g *Game) triggerChipBolts(sess *net.Session, p *player.Player, mod *ModDef, chip chipEntry) { - count := p.CountItem(chip.Input) - if count < chip.Qty { - inputDef, _ := g.ItemStore.Load(chip.Input) - name := chip.Input - if inputDef != nil { - name = inputDef.Name - } - sess.WriteLine(fmt.Sprintf("You need at least %d %s.", chip.Qty, name)) - return - } - - if p.Action != nil { - g.cancelAction(p) - } - - g.consumeJunkCost(p, mod) - - p.RemoveItem(chip.Input, chip.Qty) - placed := false - for i := 0; i < 28; i++ { - slot := p.InvSlot(i) - if slot != nil && slot.ItemID == chip.Output { - slot.Quantity += chip.Qty - placed = true - break - } - } - if !placed { - freeSlot := p.FirstFreeSlot() - p.SetInvSlot(freeSlot, &player.InventorySlot{ItemID: chip.Output, Quantity: chip.Qty}) - } - - sciXP := mod.BaseXP - g.awardSkillXP(sess, p, player.Science, sciXP) - g.AccountStore.SaveCharacter(p) - - inputDef, _ := g.ItemStore.Load(chip.Input) - name := chip.Input - if inputDef != nil { - name = inputDef.Name - } - - sess.WriteLine(fmt.Sprintf("You chip %d %s with arcane circuitry.", chip.Qty, name)) - if p.OptionBool("xp_drops") { - sess.WriteLine(g.colorize(sess, "xp", fmt.Sprintf("+%dxp sci", sciXP))) - } -} - -func (g *Game) scienceAttack(sess *net.Session, p *player.Player, mob *world.MobInstance, mod *ModDef) bool { - if p.Level(player.Science) < mod.Level { - sess.WriteLine(fmt.Sprintf("You need level %d science to trigger %s.", mod.Level, mod.Name)) - return false - } - if !g.hasJunkCost(p, mod) { - return false - } - - if g.processConsumeQueue(p, sess) { - p.ActionState = &ActionState{Type: ActionEating, TargetName: "food"} - return true - } - - g.consumeJunkCost(p, mod) - - equipSciBonus := g.totalEquipScienceAttack(p) - attRoll := (p.Level(player.Science) + g.buffLevelBonus(p, "science") + 8) * (equipSciBonus + 64) - - mobSciDef := mob.ScienceDefense - defRoll := (mob.Defense + 9) * (mobSciDef + 64) - - if mob.Weakness == mod.Element { - attRoll = attRoll * 13 / 10 - } - - if combat.HitCheck(attRoll, defRoll) { - dmg := combat.RollDamage(mod.MaxHit) - if dmg < 0 { - dmg = 0 - } - mob.HP -= dmg - if mob.HP < 0 { - mob.HP = 0 - } - if mob.HP < mob.MaxHP && mob.HP > 0 { - mob.StartRegen() - } - - sciXP := mod.BaseXP - hpXP := mod.BaseXP / 3 - if hpXP < 1 { - hpXP = 1 - } - var gains []xpGain - - g.awardSkillXP(sess, p, player.Science, sciXP) - gains = append(gains, xpGain{string(player.Science), sciXP}) - - g.awardSkillXP(sess, p, player.Hitpoints, hpXP) - gains = append(gains, xpGain{string(player.Hitpoints), hpXP}) - - g.AccountStore.SaveCharacter(p) - - mobName := mobDisplayName(mob, true) - prefix := fmt.Sprintf(" %s hits %s for %s damage.", - g.colorize(sess, "science_mod", mod.Name), - g.colorize(sess, "mob_name", mobName), - g.colorize(sess, "damage", fmt.Sprint(dmg))) - hpPart := fmt.Sprintf("[%s/%dhp]", g.colorize(sess, "enemy_hp", fmt.Sprint(mob.HP)), mob.MaxHP) - line := prefix + " " + hpPart - if p.OptionBool("xp_drops") && len(gains) > 0 { - var parts []string - for _, gain := range gains { - parts = append(parts, fmt.Sprintf("+%dxp %s", gain.XP, player.SkillAbbr[player.SkillName(gain.Skill)])) - } - line += g.colorize(sess, "xp", " ("+strings.Join(parts, ", ")+")") - } - sess.WriteLine(line) - } else { - sess.WriteLine(g.colorize(sess, "miss", fmt.Sprintf(" %s fails to connect.", mod.Name))) - } - return true -} - -func (g *Game) findInventoryItem(p *player.Player, input string) (int, *player.InventorySlot) { - lower := strings.ToLower(strings.TrimSpace(input)) - for i := 0; i < 28; i++ { - slot := p.InvSlot(i) - if slot == nil { - continue - } - def, err := g.ItemStore.Load(slot.ItemID) - if err != nil { - continue - } - if def.MatchesName(lower) { - return i, slot - } - } - return -1, nil -} -- cgit v1.2.3