aboutsummaryrefslogtreecommitdiff
path: root/internal/game/cmd_trigger.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/game/cmd_trigger.go')
-rw-r--r--internal/game/cmd_trigger.go637
1 files changed, 4 insertions, 633 deletions
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 <item>", 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 <item>")
- 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 <ore>")
- 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 <jewelry item>", 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
-}