382 lines
9.2 KiB
Go
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)
|
|
} |