diff options
Diffstat (limited to 'internal/game/sys_technology.go')
| -rw-r--r-- | internal/game/sys_technology.go | 116 |
1 files changed, 53 insertions, 63 deletions
diff --git a/internal/game/sys_technology.go b/internal/game/sys_technology.go index e673dcb..6afc757 100644 --- a/internal/game/sys_technology.go +++ b/internal/game/sys_technology.go @@ -2,80 +2,62 @@ package game import ( "fmt" + "path/filepath" "strings" + "gopkg.in/yaml.v3" + + "thehouseoficarus/internal/action" "thehouseoficarus/internal/net" "thehouseoficarus/internal/player" "thehouseoficarus/internal/world" ) type TechEffects struct { - AccuracyPercent int - StrengthPercent int - DefensePercent int - RangedPercent int - SciencePercent int - ProtectMelee bool - ProtectRanged bool - ProtectScience bool - DamageReduction float64 - HPRegenMulti float64 - PreserveDrain float64 - RetributionPct float64 + AccuracyPercent int `yaml:"accuracy_percent"` + StrengthPercent int `yaml:"strength_percent"` + DefensePercent int `yaml:"defense_percent"` + RangedPercent int `yaml:"ranged_percent"` + SciencePercent int `yaml:"science_percent"` + ProtectMelee bool `yaml:"protect_melee"` + ProtectRanged bool `yaml:"protect_ranged"` + ProtectScience bool `yaml:"protect_science"` + DamageReduction float64 `yaml:"damage_reduction"` + HPRegenMulti float64 `yaml:"hp_regen_multi"` + PreserveDrain float64 `yaml:"preserve_drain"` + RetributionPct float64 `yaml:"retribution_pct"` } type TechDef struct { - ID string - Name string - Level int - DrainRate float64 - Category string - Group string - Effects TechEffects + ID string `yaml:"id"` + Name string `yaml:"name"` + Level int `yaml:"level"` + DrainRate float64 `yaml:"drain_rate"` + Category string `yaml:"category"` + Group string `yaml:"group"` + Effects TechEffects `yaml:"effects"` } -var AllTechs []TechDef +var AllTechs []*TechDef var techByID map[string]*TechDef -func init() { - AllTechs = []TechDef{ - {ID: "clarity_1", Name: "Clarity", Level: 4, DrainRate: 0.05, Category: "accuracy", Group: "accuracy_tier", Effects: TechEffects{AccuracyPercent: 5}}, - {ID: "clarity_2", Name: "Enhanced Clarity", Level: 16, DrainRate: 0.10, Category: "accuracy", Group: "accuracy_tier", Effects: TechEffects{AccuracyPercent: 10}}, - {ID: "clarity_3", Name: "Superior Clarity", Level: 44, DrainRate: 0.15, Category: "accuracy", Group: "accuracy_tier", Effects: TechEffects{AccuracyPercent: 15}}, - - {ID: "amplifier_1", Name: "Power Amplifier", Level: 7, DrainRate: 0.05, Category: "strength", Group: "strength_tier", Effects: TechEffects{StrengthPercent: 5}}, - {ID: "amplifier_2", Name: "Enhanced Amplifier", Level: 23, DrainRate: 0.10, Category: "strength", Group: "strength_tier", Effects: TechEffects{StrengthPercent: 10}}, - {ID: "amplifier_3", Name: "Superior Amplifier", Level: 49, DrainRate: 0.15, Category: "strength", Group: "strength_tier", Effects: TechEffects{StrengthPercent: 15}}, - - {ID: "shield_1", Name: "Energy Shield", Level: 10, DrainRate: 0.05, Category: "defense", Group: "defense_tier", Effects: TechEffects{DefensePercent: 5}}, - {ID: "shield_2", Name: "Enhanced Shield", Level: 28, DrainRate: 0.10, Category: "defense", Group: "defense_tier", Effects: TechEffects{DefensePercent: 10}}, - {ID: "shield_3", Name: "Superior Shield", Level: 52, DrainRate: 0.15, Category: "defense", Group: "defense_tier", Effects: TechEffects{DefensePercent: 15}}, - - {ID: "targeting_1", Name: "Targeting System", Level: 8, DrainRate: 0.05, Category: "ranged", Group: "ranged_tier", Effects: TechEffects{RangedPercent: 5}}, - {ID: "targeting_2", Name: "Enhanced Targeting", Level: 22, DrainRate: 0.10, Category: "ranged", Group: "ranged_tier", Effects: TechEffects{RangedPercent: 10}}, - {ID: "targeting_3", Name: "Superior Targeting", Level: 46, DrainRate: 0.15, Category: "ranged", Group: "ranged_tier", Effects: TechEffects{RangedPercent: 15}}, - - {ID: "focus_1", Name: "Neural Focus", Level: 9, DrainRate: 0.05, Category: "science", Group: "science_tier", Effects: TechEffects{SciencePercent: 5}}, - {ID: "focus_2", Name: "Enhanced Focus", Level: 27, DrainRate: 0.10, Category: "science", Group: "science_tier", Effects: TechEffects{SciencePercent: 10}}, - {ID: "focus_3", Name: "Superior Focus", Level: 55, DrainRate: 0.15, Category: "science", Group: "science_tier", Effects: TechEffects{SciencePercent: 15}}, - - {ID: "protect_melee", Name: "Kinetic Barrier", Level: 37, DrainRate: 0.20, Category: "protection", Group: "protection", Effects: TechEffects{ProtectMelee: true, DamageReduction: 0.4}}, - {ID: "protect_ranged", Name: "Projectile Screen", Level: 40, DrainRate: 0.20, Category: "protection", Group: "protection", Effects: TechEffects{ProtectRanged: true, DamageReduction: 0.4}}, - {ID: "protect_science", Name: "Neural Firewall", Level: 43, DrainRate: 0.20, Category: "protection", Group: "protection", Effects: TechEffects{ProtectScience: true, DamageReduction: 0.4}}, - - {ID: "regen", Name: "Nano Repair", Level: 22, DrainRate: 0.10, Category: "utility", Group: "regen_tier", Effects: TechEffects{HPRegenMulti: 2.0}}, - {ID: "rapid_heal", Name: "Rapid Repair", Level: 31, DrainRate: 0.15, Category: "utility", Group: "regen_tier", Effects: TechEffects{HPRegenMulti: 4.0}}, - {ID: "preserve", Name: "Power Saver", Level: 55, DrainRate: 0.05, Category: "utility", Group: "", Effects: TechEffects{PreserveDrain: 0.2}}, - {ID: "retribution", Name: "Dead Man's Switch", Level: 46, DrainRate: 0.10, Category: "utility", Group: "", Effects: TechEffects{RetributionPct: 0.25}}, - - {ID: "overclock", Name: "Overclock", Level: 60, DrainRate: 0.25, Category: "combo", Group: "accuracy_tier", Effects: TechEffects{AccuracyPercent: 15, StrengthPercent: 15}}, - {ID: "fortify", Name: "Fortify", Level: 65, DrainRate: 0.25, Category: "combo", Group: "defense_tier", Effects: TechEffects{DefensePercent: 15, HPRegenMulti: 2.0}}, - } - +func (g *Game) LoadTechs() error { + dir := filepath.Join(g.DataDir, "techs") + AllTechs = nil + techByID = make(map[string]*TechDef) + action.WalkYAMLDir(dir, func(path, id string, data []byte) error { + var t TechDef + if err := yaml.Unmarshal(data, &t); err != nil { + return nil + } + AllTechs = append(AllTechs, &t) + return nil + }) techByID = make(map[string]*TechDef, len(AllTechs)) - for i := range AllTechs { - techByID[AllTechs[i].ID] = &AllTechs[i] + for _, t := range AllTechs { + techByID[t.ID] = t } + return nil } func GetTechDef(id string) *TechDef { @@ -86,13 +68,13 @@ func TechByPrefixMatch(input string) []*TechDef { input = strings.ToLower(input) var exact []*TechDef var prefix []*TechDef - for i := range AllTechs { - lower := strings.ToLower(AllTechs[i].Name) - lowerID := strings.ToLower(AllTechs[i].ID) + for _, t := range AllTechs { + lower := strings.ToLower(t.Name) + lowerID := strings.ToLower(t.ID) if lower == input || lowerID == input { - exact = append(exact, &AllTechs[i]) + exact = append(exact, t) } else if strings.HasPrefix(lower, input) || strings.HasPrefix(lowerID, input) { - prefix = append(prefix, &AllTechs[i]) + prefix = append(prefix, t) } } if len(exact) > 0 { @@ -101,7 +83,7 @@ func TechByPrefixMatch(input string) []*TechDef { return prefix } -func techEffectString(tech TechDef) string { +func techEffectString(tech *TechDef) string { var parts []string e := tech.Effects if e.AccuracyPercent > 0 { @@ -223,6 +205,14 @@ func (g *Game) applyTechProtection(p *player.Player, mob *world.MobInstance, dmg // damageAfterTechProtection reduces incoming damage if the player has the // protection tech matching the given attack type active. Shared by mob combat // and room hazards. +// +// Reserved tech IDs (must exist in data/techs/): +// +// protect_melee — mapped to stab/slash/crush attacks +// protect_ranged — mapped to ranged attacks +// protect_science — mapped to science attacks +// +// Also retribution — checked by name in killPlayer (cmd_attack.go). func (g *Game) damageAfterTechProtection(p *player.Player, attackType string, dmg int) int { if len(p.ActiveTechs) == 0 { return dmg |
