|
|
|
|
@ -190,7 +190,7 @@ func (h *GameHandler) GetHero(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
hero.RefreshDerivedCombatStats(now)
|
|
|
|
|
writeJSON(w, http.StatusOK, hero)
|
|
|
|
|
writeHeroJSON(w, http.StatusOK, hero)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ActivateBuff activates a buff on the hero.
|
|
|
|
|
@ -277,6 +277,7 @@ func (h *GameHandler) ActivateBuff(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hero.RefreshDerivedCombatStats(now)
|
|
|
|
|
model.AttachDebuffCatalogForClient(hero)
|
|
|
|
|
writeJSON(w, http.StatusOK, map[string]any{
|
|
|
|
|
"buff": ab,
|
|
|
|
|
"heroBuffs": hero.Buffs,
|
|
|
|
|
@ -350,7 +351,7 @@ func (h *GameHandler) ReviveHero(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
h.addLog(hero.ID, "Hero revived")
|
|
|
|
|
|
|
|
|
|
hero.RefreshDerivedCombatStats(now)
|
|
|
|
|
writeJSON(w, http.StatusOK, hero)
|
|
|
|
|
writeHeroJSON(w, http.StatusOK, hero)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// RequestEncounter picks a backend-generated enemy for the hero's current level.
|
|
|
|
|
@ -657,6 +658,7 @@ func (h *GameHandler) ReportVictory(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hero.RefreshDerivedCombatStats(now)
|
|
|
|
|
model.AttachDebuffCatalogForClient(hero)
|
|
|
|
|
writeJSON(w, http.StatusOK, victoryResponse{
|
|
|
|
|
Hero: hero,
|
|
|
|
|
Drops: outDrops,
|
|
|
|
|
@ -916,6 +918,7 @@ func (h *GameHandler) InitHero(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
townsWithNPCs := h.buildTownsWithNPCs(r.Context())
|
|
|
|
|
pCost, hCost := tuning.EffectiveNPCShopCosts()
|
|
|
|
|
|
|
|
|
|
model.AttachDebuffCatalogForClient(hero)
|
|
|
|
|
writeJSON(w, http.StatusOK, map[string]any{
|
|
|
|
|
"hero": hero,
|
|
|
|
|
"needsName": needsName,
|
|
|
|
|
@ -1064,7 +1067,7 @@ func (h *GameHandler) SetHeroName(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
}
|
|
|
|
|
hero.RefreshDerivedCombatStats(now)
|
|
|
|
|
h.logger.Info("hero created with spawn", "hero_id", hero.ID, "name", req.Name)
|
|
|
|
|
writeJSON(w, http.StatusOK, hero)
|
|
|
|
|
writeHeroJSON(w, http.StatusOK, hero)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -1097,7 +1100,7 @@ func (h *GameHandler) SetHeroName(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
|
|
|
|
|
now := time.Now()
|
|
|
|
|
hero.RefreshDerivedCombatStats(now)
|
|
|
|
|
writeJSON(w, http.StatusOK, hero)
|
|
|
|
|
writeHeroJSON(w, http.StatusOK, hero)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// containsUniqueViolation checks if an error message indicates a PostgreSQL unique violation.
|
|
|
|
|
@ -1207,7 +1210,7 @@ func (h *GameHandler) PurchaseBuffRefill(w http.ResponseWriter, r *http.Request)
|
|
|
|
|
h.addLog(hero.ID, fmt.Sprintf("Purchased buff refill: %s", bt))
|
|
|
|
|
|
|
|
|
|
hero.RefreshDerivedCombatStats(now)
|
|
|
|
|
writeJSON(w, http.StatusOK, hero)
|
|
|
|
|
writeHeroJSON(w, http.StatusOK, hero)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// PurchaseSubscription purchases the configured subscription duration (x2 buffs, x2 revives).
|
|
|
|
|
@ -1269,6 +1272,7 @@ func (h *GameHandler) PurchaseSubscription(w http.ResponseWriter, r *http.Reques
|
|
|
|
|
h.addLog(hero.ID, fmt.Sprintf("Subscribed for %s (%d₽) — x2 buffs & revives!", model.SubscriptionDurationLabel(), model.SubscriptionWeeklyPrice()))
|
|
|
|
|
|
|
|
|
|
hero.RefreshDerivedCombatStats(now)
|
|
|
|
|
model.AttachDebuffCatalogForClient(hero)
|
|
|
|
|
writeJSON(w, http.StatusOK, map[string]any{
|
|
|
|
|
"hero": hero,
|
|
|
|
|
"expiresAt": hero.SubscriptionExpiresAt,
|
|
|
|
|
@ -1371,7 +1375,7 @@ func (h *GameHandler) UsePotion(w http.ResponseWriter, r *http.Request) {
|
|
|
|
|
|
|
|
|
|
now := time.Now()
|
|
|
|
|
hero.RefreshDerivedCombatStats(now)
|
|
|
|
|
writeJSON(w, http.StatusOK, hero)
|
|
|
|
|
writeHeroJSON(w, http.StatusOK, hero)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetAdventureLog returns the hero's recent adventure log entries.
|
|
|
|
|
@ -1531,6 +1535,12 @@ func writeJSON(w http.ResponseWriter, status int, v any) {
|
|
|
|
|
json.NewEncoder(w).Encode(v)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// writeHeroJSON encodes a hero with client-only fields (debuff catalog durations).
|
|
|
|
|
func writeHeroJSON(w http.ResponseWriter, status int, hero *model.Hero) {
|
|
|
|
|
model.AttachDebuffCatalogForClient(hero)
|
|
|
|
|
writeJSON(w, status, hero)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// checkAchievementsAfterKill runs achievement condition checks and applies rewards.
|
|
|
|
|
func (h *GameHandler) checkAchievementsAfterKill(hero *model.Hero) {
|
|
|
|
|
if h.achievementStore == nil {
|
|
|
|
|
|