You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
286 lines
7.7 KiB
Go
286 lines
7.7 KiB
Go
package model
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// EnglishAdventureLogFallback returns a readable English line for SQL/admin when Message is empty.
|
|
// Keep roughly aligned with frontend adventureLogFormat.ts (EN branch). Sync new event codes here.
|
|
func EnglishAdventureLogFallback(ev *AdventureLogEvent) string {
|
|
if ev == nil {
|
|
return ""
|
|
}
|
|
a := ev.Args
|
|
switch ev.Code {
|
|
case LogCombatSwing:
|
|
return englishCombatSwing(a)
|
|
case LogDefeatedEnemy:
|
|
return fmt.Sprintf("Defeated %s (+%v XP, +%v gold).", englishEnemyLogName(a), logArgFloat(a, "xp"), logArgFloat(a, "gold"))
|
|
case LogLeveledUp:
|
|
return fmt.Sprintf("Reached level %d!", logArgInt(a, "level"))
|
|
case LogEquippedNew:
|
|
return fmt.Sprintf("Equipped new %s: %s.", englishSlotName(logArgStr(a, "slot")), logArgStr(a, "itemName"))
|
|
case LogInventoryFullDropped:
|
|
return fmt.Sprintf("Inventory full — dropped %s (%s).", logArgStr(a, "itemName"), englishRarityName(logArgStr(a, "rarity")))
|
|
case LogBuffActivated:
|
|
return fmt.Sprintf("%s activated.", englishBuffName(logArgStr(a, "buffType")))
|
|
case LogHeroRevived:
|
|
return "You revived."
|
|
case LogWanderingMerchant:
|
|
return "A hooded merchant blocks your path, jingling a pouch of odd trinkets."
|
|
case LogEncounteredEnemy:
|
|
return fmt.Sprintf("You encounter %s.", englishEnemyLogName(a))
|
|
case LogDiedFighting:
|
|
return fmt.Sprintf("You died fighting %s.", englishEnemyLogName(a))
|
|
case LogAutoReviveHours:
|
|
return "Hours passed; you revived in town."
|
|
case LogAutoReviveAfterSec:
|
|
return fmt.Sprintf("Auto-revived after %ds offline.", logArgInt(a, "seconds"))
|
|
case LogPurchasedBuffRefill:
|
|
return fmt.Sprintf("Refilled charges: %s.", englishBuffName(logArgStr(a, "buffType")))
|
|
case LogPurchasedBuffRefillRub:
|
|
return fmt.Sprintf("Purchased refill for %s (%d RUB).", englishBuffName(logArgStr(a, "buffType")), logArgInt(a, "priceRub"))
|
|
case LogSubscribed:
|
|
dk := logArgStr(a, "durationKey")
|
|
price := logArgInt(a, "priceRub")
|
|
dur := dk
|
|
if dk == "subscription.week" {
|
|
dur = "one week of subscription"
|
|
}
|
|
return fmt.Sprintf("Subscribed: %s (%d RUB).", dur, price)
|
|
case LogUsedHealingPotion:
|
|
return fmt.Sprintf("Used healing potion (+%d HP).", logArgInt(a, "amount"))
|
|
case LogAchievementUnlocked:
|
|
title := logArgStr(a, "title")
|
|
rt := logArgStr(a, "rewardType")
|
|
ra := logArgInt(a, "rewardAmount")
|
|
switch rt {
|
|
case "gold":
|
|
return fmt.Sprintf("Achievement: %s (+%d gold).", title, ra)
|
|
case "potion":
|
|
return fmt.Sprintf("Achievement: %s (+%d potions).", title, ra)
|
|
default:
|
|
return fmt.Sprintf("Achievement: %s.", title)
|
|
}
|
|
case LogMetNPC:
|
|
return fmt.Sprintf("Met %s in %s.", logArgStr(a, "npcKey"), logArgStr(a, "townKey"))
|
|
case LogWanderingAlmsEquipped:
|
|
return fmt.Sprintf("Equipped from the merchant: %s.", logArgStr(a, "itemName"))
|
|
case LogWanderingAlmsDropped:
|
|
return fmt.Sprintf("Dropped %s (%s) — no room.", logArgStr(a, "itemName"), englishRarityName(logArgStr(a, "rarity")))
|
|
case LogWanderingAlmsStashed:
|
|
return fmt.Sprintf("Stashed %s in your inventory.", logArgStr(a, "itemName"))
|
|
case LogHealedFullTown:
|
|
return "Paid for a full heal."
|
|
case LogBoughtPotionTown:
|
|
return "Bought a potion in town."
|
|
case LogSoldItemsMerchant:
|
|
return fmt.Sprintf("Sold %d items to %s (+%v gold).", logArgInt(a, "count"), logArgStr(a, "npcKey"), logArgFloat(a, "gold"))
|
|
case LogNPCSkippedVisit:
|
|
return fmt.Sprintf("Skipped visiting %s.", logArgStr(a, "npcKey"))
|
|
case LogThoughtRoadside:
|
|
idx := logArgInt(a, "idx")
|
|
return fmt.Sprintf("Roadside thought (%d).", idx)
|
|
case LogPurchasedPotionFromNPC:
|
|
return fmt.Sprintf("Bought a potion from %s.", logArgStr(a, "npcKey"))
|
|
case LogPaidHealerFull:
|
|
return fmt.Sprintf("Paid %s for a full heal.", logArgStr(a, "npcKey"))
|
|
case LogQuestGiverChecked:
|
|
return fmt.Sprintf("Checked in with %s — no new quests.", logArgStr(a, "npcKey"))
|
|
case LogQuestAccepted:
|
|
return fmt.Sprintf("Accepted quest: %s.", logArgStr(a, "title"))
|
|
case LogTownNPCVisitLine:
|
|
npcType := logArgStr(a, "npcType")
|
|
line := logArgInt(a, "line")
|
|
return fmt.Sprintf("Town visit (%s): beat %d/6.", npcType, line+1)
|
|
default:
|
|
if ev.Code != "" {
|
|
return fmt.Sprintf("[%s]", ev.Code)
|
|
}
|
|
return ""
|
|
}
|
|
}
|
|
|
|
func englishCombatSwing(a map[string]any) string {
|
|
source := logArgStr(a, "source")
|
|
outcome := logArgStr(a, "outcome")
|
|
damage := logArgInt(a, "damage")
|
|
isCrit := logArgBool(a, "isCrit")
|
|
enemyName := englishEnemyLogName(a)
|
|
critSuffix := ""
|
|
if isCrit {
|
|
critSuffix = " (crit)"
|
|
}
|
|
var msg string
|
|
switch source {
|
|
case "hero":
|
|
switch outcome {
|
|
case "stun":
|
|
msg = "You are stunned and cannot attack."
|
|
case "dodge":
|
|
msg = enemyName + " dodged your attack."
|
|
default:
|
|
msg = fmt.Sprintf("You hit %s for %d damage%s.", enemyName, damage, critSuffix)
|
|
}
|
|
case "enemy":
|
|
switch outcome {
|
|
case "block":
|
|
msg = fmt.Sprintf("You block %s's attack.", enemyName)
|
|
default:
|
|
msg = fmt.Sprintf("%s hits you for %d damage%s.", enemyName, damage, critSuffix)
|
|
}
|
|
}
|
|
debuff := logArgStr(a, "debuffType")
|
|
if debuff != "" {
|
|
msg += " " + englishDebuffName(debuff) + " applied."
|
|
}
|
|
return msg
|
|
}
|
|
|
|
// englishEnemyLogName prefers arg enemyName (DB) when present; else template name from slug.
|
|
func englishEnemyLogName(a map[string]any) string {
|
|
if a == nil {
|
|
return "enemy"
|
|
}
|
|
if n := strings.TrimSpace(logArgStr(a, "enemyName")); n != "" {
|
|
return n
|
|
}
|
|
return englishEnemyDisplayName(logArgStr(a, "enemyType"))
|
|
}
|
|
|
|
func englishEnemyDisplayName(slug string) string {
|
|
slug = strings.TrimSpace(slug)
|
|
if slug == "" {
|
|
return "enemy"
|
|
}
|
|
if e, ok := EnemyBySlug(slug); ok && strings.TrimSpace(e.Name) != "" {
|
|
return e.Name
|
|
}
|
|
return slug
|
|
}
|
|
|
|
func englishDebuffName(debuffType string) string {
|
|
dt, ok := ValidDebuffType(debuffType)
|
|
if !ok {
|
|
return debuffType
|
|
}
|
|
if def, ok := DebuffDefinition(dt); ok && def.Name != "" {
|
|
return def.Name
|
|
}
|
|
return debuffType
|
|
}
|
|
|
|
func englishBuffName(raw string) string {
|
|
raw = strings.ToLower(strings.TrimSpace(raw))
|
|
bt, ok := ValidBuffType(raw)
|
|
if !ok {
|
|
return raw
|
|
}
|
|
if b, ok := BuffDefinition(bt); ok && b.Name != "" {
|
|
return b.Name
|
|
}
|
|
return raw
|
|
}
|
|
|
|
func englishSlotName(raw string) string {
|
|
raw = strings.ToLower(strings.TrimSpace(raw))
|
|
m := map[string]string{
|
|
"main_hand": "weapon",
|
|
"off_hand": "off-hand",
|
|
"head": "head",
|
|
"chest": "chest",
|
|
"legs": "legs",
|
|
"feet": "feet",
|
|
"cloak": "cloak",
|
|
"neck": "neck",
|
|
"finger": "ring",
|
|
"wrist": "wrist",
|
|
"hands": "hands",
|
|
"quiver": "quiver",
|
|
}
|
|
if s, ok := m[raw]; ok {
|
|
return s
|
|
}
|
|
return raw
|
|
}
|
|
|
|
func englishRarityName(raw string) string {
|
|
raw = strings.ToLower(strings.TrimSpace(raw))
|
|
m := map[string]string{
|
|
"common": "common",
|
|
"uncommon": "uncommon",
|
|
"rare": "rare",
|
|
"epic": "epic",
|
|
"legendary": "legendary",
|
|
}
|
|
if s, ok := m[raw]; ok {
|
|
return s
|
|
}
|
|
return raw
|
|
}
|
|
|
|
func logArgStr(a map[string]any, key string) string {
|
|
if a == nil {
|
|
return ""
|
|
}
|
|
v, ok := a[key]
|
|
if !ok || v == nil {
|
|
return ""
|
|
}
|
|
switch x := v.(type) {
|
|
case string:
|
|
return x
|
|
case fmt.Stringer:
|
|
return x.String()
|
|
default:
|
|
return fmt.Sprint(x)
|
|
}
|
|
}
|
|
|
|
func logArgFloat(a map[string]any, key string) float64 {
|
|
if a == nil {
|
|
return 0
|
|
}
|
|
v, ok := a[key]
|
|
if !ok || v == nil {
|
|
return 0
|
|
}
|
|
switch x := v.(type) {
|
|
case float64:
|
|
return x
|
|
case float32:
|
|
return float64(x)
|
|
case int:
|
|
return float64(x)
|
|
case int64:
|
|
return float64(x)
|
|
case uint64:
|
|
return float64(x)
|
|
default:
|
|
return 0
|
|
}
|
|
}
|
|
|
|
func logArgInt(a map[string]any, key string) int {
|
|
return int(logArgFloat(a, key))
|
|
}
|
|
|
|
func logArgBool(a map[string]any, key string) bool {
|
|
if a == nil {
|
|
return false
|
|
}
|
|
v, ok := a[key]
|
|
if !ok || v == nil {
|
|
return false
|
|
}
|
|
switch x := v.(type) {
|
|
case bool:
|
|
return x
|
|
case string:
|
|
return strings.EqualFold(x, "true") || x == "1"
|
|
default:
|
|
return false
|
|
}
|
|
}
|