package game import ( "fmt" "strings" "thehouseoficarus/internal/combat" "thehouseoficarus/internal/net" "thehouseoficarus/internal/player" "thehouseoficarus/internal/world" ) 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.processConsumeQueue(p, sess) { p.ActionState = &ActionState{Type: ActionEating, TargetName: "food"} return true } g.consumeJunkCost(p, mod) equipSciBonus := g.totalScienceAttack(p) effectiveScience := p.Level(player.Science) + g.techLevelBonus(p, "science") + g.buffLevelBonus(p, "science") attRoll := combat.EffectiveRoll(effectiveScience, 0, equipSciBonus) mobSciDef := mob.ScienceDefense defRoll := combat.EffectiveRoll(mob.Defense, 0, mobSciDef) 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", mobName), g.colorize(sess, "damage_dealt", fmt.Sprint(dmg))) hpSuffix := fmt.Sprintf("%s [%2d/%d]", g.hpBar(sess, mob.HP, mob.MaxHP), mob.HP, mob.MaxHP) line := prefix + " " + hpSuffix + g.formatXpDrop(sess, p, gains) 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 }