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.

192 lines
5.7 KiB
Go

package model
import "time"
// ---- Buffs ----
type BuffType string
const (
BuffRush BuffType = "rush" // +attack speed
BuffRage BuffType = "rage" // +damage
BuffShield BuffType = "shield" // -incoming damage
BuffLuck BuffType = "luck" // x2.5 loot
BuffResurrection BuffType = "resurrection" // revive on death
BuffHeal BuffType = "heal" // +50% HP instantly
BuffPowerPotion BuffType = "power_potion" // +150% damage
BuffWarCry BuffType = "war_cry" // +100% attack speed
)
// AllBuffTypes is the complete list of valid buff types.
var AllBuffTypes = []BuffType{
BuffRush, BuffRage, BuffShield, BuffLuck, BuffResurrection,
BuffHeal, BuffPowerPotion, BuffWarCry,
}
// ValidBuffType checks if a string is a valid buff type.
func ValidBuffType(s string) (BuffType, bool) {
bt := BuffType(s)
for _, t := range AllBuffTypes {
if t == bt {
return bt, true
}
}
return "", false
}
type Buff struct {
ID int64 `json:"id"`
Type BuffType `json:"type"`
Name string `json:"name"`
Duration time.Duration `json:"duration"`
Magnitude float64 `json:"magnitude"` // effect strength (e.g., 0.3 = +30%)
CooldownDuration time.Duration `json:"cooldownDuration"`
}
type ActiveBuff struct {
Buff Buff `json:"buff"`
AppliedAt time.Time `json:"appliedAt"`
ExpiresAt time.Time `json:"expiresAt"`
}
// IsExpired returns true if the buff has expired relative to the given time.
func (ab *ActiveBuff) IsExpired(now time.Time) bool {
return now.After(ab.ExpiresAt)
}
// DefaultBuffs defines the base buff definitions.
var DefaultBuffs = map[BuffType]Buff{
BuffRush: {
Type: BuffRush, Name: "Rush",
Duration: 5 * time.Minute, Magnitude: 0.5, // +50% movement
CooldownDuration: 15 * time.Minute,
},
BuffRage: {
Type: BuffRage, Name: "Rage",
Duration: 3 * time.Minute, Magnitude: 1.0, // +100% damage
CooldownDuration: 10 * time.Minute,
},
BuffShield: {
Type: BuffShield, Name: "Shield",
Duration: 5 * time.Minute, Magnitude: 0.5, // -50% incoming damage
CooldownDuration: 12 * time.Minute,
},
BuffLuck: {
Type: BuffLuck, Name: "Luck",
Duration: 30 * time.Minute, Magnitude: 1.5, // x2.5 loot
CooldownDuration: 2 * time.Hour,
},
BuffResurrection: {
Type: BuffResurrection, Name: "Resurrection",
Duration: 10 * time.Minute, Magnitude: 0.5, // revive with 50% HP
CooldownDuration: 30 * time.Minute,
},
BuffHeal: {
Type: BuffHeal, Name: "Heal",
Duration: 1 * time.Second, Magnitude: 0.5, // +50% HP (instant)
CooldownDuration: 5 * time.Minute,
},
BuffPowerPotion: {
Type: BuffPowerPotion, Name: "Power Potion",
Duration: 5 * time.Minute, Magnitude: 1.5, // +150% damage
CooldownDuration: 20 * time.Minute,
},
BuffWarCry: {
Type: BuffWarCry, Name: "War Cry",
Duration: 3 * time.Minute, Magnitude: 1.0, // +100% attack speed
CooldownDuration: 10 * time.Minute,
},
}
// ---- Debuffs ----
type DebuffType string
const (
DebuffPoison DebuffType = "poison" // -2% HP/sec
DebuffFreeze DebuffType = "freeze" // -50% attack speed
DebuffBurn DebuffType = "burn" // -3% HP/sec
DebuffStun DebuffType = "stun" // no attacks for 2 sec
DebuffSlow DebuffType = "slow" // -40% movement speed (not attack speed)
DebuffWeaken DebuffType = "weaken" // -30% hero outgoing damage
DebuffIceSlow DebuffType = "ice_slow" // -20% attack speed (Ice Guardian per spec §4.2)
)
// AllDebuffTypes is the complete list of valid debuff types.
var AllDebuffTypes = []DebuffType{
DebuffPoison, DebuffFreeze, DebuffBurn, DebuffStun, DebuffSlow, DebuffWeaken, DebuffIceSlow,
}
// ValidDebuffType checks if a string is a valid debuff type.
func ValidDebuffType(s string) (DebuffType, bool) {
dt := DebuffType(s)
for _, t := range AllDebuffTypes {
if t == dt {
return dt, true
}
}
return "", false
}
type Debuff struct {
ID int64 `json:"id"`
Type DebuffType `json:"type"`
Name string `json:"name"`
Duration time.Duration `json:"duration"`
Magnitude float64 `json:"magnitude"` // effect strength
}
type ActiveDebuff struct {
Debuff Debuff `json:"debuff"`
AppliedAt time.Time `json:"appliedAt"`
ExpiresAt time.Time `json:"expiresAt"`
}
// IsExpired returns true if the debuff has expired relative to the given time.
func (ad *ActiveDebuff) IsExpired(now time.Time) bool {
return now.After(ad.ExpiresAt)
}
// DefaultDebuffs defines the base debuff definitions.
var DefaultDebuffs = map[DebuffType]Debuff{
DebuffPoison: {
Type: DebuffPoison, Name: "Poison",
Duration: 5 * time.Second, Magnitude: 0.02, // -2% HP/sec
},
DebuffFreeze: {
Type: DebuffFreeze, Name: "Freeze",
Duration: 3 * time.Second, Magnitude: 0.50, // -50% attack speed
},
DebuffBurn: {
Type: DebuffBurn, Name: "Burn",
Duration: 4 * time.Second, Magnitude: 0.03, // -3% HP/sec
},
DebuffStun: {
Type: DebuffStun, Name: "Stun",
Duration: 2 * time.Second, Magnitude: 1.0, // no attacks
},
DebuffSlow: {
Type: DebuffSlow, Name: "Slow",
Duration: 4 * time.Second, Magnitude: 0.40, // -40% movement
},
DebuffWeaken: {
Type: DebuffWeaken, Name: "Weaken",
Duration: 5 * time.Second, Magnitude: 0.30, // -30% hero outgoing damage
},
DebuffIceSlow: {
Type: DebuffIceSlow, Name: "Ice Slow",
Duration: 4 * time.Second, Magnitude: 0.20, // -20% attack speed (Ice Guardian spec §4.2)
},
}
// RemoveBuffType returns buffs without any active entry of the given type (e.g. consume Resurrection on manual revive).
func RemoveBuffType(buff []ActiveBuff, remove BuffType) []ActiveBuff {
var out []ActiveBuff
for _, ab := range buff {
if ab.Buff.Type != remove {
out = append(out, ab)
}
}
return out
}