Files
Catacombs/entity/player.go
tolelom f28160d4da feat: localize all UI text to Korean
Translate all user-facing strings to Korean across 25 files:
- UI screens: title, nickname, lobby, class select, waiting, game,
  shop, result, help, leaderboard, achievements, codex, stats
- Game logic: combat logs, events, achievements, mutations, emotes,
  lobby errors, session messages
- Keep English for: class names, monster names, item names, relic names

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 23:47:27 +09:00

213 lines
4.0 KiB
Go

package entity
import "fmt"
type Class int
const (
ClassWarrior Class = iota
ClassMage
ClassHealer
ClassRogue
)
func (c Class) String() string {
return [...]string{"Warrior", "Mage", "Healer", "Rogue"}[c]
}
type classStats struct {
HP, ATK, DEF int
}
var classBaseStats = map[Class]classStats{
ClassWarrior: {120, 12, 8},
ClassMage: {70, 20, 3},
ClassHealer: {90, 8, 5},
ClassRogue: {85, 15, 4},
}
type StatusEffect int
const (
StatusPoison StatusEffect = iota
StatusBurn
StatusFreeze
StatusBleed
StatusCurse
)
type ActiveEffect struct {
Type StatusEffect
Duration int // remaining turns
Value int // damage per turn or effect strength
}
type Player struct {
Name string
Fingerprint string
Class Class
HP, MaxHP int
ATK, DEF int
Gold int
Inventory []Item
Relics []Relic
Effects []ActiveEffect
Dead bool
Fled bool
SkillUses int // remaining skill uses this combat
Skills *PlayerSkills
}
func NewPlayer(name string, class Class) *Player {
stats := classBaseStats[class]
return &Player{
Name: name,
Class: class,
HP: stats.HP,
MaxHP: stats.HP,
ATK: stats.ATK,
DEF: stats.DEF,
}
}
func (p *Player) TakeDamage(dmg int) {
p.HP -= dmg
if p.HP <= 0 {
p.HP = 0
p.Dead = true
}
}
func (p *Player) Heal(amount int) {
for _, e := range p.Effects {
if e.Type == StatusCurse {
amount = amount * (100 - e.Value) / 100
break
}
}
p.HP += amount
if p.HP > p.MaxHP {
p.HP = p.MaxHP
}
}
func (p *Player) IsDead() bool {
return p.Dead
}
func (p *Player) IsOut() bool {
return p.Dead || p.Fled
}
func (p *Player) Revive(hpPercent float64) {
p.Dead = false
p.HP = int(float64(p.MaxHP) * hpPercent)
if p.HP < 1 {
p.HP = 1
}
}
func (p *Player) EffectiveATK() int {
atk := p.ATK
for _, item := range p.Inventory {
if item.Type == ItemWeapon {
atk += item.Bonus
}
}
for _, r := range p.Relics {
if r.Effect == RelicATKBoost {
atk += r.Value
}
}
atk += p.Skills.GetATKBonus(p.Class)
return atk
}
func (p *Player) EffectiveDEF() int {
def := p.DEF
for _, item := range p.Inventory {
if item.Type == ItemArmor {
def += item.Bonus
}
}
for _, r := range p.Relics {
if r.Effect == RelicDEFBoost {
def += r.Value
}
}
def += p.Skills.GetDEFBonus(p.Class)
return def
}
func (p *Player) AddEffect(e ActiveEffect) {
// Check relic immunities
for _, r := range p.Relics {
if e.Type == StatusPoison && r.Effect == RelicPoisonImmunity {
return // immune
}
if e.Type == StatusBurn && r.Effect == RelicBurnResist {
e.Value = e.Value / 2 // halve burn damage
}
}
// Don't stack same type, refresh duration
for i, existing := range p.Effects {
if existing.Type == e.Type {
p.Effects[i] = e
return
}
}
p.Effects = append(p.Effects, e)
}
func (p *Player) HasEffect(t StatusEffect) bool {
for _, e := range p.Effects {
if e.Type == t {
return true
}
}
return false
}
func (p *Player) TickEffects() []string {
var msgs []string
remaining := p.Effects[:0] // reuse underlying array
for i := 0; i < len(p.Effects); i++ {
e := &p.Effects[i]
switch e.Type {
case StatusPoison:
p.HP -= e.Value
if p.HP <= 0 {
p.HP = 1 // Poison can't kill, leaves at 1 HP
}
msgs = append(msgs, fmt.Sprintf("%s 독 피해 %d", p.Name, e.Value))
case StatusBurn:
p.HP -= e.Value
if p.HP <= 0 {
p.HP = 0
p.Dead = true
}
msgs = append(msgs, fmt.Sprintf("%s 화상 피해 %d", p.Name, e.Value))
case StatusFreeze:
msgs = append(msgs, fmt.Sprintf("%s 동결됨!", p.Name))
case StatusBleed:
p.HP -= e.Value
msgs = append(msgs, fmt.Sprintf("%s 출혈 피해 %d", p.Name, e.Value))
e.Value++ // Bleed intensifies each turn
case StatusCurse:
msgs = append(msgs, fmt.Sprintf("%s 저주 상태! 회복량 감소", p.Name))
}
if p.HP < 0 {
p.HP = 0
}
e.Duration--
if e.Duration > 0 {
remaining = append(remaining, *e)
}
}
p.Effects = remaining
if p.HP <= 0 && !p.Dead {
p.Dead = true
}
return msgs
}