eq2go/internal/entity/info_struct.go

858 lines
25 KiB
Go

package entity
import (
"sync"
"time"
)
// RaceAlignment represents character alignment types
type RaceAlignment int
const (
AlignmentEvil RaceAlignment = 0
AlignmentGood RaceAlignment = 1
)
// InfoStruct contains all character statistics and information
// This is a comprehensive structure that manages all entity stats,
// equipment bonuses, and various game mechanics data
type InfoStruct struct {
// Basic character information
name string
class1 int8 // Primary class
class2 int8 // Secondary class
class3 int8 // Tertiary class
race int8 // Character race
gender int8 // Character gender
level int16 // Current level
maxLevel int16 // Maximum achievable level
effectiveLevel int16 // Effective level for calculations
tradeskillLevel int16 // Tradeskill level
tradeskillMaxLevel int16 // Maximum tradeskill level
// Concentration system (for maintaining spells)
curConcentration int16 // Current concentration used
maxConcentration int16 // Maximum concentration available
// Combat statistics
curAttack int32 // Current attack rating
attackBase int32 // Base attack rating
curMitigation int32 // Current mitigation (damage reduction)
maxMitigation int32 // Maximum mitigation
mitigationBase int32 // Base mitigation
mitigationMod float32 // Mitigation modifier
// Avoidance statistics
avoidanceDisplay int16 // Display value for avoidance
curAvoidance float32 // Current avoidance percentage
baseAvoidancePct int16 // Base avoidance percentage
avoidanceBase int16 // Base avoidance rating
maxAvoidance int16 // Maximum avoidance
parry float32 // Parry chance
parryBase float32 // Base parry
deflection int16 // Deflection rating
deflectionBase int16 // Base deflection
block int16 // Block rating
blockBase int16 // Base block
// Primary attributes
str float32 // Strength
sta float32 // Stamina
agi float32 // Agility
wis float32 // Wisdom
intel float32 // Intelligence
strBase float32 // Base strength
staBase float32 // Base stamina
agiBase float32 // Base agility
wisBase float32 // Base wisdom
intelBase float32 // Base intelligence
// Resistances
heat int16 // Heat resistance
cold int16 // Cold resistance
magic int16 // Magic resistance
mental int16 // Mental resistance
divine int16 // Divine resistance
disease int16 // Disease resistance
poison int16 // Poison resistance
heatBase int16 // Base heat resistance
coldBase int16 // Base cold resistance
magicBase int16 // Base magic resistance
mentalBase int16 // Base mental resistance
divineBase int16 // Base divine resistance
diseaseBase int16 // Base disease resistance
poisonBase int16 // Base poison resistance
elementalBase int16 // Base elemental resistance
noxiousBase int16 // Base noxious resistance
arcaneBase int16 // Base arcane resistance
// Currency
coinCopper int32 // Copper coins
coinSilver int32 // Silver coins
coinGold int32 // Gold coins
coinPlat int32 // Platinum coins
bankCoinCopper int32 // Banked copper
bankCoinSilver int32 // Banked silver
bankCoinGold int32 // Banked gold
bankCoinPlat int32 // Banked platinum
statusPoints int32 // Status points
// Character details
deity string // Deity name
weight int32 // Current weight
maxWeight int32 // Maximum carrying capacity
// Tradeskill classes
tradeskillClass1 int8 // Primary tradeskill class
tradeskillClass2 int8 // Secondary tradeskill class
tradeskillClass3 int8 // Tertiary tradeskill class
// Account and character age
accountAgeBase int16 // Base account age
accountAgeBonus [19]int8 // Account age bonuses
// Combat and damage
absorb int32 // Damage absorption
// Experience points
xp int32 // Current experience
xpNeeded int32 // Experience needed for next level
xpDebt float32 // Experience debt
xpYellow int32 // Yellow (bonus) experience
xpYellowVitalityBar int32 // Yellow vitality bar
xpBlueVitalityBar int32 // Blue vitality bar
xpBlue int32 // Blue (rested) experience
tsXp int32 // Tradeskill experience
tsXpNeeded int32 // Tradeskill experience needed
tradeskillExpYellow int32 // Tradeskill yellow experience
tradeskillExpBlue int32 // Tradeskill blue experience
xpVitality float32 // Experience vitality
tradeskillXpVitality float32 // Tradeskill experience vitality
// Flags and states
flags int32 // General flags
flags2 int32 // Additional flags
// Specialized mitigation
mitigationSkill1 int16 // Mitigation skill 1
mitigationSkill2 int16 // Mitigation skill 2
mitigationSkill3 int16 // Mitigation skill 3
mitigationPve int16 // PvE mitigation
mitigationPvp int16 // PvP mitigation
// Combat modifiers
abilityModifier int16 // Ability modifier
criticalMitigation int16 // Critical hit mitigation
blockChance int16 // Block chance
uncontestedParry int16 // Uncontested parry
uncontestedBlock int16 // Uncontested block
uncontestedDodge int16 // Uncontested dodge
uncontestedRiposte int16 // Uncontested riposte
critChance int16 // Critical hit chance
critBonus int16 // Critical hit bonus
potency int16 // Spell potency
hateMod int16 // Hate modifier
reuseSpeed int16 // Ability reuse speed
castingSpeed int16 // Spell casting speed
recoverySpeed int16 // Recovery speed
spellReuseSpeed int16 // Spell reuse speed
spellMultiAttack int16 // Spell multi-attack
// Size and physical attributes
sizeMod float32 // Size modifier
ignoreSizeModCalc int8 // Ignore size modifier calculations
dps int16 // Damage per second
dpsMultiplier int16 // DPS multiplier
attackSpeed int16 // Attack speed
haste int16 // Haste
multiAttack int16 // Multi-attack chance
flurry int16 // Flurry chance
meleeAe int16 // Melee area effect
strikethrough int16 // Strikethrough
accuracy int16 // Accuracy
offensiveSpeed int16 // Offensive speed
// Environmental
rain int16 // Rain resistance/affinity
wind int16 // Wind resistance/affinity
alignment int8 // Character alignment
// Pet information
petId int32 // Pet ID
petName string // Pet name
petHealthPct float32 // Pet health percentage
petPowerPct float32 // Pet power percentage
petMovement int8 // Pet movement mode
petBehavior int8 // Pet behavior mode
// Character abilities
vision int8 // Vision type
breatheUnderwater int8 // Can breathe underwater
biography string // Character biography
drunk int8 // Drunk level
// Regeneration
powerRegen int16 // Power regeneration rate
hpRegen int16 // Health regeneration rate
powerRegenOverride int16 // Power regen override
hpRegenOverride int16 // Health regen override
// Movement types
waterType int8 // Water movement type
flyingType int8 // Flying movement type
// Special flags
noInterrupt int8 // Cannot be interrupted
interactionFlag int8 // Interaction flag
tag1 int8 // Tag 1
mood int8 // Mood state
// Weapon timing
rangeLastAttackTime int32 // Last ranged attack time
primaryLastAttackTime int32 // Last primary attack time
secondaryLastAttackTime int32 // Last secondary attack time
primaryAttackDelay int32 // Primary attack delay
secondaryAttackDelay int32 // Secondary attack delay
rangedAttackDelay int32 // Ranged attack delay
// Weapon information
primaryWeaponType int8 // Primary weapon type
secondaryWeaponType int8 // Secondary weapon type
rangedWeaponType int8 // Ranged weapon type
primaryWeaponDmgLow int16 // Primary weapon min damage
primaryWeaponDmgHigh int16 // Primary weapon max damage
secondaryWeaponDmgLow int16 // Secondary weapon min damage
secondaryWeaponDmgHigh int16 // Secondary weapon max damage
rangedWeaponDmgLow int16 // Ranged weapon min damage
rangedWeaponDmgHigh int16 // Ranged weapon max damage
wieldType int8 // Weapon wield type
attackType int8 // Attack type
primaryWeaponDelay int16 // Primary weapon delay
secondaryWeaponDelay int16 // Secondary weapon delay
rangedWeaponDelay int16 // Ranged weapon delay
// Weapon overrides
overridePrimaryWeapon int8 // Override primary weapon
overrideSecondaryWeapon int8 // Override secondary weapon
overrideRangedWeapon int8 // Override ranged weapon
// NPC specific
friendlyTargetNpc int8 // Friendly target NPC flag
lastClaimTime int32 // Last claim time
// Encounter system
engagedEncounter int8 // Engaged in encounter
lockableEncounter int8 // Encounter can be locked
// Player flags
firstWorldLogin int8 // First world login flag
reloadPlayerSpells int8 // Reload player spells flag
// Group settings
groupLootMethod int8 // Group loot method
groupLootItemsRarity int8 // Group loot rarity threshold
groupAutoSplit int8 // Auto-split loot
groupDefaultYell int8 // Default yell in group
groupAutolock int8 // Auto-lock group
groupLockMethod int8 // Group lock method
groupSoloAutolock int8 // Solo auto-lock
groupAutoLootMethod int8 // Auto-loot method
assistAutoAttack int8 // Assist auto-attack
// Action state
actionState string // Current action state
// Spell and ability reductions
spellMulticastChance int16 // Spell multicast chance
maxSpellReductionOverride int16 // Max spell reduction override
maxChaseDistance float32 // Maximum chase distance
// Thread safety
mutex sync.RWMutex
}
// NewInfoStruct creates a new InfoStruct with default values
// Initializes all fields to appropriate defaults for a new entity
func NewInfoStruct() *InfoStruct {
return &InfoStruct{
name: "",
class1: 0,
class2: 0,
class3: 0,
race: 0,
gender: 0,
level: 0,
maxLevel: 0,
effectiveLevel: 0,
tradeskillLevel: 0,
tradeskillMaxLevel: 0,
curConcentration: 0,
maxConcentration: 5, // Default max concentration
curAttack: 0,
attackBase: 0,
curMitigation: 0,
maxMitigation: 0,
mitigationBase: 0,
mitigationMod: 0,
avoidanceDisplay: 0,
curAvoidance: 0.0,
baseAvoidancePct: 0,
avoidanceBase: 0,
maxAvoidance: 0,
parry: 0.0,
parryBase: 0.0,
deflection: 0,
deflectionBase: 0,
block: 0,
blockBase: 0,
str: 0.0,
sta: 0.0,
agi: 0.0,
wis: 0.0,
intel: 0.0,
strBase: 0.0,
staBase: 0.0,
agiBase: 0.0,
wisBase: 0.0,
intelBase: 0.0,
heat: 0,
cold: 0,
magic: 0,
mental: 0,
divine: 0,
disease: 0,
poison: 0,
heatBase: 0,
coldBase: 0,
magicBase: 0,
mentalBase: 0,
divineBase: 0,
diseaseBase: 0,
poisonBase: 0,
elementalBase: 0,
noxiousBase: 0,
arcaneBase: 0,
coinCopper: 0,
coinSilver: 0,
coinGold: 0,
coinPlat: 0,
bankCoinCopper: 0,
bankCoinSilver: 0,
bankCoinGold: 0,
bankCoinPlat: 0,
statusPoints: 0,
deity: "",
weight: 0,
maxWeight: 0,
tradeskillClass1: 0,
tradeskillClass2: 0,
tradeskillClass3: 0,
accountAgeBase: 0,
absorb: 0,
xp: 0,
xpNeeded: 0,
xpDebt: 0.0,
xpYellow: 0,
xpYellowVitalityBar: 0,
xpBlueVitalityBar: 0,
xpBlue: 0,
tsXp: 0,
tsXpNeeded: 0,
tradeskillExpYellow: 0,
tradeskillExpBlue: 0,
flags: 0,
flags2: 0,
xpVitality: 0,
tradeskillXpVitality: 0,
mitigationSkill1: 0,
mitigationSkill2: 0,
mitigationSkill3: 0,
mitigationPve: 0,
mitigationPvp: 0,
abilityModifier: 0,
criticalMitigation: 0,
blockChance: 0,
uncontestedParry: 0,
uncontestedBlock: 0,
uncontestedDodge: 0,
uncontestedRiposte: 0,
critChance: 0,
critBonus: 0,
potency: 0,
hateMod: 0,
reuseSpeed: 0,
castingSpeed: 0,
recoverySpeed: 0,
spellReuseSpeed: 0,
spellMultiAttack: 0,
sizeMod: 0.0,
ignoreSizeModCalc: 0,
dps: 0,
dpsMultiplier: 0,
attackSpeed: 0,
haste: 0,
multiAttack: 0,
flurry: 0,
meleeAe: 0,
strikethrough: 0,
accuracy: 0,
offensiveSpeed: 0,
rain: 0,
wind: 0,
alignment: 0,
petId: 0,
petName: "",
petHealthPct: 0.0,
petPowerPct: 0.0,
petMovement: 0,
petBehavior: 0,
vision: 0,
breatheUnderwater: 0,
biography: "",
drunk: 0,
powerRegen: 0,
hpRegen: 0,
powerRegenOverride: 0,
hpRegenOverride: 0,
waterType: 0,
flyingType: 0,
noInterrupt: 0,
interactionFlag: 0,
tag1: 0,
mood: 0,
rangeLastAttackTime: 0,
primaryLastAttackTime: 0,
secondaryLastAttackTime: 0,
primaryAttackDelay: 0,
secondaryAttackDelay: 0,
rangedAttackDelay: 0,
primaryWeaponType: 0,
secondaryWeaponType: 0,
rangedWeaponType: 0,
primaryWeaponDmgLow: 0,
primaryWeaponDmgHigh: 0,
secondaryWeaponDmgLow: 0,
secondaryWeaponDmgHigh: 0,
rangedWeaponDmgLow: 0,
rangedWeaponDmgHigh: 0,
wieldType: 0,
attackType: 0,
primaryWeaponDelay: 0,
secondaryWeaponDelay: 0,
rangedWeaponDelay: 0,
overridePrimaryWeapon: 0,
overrideSecondaryWeapon: 0,
overrideRangedWeapon: 0,
friendlyTargetNpc: 0,
lastClaimTime: 0,
engagedEncounter: 0,
lockableEncounter: 1,
firstWorldLogin: 0,
reloadPlayerSpells: 0,
groupLootMethod: 1,
groupLootItemsRarity: 0,
groupAutoSplit: 1,
groupDefaultYell: 1,
groupAutolock: 0,
groupLockMethod: 0,
groupSoloAutolock: 0,
groupAutoLootMethod: 0,
assistAutoAttack: 0,
actionState: "",
spellMulticastChance: 0,
maxSpellReductionOverride: 0,
maxChaseDistance: 0.0,
}
}
// GetName returns the entity's name
func (info *InfoStruct) GetName() string {
info.mutex.RLock()
defer info.mutex.RUnlock()
return info.name
}
// SetName updates the entity's name
func (info *InfoStruct) SetName(name string) {
info.mutex.Lock()
defer info.mutex.Unlock()
info.name = name
}
// GetLevel returns the entity's level
func (info *InfoStruct) GetLevel() int16 {
info.mutex.RLock()
defer info.mutex.RUnlock()
return info.level
}
// SetLevel updates the entity's level
func (info *InfoStruct) SetLevel(level int16) {
info.mutex.Lock()
defer info.mutex.Unlock()
info.level = level
}
// GetEffectiveLevel returns the entity's effective level for calculations
func (info *InfoStruct) GetEffectiveLevel() int16 {
info.mutex.RLock()
defer info.mutex.RUnlock()
return info.effectiveLevel
}
// SetEffectiveLevel updates the entity's effective level
func (info *InfoStruct) SetEffectiveLevel(level int16) {
info.mutex.Lock()
defer info.mutex.Unlock()
info.effectiveLevel = level
}
// GetClass1 returns the primary class
func (info *InfoStruct) GetClass1() int8 {
info.mutex.RLock()
defer info.mutex.RUnlock()
return info.class1
}
// SetClass1 updates the primary class
func (info *InfoStruct) SetClass1(class int8) {
info.mutex.Lock()
defer info.mutex.Unlock()
info.class1 = class
}
// GetRace returns the entity's race
func (info *InfoStruct) GetRace() int8 {
info.mutex.RLock()
defer info.mutex.RUnlock()
return info.race
}
// SetRace updates the entity's race
func (info *InfoStruct) SetRace(race int8) {
info.mutex.Lock()
defer info.mutex.Unlock()
info.race = race
}
// GetGender returns the entity's gender
func (info *InfoStruct) GetGender() int8 {
info.mutex.RLock()
defer info.mutex.RUnlock()
return info.gender
}
// SetGender updates the entity's gender
func (info *InfoStruct) SetGender(gender int8) {
info.mutex.Lock()
defer info.mutex.Unlock()
info.gender = gender
}
// GetStr returns the strength stat
func (info *InfoStruct) GetStr() float32 {
info.mutex.RLock()
defer info.mutex.RUnlock()
return info.str
}
// SetStr updates the strength stat
func (info *InfoStruct) SetStr(str float32) {
info.mutex.Lock()
defer info.mutex.Unlock()
info.str = str
}
// GetSta returns the stamina stat
func (info *InfoStruct) GetSta() float32 {
info.mutex.RLock()
defer info.mutex.RUnlock()
return info.sta
}
// SetSta updates the stamina stat
func (info *InfoStruct) SetSta(sta float32) {
info.mutex.Lock()
defer info.mutex.Unlock()
info.sta = sta
}
// GetAgi returns the agility stat
func (info *InfoStruct) GetAgi() float32 {
info.mutex.RLock()
defer info.mutex.RUnlock()
return info.agi
}
// SetAgi updates the agility stat
func (info *InfoStruct) SetAgi(agi float32) {
info.mutex.Lock()
defer info.mutex.Unlock()
info.agi = agi
}
// GetWis returns the wisdom stat
func (info *InfoStruct) GetWis() float32 {
info.mutex.RLock()
defer info.mutex.RUnlock()
return info.wis
}
// SetWis updates the wisdom stat
func (info *InfoStruct) SetWis(wis float32) {
info.mutex.Lock()
defer info.mutex.Unlock()
info.wis = wis
}
// GetIntel returns the intelligence stat
func (info *InfoStruct) GetIntel() float32 {
info.mutex.RLock()
defer info.mutex.RUnlock()
return info.intel
}
// SetIntel updates the intelligence stat
func (info *InfoStruct) SetIntel(intel float32) {
info.mutex.Lock()
defer info.mutex.Unlock()
info.intel = intel
}
// GetMaxConcentration returns the maximum concentration
func (info *InfoStruct) GetMaxConcentration() int16 {
info.mutex.RLock()
defer info.mutex.RUnlock()
return info.maxConcentration
}
// SetMaxConcentration updates the maximum concentration
func (info *InfoStruct) SetMaxConcentration(maxConcentration int16) {
info.mutex.Lock()
defer info.mutex.Unlock()
info.maxConcentration = maxConcentration
}
// GetCurConcentration returns the current concentration used
func (info *InfoStruct) GetCurConcentration() int16 {
info.mutex.RLock()
defer info.mutex.RUnlock()
return info.curConcentration
}
// SetCurConcentration updates the current concentration used
func (info *InfoStruct) SetCurConcentration(curConcentration int16) {
info.mutex.Lock()
defer info.mutex.Unlock()
info.curConcentration = curConcentration
}
// AddConcentration adds to the current concentration used
func (info *InfoStruct) AddConcentration(amount int16) bool {
info.mutex.Lock()
defer info.mutex.Unlock()
if info.curConcentration+amount > info.maxConcentration {
return false // Not enough concentration available
}
info.curConcentration += amount
return true
}
// RemoveConcentration removes from the current concentration used
func (info *InfoStruct) RemoveConcentration(amount int16) {
info.mutex.Lock()
defer info.mutex.Unlock()
info.curConcentration -= amount
if info.curConcentration < 0 {
info.curConcentration = 0
}
}
// GetCoins returns total coin value in copper
func (info *InfoStruct) GetCoins() int32 {
info.mutex.RLock()
defer info.mutex.RUnlock()
return info.coinCopper + (info.coinSilver * 100) +
(info.coinGold * 10000) + (info.coinPlat * 1000000)
}
// AddCoins adds coins to the entity (automatically distributes to appropriate denominations)
func (info *InfoStruct) AddCoins(copperAmount int32) {
info.mutex.Lock()
defer info.mutex.Unlock()
totalCopper := info.coinCopper + copperAmount
// Convert to higher denominations
info.coinPlat += totalCopper / 1000000
totalCopper %= 1000000
info.coinGold += totalCopper / 10000
totalCopper %= 10000
info.coinSilver += totalCopper / 100
info.coinCopper = totalCopper % 100
}
// RemoveCoins removes coins from the entity
func (info *InfoStruct) RemoveCoins(copperAmount int32) bool {
info.mutex.Lock()
defer info.mutex.Unlock()
totalCopper := info.coinCopper + (info.coinSilver * 100) +
(info.coinGold * 10000) + (info.coinPlat * 1000000)
if totalCopper < copperAmount {
return false // Not enough coins
}
totalCopper -= copperAmount
// Redistribute
info.coinPlat = totalCopper / 1000000
totalCopper %= 1000000
info.coinGold = totalCopper / 10000
totalCopper %= 10000
info.coinSilver = totalCopper / 100
info.coinCopper = totalCopper % 100
return true
}
// GetResistance returns the resistance value for a specific type
func (info *InfoStruct) GetResistance(resistType string) int16 {
info.mutex.RLock()
defer info.mutex.RUnlock()
switch resistType {
case "heat":
return info.heat
case "cold":
return info.cold
case "magic":
return info.magic
case "mental":
return info.mental
case "divine":
return info.divine
case "disease":
return info.disease
case "poison":
return info.poison
default:
return 0
}
}
// SetResistance updates a resistance value
func (info *InfoStruct) SetResistance(resistType string, value int16) {
info.mutex.Lock()
defer info.mutex.Unlock()
switch resistType {
case "heat":
info.heat = value
case "cold":
info.cold = value
case "magic":
info.magic = value
case "mental":
info.mental = value
case "divine":
info.divine = value
case "disease":
info.disease = value
case "poison":
info.poison = value
}
}
// ResetEffects resets all temporary effects and bonuses
// This method should be called when recalculating all bonuses
func (info *InfoStruct) ResetEffects() {
info.mutex.Lock()
defer info.mutex.Unlock()
// Reset stats to base values
info.str = info.strBase
info.sta = info.staBase
info.agi = info.agiBase
info.wis = info.wisBase
info.intel = info.intelBase
info.heat = info.heatBase
info.cold = info.coldBase
info.magic = info.magicBase
info.mental = info.mentalBase
info.divine = info.divineBase
info.disease = info.diseaseBase
info.poison = info.poisonBase
info.parry = info.parryBase
info.deflection = info.deflectionBase
info.block = info.blockBase
// Reset combat stats to base
info.curAttack = info.attackBase
info.curMitigation = info.mitigationBase
info.curAvoidance = float32(info.baseAvoidancePct)
}
// CalculatePrimaryStat returns the highest primary stat value
func (info *InfoStruct) CalculatePrimaryStat() float32 {
info.mutex.RLock()
defer info.mutex.RUnlock()
primary := info.str
if info.sta > primary {
primary = info.sta
}
if info.agi > primary {
primary = info.agi
}
if info.wis > primary {
primary = info.wis
}
if info.intel > primary {
primary = info.intel
}
return primary
}
// Clone creates a deep copy of the InfoStruct
func (info *InfoStruct) Clone() *InfoStruct {
info.mutex.RLock()
defer info.mutex.RUnlock()
clone := &InfoStruct{}
*clone = *info // Copy all fields
// Reset the mutex in the clone to avoid sharing the same mutex
clone.mutex = sync.RWMutex{}
// Copy the account age bonus array
copy(clone.accountAgeBonus[:], info.accountAgeBonus[:])
return clone
}
// GetUptime returns how long the entity has been active (for players, time logged in)
func (info *InfoStruct) GetUptime() time.Duration {
// TODO: Implement when we have login tracking
return time.Duration(0)
}
// TODO: Additional methods to implement:
// - Experience calculation methods
// - Weapon damage calculation methods
// - Spell-related stat methods
// - Group and encounter methods
// - Equipment bonus application methods