eq2go/internal/spells/spell_data.go

435 lines
14 KiB
Go

package spells
import (
"sync"
)
// LevelArray represents spell level requirements for different classes
type LevelArray struct {
AdventureClass int8 // Adventure class ID
TradeskillClass int8 // Tradeskill class ID
SpellLevel int16 // Required level
ClassicSpellLevel float32 // Classic spell level calculation
}
// SpellDisplayEffect represents a displayed effect in spell descriptions
type SpellDisplayEffect struct {
Percentage int8 // Effect percentage
Subbullet int8 // Subbullet indicator
Description string // Effect description text
NeedsDBSave bool // Whether this needs database saving
}
// LUAData represents Lua script data for spells
type LUAData struct {
Type int8 // Data type (int, float, bool, string)
IntValue int32 // Integer value
BoolValue bool // Boolean value
FloatValue float32 // Float value
StringValue string // String value
StringValue2 string // Second string value
IntValue2 int32 // Second integer value
FloatValue2 float32 // Second float value
StringHelper string // Helper string for identification
NeedsDBSave bool // Whether this needs database saving
}
// SpellData contains all core spell information
// This is the main spell data structure converted from C++ SpellData
type SpellData struct {
// Basic identification
SpellBookType int32 // Type of spell book this belongs to
ID int32 // Unique spell ID
InheritedSpellID int32 // ID of spell this inherits from
Name string // Spell name
Description string // Spell description
// Visual information
Icon int16 // Spell icon ID
IconHeroicOp int16 // Heroic opportunity icon
IconBackdrop int16 // Icon backdrop
SpellVisual int32 // Visual effect ID
// Classification
Type int16 // Spell type
SpellType int8 // Additional spell type classification
ClassSkill int32 // Required class skill
MinClassSkillReq int16 // Minimum class skill requirement
MasterySkill int32 // Mastery skill required
TSLocIndex int8 // Tradeskill location index
Tier int8 // Spell tier
NumLevels int8 // Number of levels this spell has
// Resource requirements
HPReq int16 // Health points required
HPUpkeep int16 // Health points upkeep
PowerReq float32 // Power required to cast
PowerByLevel bool // Power requirement scales by level
PowerUpkeep int16 // Power upkeep cost
SavageryReq int16 // Savagery required
SavageryUpkeep int16 // Savagery upkeep
DissonanceReq int16 // Dissonance required
DissonanceUpkeep int16 // Dissonance upkeep
ReqConcentration int16 // Concentration required
// Percentage-based requirements
PowerReqPercent int8 // Power requirement as percentage of max
HPReqPercent int8 // HP requirement as percentage of max
SavageryReqPercent int8 // Savagery requirement as percentage
DissonanceReqPercent int8 // Dissonance requirement as percentage
// Targeting and range
TargetType int8 // Type of target (self, enemy, group, etc.)
Range float32 // Casting range
MinRange float32 // Minimum casting range
Radius float32 // Area of effect radius
MaxAOETargets int16 // Maximum AoE targets
FriendlySpell int8 // Whether this is a friendly spell
// Timing
CastTime int16 // Cast time in deciseconds
OrigCastTime int16 // Original cast time (before modifications)
Recovery float32 // Recovery time
Recast float32 // Recast delay
LinkedTimer int32 // Linked timer ID
CallFrequency int32 // How often spell effect is called
// Duration and resistibility
Duration1 int32 // Primary duration
Duration2 int32 // Secondary duration
Resistibility float32 // How resistible the spell is
DurationUntilCancel bool // Duration lasts until cancelled
// Combat and effect properties
HitBonus float32 // Hit bonus provided
CanEffectRaid int8 // Can affect raid members
AffectOnlyGroupMembers int8 // Only affects group members
GroupSpell int8 // Is a group spell
DetType int8 // Detrimental type
Incurable bool // Cannot be cured
ControlEffectType int8 // Type of control effect
// Behavioral flags
CastType int8 // Cast type (normal, toggle)
CastingFlags int32 // Various casting flags
CastWhileMoving bool // Can cast while moving
PersistThroughDeath bool // Persists through death
NotMaintained bool // Not a maintained spell
IsAA bool // Is an Alternate Advancement ability
CanFizzle bool // Can fizzle on cast
Interruptable bool // Can be interrupted
IsActive bool // Spell is active/enabled
// Savage bar (for certain spell types)
SavageBar int8 // Savage bar requirement
SavageBarSlot int8 // Savage bar slot
// Messages
SuccessMessage string // Message on successful cast
FadeMessage string // Message when spell fades
FadeMessageOthers string // Fade message for others
EffectMessage string // Effect message
// Scripting
LuaScript string // Lua script filename
// Versioning and classification
DisplaySpellTier int8 // Displayed tier
SOESpellCRC int32 // SOE spell CRC
SpellNameCRC int32 // Spell name CRC
TypeGroupSpellID int32 // Type group spell ID
GivenBy string // Description of how spell was obtained
GivenByType GivenByType // Type of how spell was obtained
// Thread safety
mutex sync.RWMutex
}
// NewSpellData creates a new SpellData with default values
func NewSpellData() *SpellData {
return &SpellData{
SpellBookType: SpellBookTypeSpell,
ID: 0,
InheritedSpellID: 0,
Name: "",
Description: "",
Icon: 0,
IconHeroicOp: 0,
IconBackdrop: 0,
SpellVisual: 0,
Type: 0,
SpellType: 0,
ClassSkill: 0,
MinClassSkillReq: 0,
MasterySkill: 0,
TSLocIndex: 0,
Tier: 1,
NumLevels: 1,
HPReq: 0,
HPUpkeep: 0,
PowerReq: 0.0,
PowerByLevel: false,
PowerUpkeep: 0,
SavageryReq: 0,
SavageryUpkeep: 0,
DissonanceReq: 0,
DissonanceUpkeep: 0,
ReqConcentration: 0,
PowerReqPercent: 0,
HPReqPercent: 0,
SavageryReqPercent: 0,
DissonanceReqPercent: 0,
TargetType: SpellTargetSelf,
Range: 0.0,
MinRange: 0.0,
Radius: 0.0,
MaxAOETargets: 0,
FriendlySpell: 1,
CastTime: 0,
OrigCastTime: 0,
Recovery: 0.0,
Recast: 0.0,
LinkedTimer: 0,
CallFrequency: 0,
Duration1: 0,
Duration2: 0,
Resistibility: 0.0,
DurationUntilCancel: false,
HitBonus: 0.0,
CanEffectRaid: 0,
AffectOnlyGroupMembers: 0,
GroupSpell: 0,
DetType: 0,
Incurable: false,
ControlEffectType: 0,
CastType: SpellCastTypeNormal,
CastingFlags: 0,
CastWhileMoving: false,
PersistThroughDeath: false,
NotMaintained: false,
IsAA: false,
CanFizzle: true,
Interruptable: true,
IsActive: true,
SavageBar: 0,
SavageBarSlot: 0,
SuccessMessage: "",
FadeMessage: "",
FadeMessageOthers: "",
EffectMessage: "",
LuaScript: "",
DisplaySpellTier: 1,
SOESpellCRC: 0,
SpellNameCRC: 0,
TypeGroupSpellID: 0,
GivenBy: "",
GivenByType: GivenByUnset,
}
}
// GetID returns the spell ID (thread-safe)
func (sd *SpellData) GetID() int32 {
sd.mutex.RLock()
defer sd.mutex.RUnlock()
return sd.ID
}
// SetID updates the spell ID (thread-safe)
func (sd *SpellData) SetID(id int32) {
sd.mutex.Lock()
defer sd.mutex.Unlock()
sd.ID = id
}
// GetName returns the spell name (thread-safe)
func (sd *SpellData) GetName() string {
sd.mutex.RLock()
defer sd.mutex.RUnlock()
return sd.Name
}
// SetName updates the spell name (thread-safe)
func (sd *SpellData) SetName(name string) {
sd.mutex.Lock()
defer sd.mutex.Unlock()
sd.Name = name
}
// GetTier returns the spell tier
func (sd *SpellData) GetTier() int8 {
sd.mutex.RLock()
defer sd.mutex.RUnlock()
return sd.Tier
}
// GetDuration returns the primary spell duration
func (sd *SpellData) GetDuration() int32 {
sd.mutex.RLock()
defer sd.mutex.RUnlock()
return sd.Duration1
}
// GetCastTime returns the cast time
func (sd *SpellData) GetCastTime() int16 {
sd.mutex.RLock()
defer sd.mutex.RUnlock()
return sd.CastTime
}
// GetTargetType returns the target type
func (sd *SpellData) GetTargetType() int8 {
sd.mutex.RLock()
defer sd.mutex.RUnlock()
return sd.TargetType
}
// GetRange returns the casting range
func (sd *SpellData) GetRange() float32 {
sd.mutex.RLock()
defer sd.mutex.RUnlock()
return sd.Range
}
// IsHealSpell determines if this is a healing spell
func (sd *SpellData) IsHealSpell() bool {
// TODO: Implement based on spell effects or type classification
return false
}
// IsBuffSpell determines if this is a buff spell
func (sd *SpellData) IsBuffSpell() bool {
// TODO: Implement based on spell effects or duration
return sd.GetDuration() > 0 && sd.FriendlySpell == 1
}
// IsDamageSpell determines if this is a damage spell
func (sd *SpellData) IsDamageSpell() bool {
// TODO: Implement based on spell effects
return false
}
// IsControlSpell determines if this is a control spell
func (sd *SpellData) IsControlSpell() bool {
sd.mutex.RLock()
defer sd.mutex.RUnlock()
return sd.ControlEffectType > 0
}
// IsOffenseSpell determines if this is an offensive spell
func (sd *SpellData) IsOffenseSpell() bool {
sd.mutex.RLock()
defer sd.mutex.RUnlock()
return sd.FriendlySpell == 0
}
// CanCastWhileStunned returns whether spell can be cast while stunned
func (sd *SpellData) CanCastWhileStunned() bool {
// Check casting flags for stun immunity
return (sd.CastingFlags & 0x01) != 0
}
// CanCastWhileMezzed returns whether spell can be cast while mezzed
func (sd *SpellData) CanCastWhileMezzed() bool {
// Check casting flags for mez immunity
return (sd.CastingFlags & 0x02) != 0
}
// CanCastWhileStifled returns whether spell can be cast while stifled
func (sd *SpellData) CanCastWhileStifled() bool {
// Check casting flags for stifle immunity
return (sd.CastingFlags & 0x04) != 0
}
// CanCastWhileFeared returns whether spell can be cast while feared
func (sd *SpellData) CanCastWhileFeared() bool {
// Check casting flags for fear immunity
return (sd.CastingFlags & 0x08) != 0
}
// Clone creates a deep copy of the SpellData
func (sd *SpellData) Clone() *SpellData {
sd.mutex.RLock()
defer sd.mutex.RUnlock()
clone := &SpellData{
SpellBookType: sd.SpellBookType,
ID: sd.ID,
InheritedSpellID: sd.InheritedSpellID,
Name: sd.Name,
Description: sd.Description,
Icon: sd.Icon,
IconHeroicOp: sd.IconHeroicOp,
IconBackdrop: sd.IconBackdrop,
SpellVisual: sd.SpellVisual,
Type: sd.Type,
SpellType: sd.SpellType,
ClassSkill: sd.ClassSkill,
MinClassSkillReq: sd.MinClassSkillReq,
MasterySkill: sd.MasterySkill,
TSLocIndex: sd.TSLocIndex,
Tier: sd.Tier,
NumLevels: sd.NumLevels,
HPReq: sd.HPReq,
HPUpkeep: sd.HPUpkeep,
PowerReq: sd.PowerReq,
PowerByLevel: sd.PowerByLevel,
PowerUpkeep: sd.PowerUpkeep,
SavageryReq: sd.SavageryReq,
SavageryUpkeep: sd.SavageryUpkeep,
DissonanceReq: sd.DissonanceReq,
DissonanceUpkeep: sd.DissonanceUpkeep,
ReqConcentration: sd.ReqConcentration,
PowerReqPercent: sd.PowerReqPercent,
HPReqPercent: sd.HPReqPercent,
SavageryReqPercent: sd.SavageryReqPercent,
DissonanceReqPercent: sd.DissonanceReqPercent,
TargetType: sd.TargetType,
Range: sd.Range,
MinRange: sd.MinRange,
Radius: sd.Radius,
MaxAOETargets: sd.MaxAOETargets,
FriendlySpell: sd.FriendlySpell,
CastTime: sd.CastTime,
OrigCastTime: sd.OrigCastTime,
Recovery: sd.Recovery,
Recast: sd.Recast,
LinkedTimer: sd.LinkedTimer,
CallFrequency: sd.CallFrequency,
Duration1: sd.Duration1,
Duration2: sd.Duration2,
Resistibility: sd.Resistibility,
DurationUntilCancel: sd.DurationUntilCancel,
HitBonus: sd.HitBonus,
CanEffectRaid: sd.CanEffectRaid,
AffectOnlyGroupMembers: sd.AffectOnlyGroupMembers,
GroupSpell: sd.GroupSpell,
DetType: sd.DetType,
Incurable: sd.Incurable,
ControlEffectType: sd.ControlEffectType,
CastType: sd.CastType,
CastingFlags: sd.CastingFlags,
CastWhileMoving: sd.CastWhileMoving,
PersistThroughDeath: sd.PersistThroughDeath,
NotMaintained: sd.NotMaintained,
IsAA: sd.IsAA,
CanFizzle: sd.CanFizzle,
Interruptable: sd.Interruptable,
IsActive: sd.IsActive,
SavageBar: sd.SavageBar,
SavageBarSlot: sd.SavageBarSlot,
SuccessMessage: sd.SuccessMessage,
FadeMessage: sd.FadeMessage,
FadeMessageOthers: sd.FadeMessageOthers,
EffectMessage: sd.EffectMessage,
LuaScript: sd.LuaScript,
DisplaySpellTier: sd.DisplaySpellTier,
SOESpellCRC: sd.SOESpellCRC,
SpellNameCRC: sd.SpellNameCRC,
TypeGroupSpellID: sd.TypeGroupSpellID,
GivenBy: sd.GivenBy,
GivenByType: sd.GivenByType,
}
return clone
}