eq2go/internal/combat/types.go
2025-08-30 11:51:05 -05:00

382 lines
9.2 KiB
Go

package combat
import (
"sync"
"time"
)
// Entity represents any combat-capable entity (Player, NPC, etc.)
type Entity interface {
GetID() int32
GetLevel() int32
GetHP() int32
GetTotalHP() int32
GetPower() int32
GetTotalPower() int32
GetX() float32
GetY() float32
GetZ() float32
GetHeading() float32
GetStat(statType int32) int32
SetHP(hp int32)
SetPower(power int32)
IsAlive() bool
SetAlive(alive bool)
IsPlayer() bool
IsNPC() bool
IsPet() bool
IsBot() bool
GetClass() int8
GetRace() int8
GetName() string
GetFactionID() int32
GetZoneID() int32
GetAttackable() int8
SetAttackable(attackable int8)
IsMezzedOrStunned() bool
IsDazed() bool
IsDualWield() bool
GetPrimaryLastAttackTime() int64
GetSecondaryLastAttackTime() int64
GetRangeLastAttackTime() int64
GetPrimaryAttackDelay() int64
GetSecondaryAttackDelay() int64
GetRangeAttackDelay() int64
SetPrimaryLastAttackTime(time int64)
SetSecondaryLastAttackTime(time int64)
SetRangeLastAttackTime(time int64)
GetLockedNoLoot() int32
IsEngagedBySpawnID(spawnID int32) bool
GetInfoStruct() InfoStruct
}
// InfoStruct interface for entity info
type InfoStruct interface {
GetLockableEncounter() bool
GetAlignment() int32
}
// Item represents a weapon or equipment item
type Item interface {
GetID() int32
GetName() string
GetItemType() int8
GetSkillType() int8
GetDamageType() int8
GetMinDamage() int32
GetMaxDamage() int32
GetSpeed() float32
IsRanged() bool
IsAmmo() bool
IsThrown() bool
GetRangeInfo() *RangeInfo
}
// RangeInfo contains ranged weapon information
type RangeInfo struct {
RangeLow float32
RangeHigh float32
}
// Client represents a player client
type Client interface {
GetVersion() int32
SimpleMessage(channel int32, message string)
Message(channel int32, format string, args ...any)
QueuePacket(packet []byte)
GetPlayer() Entity
}
// CombatManager manages all combat operations
type CombatManager struct {
// Combat sessions
activeSessions map[int32]*CombatSession
sessionMutex sync.RWMutex
// Hate management
hateLists map[int32]*HateList
hatesMutex sync.RWMutex
// Statistics
totalAttacks int64
totalDamage int64
totalHealing int64
sessionStats map[int32]*SessionStats
statsMutex sync.RWMutex
// Configuration
config *CombatConfig
// Dependencies
database Database
ruleManager RuleManager
spellManager SpellManager
itemManager ItemManager
zoneManager ZoneManager
hateManager *HateManager
pvpManager *PVPManager
weaponTiming *WeaponTimingManager
}
// CombatSession represents an active combat session
type CombatSession struct {
SessionID int32
AttackerID int32
DefenderID int32
StartTime time.Time
LastActivity time.Time
DamageDealt int64
DamageTaken int64
HealingDealt int64
HealingTaken int64
AttacksLanded int32
AttacksMissed int32
SpellsCast int32
SpellsResisted int32
IsActive bool
CombatType int8
mutex sync.RWMutex
}
// HateList manages hate/threat for an entity
type HateList struct {
OwnerID int32
HateEntries map[int32]*HateEntry
MostHated int32
LastUpdate time.Time
mutex sync.RWMutex
}
// HateEntry represents hate toward a specific target
type HateEntry struct {
TargetID int32
HateAmount int32
DamageAmount int64
LastHit time.Time
IsLocked bool
}
// AttackResult contains the outcome of an attack
type AttackResult struct {
HitType int8
DamageDealt int32
DamageType int8
WeaponSkill int8
CriticalHit bool
Blocked bool
Dodged bool
Parried bool
Riposte bool
Interrupted bool
Resisted bool
Immune bool
TotalDamage int32
Mitigation float32
Weapon Item
SkillIncrease bool
}
// WeaponTiming tracks weapon attack timers
type WeaponTiming struct {
PrimaryReady bool
SecondaryReady bool
RangedReady bool
LastPrimaryTime int64
LastSecondaryTime int64
LastRangedTime int64
PrimaryDelay int64
SecondaryDelay int64
RangedDelay int64
mutex sync.RWMutex
}
// DamageInfo contains damage calculation details
type DamageInfo struct {
BaseDamage int32
ScaledDamage int32
FinalDamage int32
DamageType int8
Mitigation float32
Resistance float32
CriticalMod float32
SpellDamage int32
WeaponDamage int32
EffectiveLevelAttacker int16
EffectiveLevelDefender int16
}
// HealInfo contains healing calculation details
type HealInfo struct {
BaseHealing int32
ScaledHealing int32
FinalHealing int32
CriticalMod float32
SpellHealing int32
WisdomBonus int32
HealingFocus float32
Overheal int32
}
// CombatConfig holds combat system configuration
type CombatConfig struct {
EnablePVP bool
PVPType int32
PVPLevelRange int32
MaxMitigationPercent float32
BaseHitChance float32
BaseCriticalChance float32
BaseDodgeChance float32
BaseParryChance float32
BaseBlockChance float32
HateDecayRate float32
CombatTimeout time.Duration
EnableArmorMitigation bool
EnableSpellResist bool
EnableMultiAttack bool
EnableFlurry bool
EnableBerserk bool
EnableRiposte bool
}
// SessionStats tracks statistics for a combat session
type SessionStats struct {
TotalDamageDealt int64
TotalDamageTaken int64
TotalHealingDealt int64
TotalHealingTaken int64
AttacksLanded int32
AttacksMissed int32
CriticalHits int32
SpellsCast int32
SpellsResisted int32
Duration time.Duration
}
// Database interface for combat persistence
type Database interface {
// Combat logs
LogCombatEvent(event *CombatEvent) error
GetCombatHistory(entityID int32, limit int32) ([]*CombatEvent, error)
// Hate persistence (for NPCs that need to persist hate across server restarts)
SaveHateList(ownerID int32, hateList *HateList) error
LoadHateList(ownerID int32) (*HateList, error)
ClearHateList(ownerID int32) error
// Combat statistics
SaveCombatStats(stats *SessionStats) error
GetPlayerCombatStats(playerID int32) (*SessionStats, error)
}
// CombatEvent represents a combat event for logging
type CombatEvent struct {
ID int64
Timestamp time.Time
AttackerID int32
DefenderID int32
DamageType int8
HitType int8
DamageAmount int32
WeaponType int8
SpellID int32
ZoneID int32
X float32
Y float32
Z float32
}
// RuleManager interface for rule access
type RuleManager interface {
GetBool(category, rule string) bool
GetInt32(category, rule string) int32
GetFloat32(category, rule string) float32
GetZoneBool(zoneID int32, category, rule string) bool
GetZoneInt32(zoneID int32, category, rule string) int32
GetZoneFloat32(zoneID int32, category, rule string) float32
}
// SpellManager interface for spell integration
type SpellManager interface {
GetSpell(spellID int32) Spell
IsSpellCasting(entityID int32) bool
InterruptSpell(entityID int32) bool
CheckFizzle(entityID int32, spell Spell) bool
}
// Spell interface for combat spell integration
type Spell interface {
GetID() int32
GetName() string
GetDamageType() int8
GetBaseDamage() int32
GetCastTime() int32
GetRecoveryTime() int32
GetRange() float32
GetTargetType() int8
IsOffensive() bool
IsHealing() bool
}
// ItemManager interface for weapon/equipment access
type ItemManager interface {
GetItem(itemID int32) Item
GetEquippedItem(entityID int32, slot int8) Item
GetWeaponSkill(weapon Item) int8
GetArmorMitigation(entityID int32) float32
}
// ZoneManager interface for zone operations
type ZoneManager interface {
GetEntitiesInRange(x, y, z, range_ float32, zoneID int32) []Entity
SendCombatMessage(zoneID int32, message string, x, y, z float32)
ProcessEntityCommand(entityID int32, command string, args []string)
}
// CombatPacketBuilder handles combat packet construction
type CombatPacketBuilder interface {
BuildAttackPacket(attacker, defender Entity, result *AttackResult) ([]byte, error)
BuildDamagePacket(victim Entity, damage *DamageInfo) ([]byte, error)
BuildHealPacket(target Entity, healing *HealInfo) ([]byte, error)
BuildCombatLogPacket(event *CombatEvent) ([]byte, error)
BuildInterruptPacket(target Entity) ([]byte, error)
}
// NewCombatSession creates a new combat session
func NewCombatSession(attackerID, defenderID int32, combatType int8) *CombatSession {
return &CombatSession{
SessionID: generateSessionID(),
AttackerID: attackerID,
DefenderID: defenderID,
StartTime: time.Now(),
LastActivity: time.Now(),
IsActive: true,
CombatType: combatType,
}
}
// NewHateList creates a new hate list for an entity
func NewHateList(ownerID int32) *HateList {
return &HateList{
OwnerID: ownerID,
HateEntries: make(map[int32]*HateEntry),
MostHated: 0,
LastUpdate: time.Now(),
}
}
// NewHateEntry creates a new hate entry
func NewHateEntry(targetID int32, initialHate int32) *HateEntry {
return &HateEntry{
TargetID: targetID,
HateAmount: initialHate,
DamageAmount: 0,
LastHit: time.Now(),
IsLocked: false,
}
}
// generateSessionID generates a unique session ID
func generateSessionID() int32 {
// Simple implementation - in production would use proper ID generation
return int32(time.Now().UnixNano() & 0x7FFFFFFF)
}