diff options
| author | historia <[not public]> | 2026-06-19 02:08:55 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-06-19 02:08:55 -0400 |
| commit | 458916fb78dcef3ff77cb29b7ba98d9f646819fc (patch) | |
| tree | 19cd8b8eef41a1aa00d155bf7953ad2770f91a4c /internal/game/cmd_attack.go | |
| parent | 97a1a908b9e6e6d3516628c139c9b64262b4fe08 (diff) | |
| download | thehouseoficarus-458916fb78dcef3ff77cb29b7ba98d9f646819fc.tar.gz | |
feat: rough pharmacy skill added
Diffstat (limited to 'internal/game/cmd_attack.go')
| -rw-r--r-- | internal/game/cmd_attack.go | 143 |
1 files changed, 107 insertions, 36 deletions
diff --git a/internal/game/cmd_attack.go b/internal/game/cmd_attack.go index 4c6941a..4d2d19f 100644 --- a/internal/game/cmd_attack.go +++ b/internal/game/cmd_attack.go @@ -46,6 +46,15 @@ func (g *Game) doAttack(sess *net.Session, input string) { return } + if itemID, ok := p.Equipment[object.SlotMainHand]; ok { + if def, err := g.ItemStore.Load(itemID); err == nil && def.WeaponType == object.WeaponRanged { + if _, hasAmmo := p.Equipment[object.SlotAmmo]; !hasAmmo || p.AmmoQty <= 0 { + sess.WriteLine("You don't have any ammo equipped.") + return + } + } + } + g.startCombat(sess, p, mob) } @@ -177,23 +186,51 @@ func (g *Game) playerAttack(sess *net.Session, p *player.Player, mob *world.MobI return } - attBonus, strBonus, _ := combat.AttackStyleBonus(string(p.AttackStyle)) - - equipAtt := 0 - equipStr := 0 + attackType := "crush" + var weaponType object.WeaponType if itemID, ok := p.Equipment[object.SlotMainHand]; ok { - def, err := g.ItemStore.Load(itemID) - if err == nil { - equipAtt = def.Stats.AttackBonus - equipStr = def.Stats.StrengthBonus + if def, err := g.ItemStore.Load(itemID); err == nil { + if def.AttackType != "" { + attackType = def.AttackType + } else if def.WeaponType == object.WeaponRanged { + attackType = "ranged" + } else if def.WeaponType == object.WeaponScience { + attackType = "science" + } + weaponType = def.WeaponType } } - attRoll := combat.AttackRoll(p.Level(player.Attack), attBonus, equipAtt) - defRoll := combat.DefenseRoll(mob.Defense, 0, 0) + totals := g.playerEquipBonuses(p) + isRanged := weaponType == object.WeaponRanged + + var attRoll, defRoll, maxHit int + + if isRanged { + rangedBonus, _ := combat.RangedStyleBonus(string(p.AttackStyle)) + equipAttack := totals.RangedAttack + attRoll = combat.AttackRoll(p.Level(player.Ranged), rangedBonus, equipAttack) + + mobDefBonus := combat.SelectDefenseBonus(attackType, + mob.StabDefense, mob.SlashDefense, mob.CrushDefense, + mob.ScienceDefense, mob.RangedDefense) + defRoll = combat.DefenseRoll(mob.Defense, 0, mobDefBonus) + maxHit = combat.MaxHit(p.Level(player.Ranged), rangedBonus, totals.RangedStrength) + } else { + attBonus, strBonus, _ := combat.AttackStyleBonus(string(p.AttackStyle)) + equipAttack := combat.SelectAttackBonus(attackType, + totals.StabAttack, totals.SlashAttack, totals.CrushAttack, + totals.ScienceAttack, totals.RangedAttack) + attRoll = combat.AttackRoll(p.Level(player.Attack), attBonus, equipAttack) + + mobDefBonus := combat.SelectDefenseBonus(attackType, + mob.StabDefense, mob.SlashDefense, mob.CrushDefense, + mob.ScienceDefense, mob.RangedDefense) + defRoll = combat.DefenseRoll(mob.Defense, 0, mobDefBonus) + maxHit = combat.MaxHit(p.Level(player.Strength), strBonus, totals.StrengthBonus) + } if combat.HitCheck(attRoll, defRoll) { - maxHit := combat.MaxHit(p.Level(player.Strength), strBonus, equipStr) dmg := combat.RollDamage(maxHit) mob.HP -= dmg @@ -203,7 +240,16 @@ func (g *Game) playerAttack(sess *net.Session, p *player.Player, mob *world.MobI if mob.HP < mob.MaxHP && mob.HP > 0 { mob.StartRegen() } - gains, leveled := g.awardCombatXP(p, dmg) + gains, leveled := g.awardCombatXP(p, dmg, isRanged) + + if isRanged { + p.AmmoQty-- + if p.AmmoQty <= 0 { + delete(p.Equipment, object.SlotAmmo) + p.AmmoQty = 0 + } + g.AccountStore.SaveCharacter(p) + } for _, skill := range leveled { sess.WriteLine(g.colorize(sess, "level_up", fmt.Sprintf("*** You are now level %d %s! ***", p.Level(skill), skill))) @@ -230,27 +276,45 @@ func (g *Game) playerAttack(sess *net.Session, p *player.Player, mob *world.MobI line += g.colorize(sess, "xp", " ("+strings.Join(parts, ", ")+")") } sess.WriteLine(line) + + if isRanged && p.AmmoQty <= 0 { + sess.WriteLine("You've run out of ammo!") + combat.LeaveCombat(p.Name) + } } else { sess.WriteLine(g.colorize(sess, "miss", fmt.Sprintf(" You miss %s.", mobDisplayName(mob, true)))) + + if isRanged { + p.AmmoQty-- + if p.AmmoQty <= 0 { + delete(p.Equipment, object.SlotAmmo) + p.AmmoQty = 0 + g.AccountStore.SaveCharacter(p) + sess.WriteLine("You've run out of ammo!") + combat.LeaveCombat(p.Name) + } + } } } func (g *Game) mobAttack(sess *net.Session, p *player.Player, mob *world.MobInstance) { - _, _, defBonus := combat.AttackStyleBonus(string(p.AttackStyle)) + _, _, defStyleBonus := combat.AttackStyleBonus(string(p.AttackStyle)) - equipDef := 0 - for _, itemID := range p.Equipment { - def, err := g.ItemStore.Load(itemID) - if err == nil { - equipDef += def.Stats.DefenseBonus - } + mobAttackType := mob.AttackType + if mobAttackType == "" { + mobAttackType = "crush" } - attRoll := combat.AttackRoll(mob.Attack, 0, 0) - defRoll := combat.DefenseRoll(p.Level(player.Defense), defBonus, equipDef) + attRoll := combat.AttackRoll(mob.Attack, 0, mob.AttackBonus) + + totals := g.playerEquipBonuses(p) + equipDef := combat.SelectDefenseBonus(mobAttackType, + totals.StabDefense, totals.SlashDefense, totals.CrushDefense, + totals.ScienceDefense, totals.RangedDefense) + defRoll := combat.DefenseRoll(p.Level(player.Defense), defStyleBonus, equipDef) if combat.HitCheck(attRoll, defRoll) { - maxHit := combat.MaxHit(mob.Strength, 0, 0) + maxHit := combat.MaxHit(mob.Strength, 0, mob.StrengthBonus) dmg := combat.RollDamage(maxHit) p.HP -= dmg @@ -375,25 +439,32 @@ func (g *Game) endCombat(sess *net.Session, p *player.Player, mob *world.MobInst } } -func (g *Game) awardCombatXP(p *player.Player, dmg int) ([]xpGain, []player.SkillName) { +func (g *Game) awardCombatXP(p *player.Player, dmg int, isRanged bool) ([]xpGain, []player.SkillName) { baseXP := dmg * 4 var gains []xpGain var leveledUp []player.SkillName - switch p.AttackStyle { - case player.Accurate: - gains = []xpGain{{string(player.Attack), baseXP * 3 / 4}, {string(player.Hitpoints), baseXP / 4}} - case player.Aggressive: - gains = []xpGain{{string(player.Strength), baseXP * 3 / 4}, {string(player.Hitpoints), baseXP / 4}} - case player.Defensive: - gains = []xpGain{{string(player.Defense), baseXP * 3 / 4}, {string(player.Hitpoints), baseXP / 4}} - case player.Balanced: - quarter := baseXP / 4 + if isRanged { gains = []xpGain{ - {string(player.Attack), quarter}, - {string(player.Strength), quarter}, - {string(player.Defense), quarter}, - {string(player.Hitpoints), quarter}, + {string(player.Ranged), baseXP * 3 / 4}, + {string(player.Hitpoints), baseXP / 4}, + } + } else { + switch p.AttackStyle { + case player.Accurate: + gains = []xpGain{{string(player.Attack), baseXP * 3 / 4}, {string(player.Hitpoints), baseXP / 4}} + case player.Aggressive: + gains = []xpGain{{string(player.Strength), baseXP * 3 / 4}, {string(player.Hitpoints), baseXP / 4}} + case player.Defensive: + gains = []xpGain{{string(player.Defense), baseXP * 3 / 4}, {string(player.Hitpoints), baseXP / 4}} + case player.Balanced: + quarter := baseXP / 4 + gains = []xpGain{ + {string(player.Attack), quarter}, + {string(player.Strength), quarter}, + {string(player.Defense), quarter}, + {string(player.Hitpoints), quarter}, + } } } |
