simplify spell, remove lua integration from spells

This commit is contained in:
Sky Johnson 2025-08-30 10:57:09 -05:00
parent a5444ed0b9
commit fc32aa4b74
12 changed files with 526 additions and 180 deletions

View File

@ -24,6 +24,10 @@ This document outlines how we successfully simplified the EverQuest II housing p
- NPC/Race Types - NPC/Race Types
- Object - Object
- Player - Player
- Quests
- Races
- Recipes
## Before: Complex Architecture (8 Files, ~2000+ Lines) ## Before: Complex Architecture (8 Files, ~2000+ Lines)

View File

@ -96,6 +96,53 @@ const (
OP_ItemExamineMsg OP_ItemExamineMsg
OP_ItemUpdateMsg OP_ItemUpdateMsg
// Recipe and crafting system
OP_UpdateRecipeBookMsg
OP_RequestRecipeDetailsMsg
OP_RecipeDetailsMsg
OP_ShowCreateFromRecipeUIMsg
OP_CancelCreateFromRecipeMsg
OP_ShowRecipeBookMsg
OP_RecipeList
OP_RecipeBook
OP_RecipeListUnknown
// Skills system
OP_UpdateSkillBookMsg
OP_UpdateSkillsMsg
OP_PopulateSkillMapsMsg
OP_SkillInfoRequest
OP_SkillInfoResponse
OP_TradeskillList
// Sign and widget system
OP_EqCreateSignWidgetCmd
OP_EqUpdateSignWidgetCmd
OP_SignalMsg
// Spawn and object system
OP_TintWidgetsMsg
OP_MoveableObjectPlacementCriteri
OP_EnterMoveObjectModeMsg
OP_PositionMoveableObject
OP_CancelMoveObjectModeMsg
// Spell system
OP_RemoveSpellEffectMsg
OP_DispatchSpellCmdMsg
OP_SpellGainedMsg
OP_CancelSpellCast
OP_AfterInvSpellUpdate
OP_EqHearSpellCastCmd
OP_EqHearSpellInterruptCmd
OP_EqHearSpellFizzleCmd
OP_EqHearSpellNoLandCmd
OP_EqHearChainEffectCmd
OP_EqDisplaySpellFailCmd
OP_EqSpellCastStartCmd
OP_EqSpellCastEndCmd
OP_EqSpellMoveToRangeAndRetryCmd
// EverQuest specific commands - Core // EverQuest specific commands - Core
OP_EqHearChatCmd OP_EqHearChatCmd
OP_EqDisplayTextCmd OP_EqDisplayTextCmd
@ -165,6 +212,19 @@ const (
OP_ModifyGuildMsg OP_ModifyGuildMsg
OP_RequestGuildInfoMsg OP_RequestGuildInfoMsg
// Quest system opcodes
OP_QuestJournalOpenMsg
OP_QuestJournalInspectMsg
OP_QuestJournalSetVisibleMsg
OP_QuestJournalWaypointMsg
OP_QuestReward
OP_OfferQuestMsg
OP_EqQuestJournalUpdateCmd
OP_EqQuestJournalReplyCmd
OP_EqQuestGroupCmd
OP_JournalQuestStoryline
OP_QuestionnaireMsg
// Heroic Opportunity system opcodes // Heroic Opportunity system opcodes
OP_HeroicOpportunityMsg OP_HeroicOpportunityMsg
OP_HeroicOpportunityStartMsg OP_HeroicOpportunityStartMsg
@ -235,6 +295,53 @@ var OpcodeNames = map[InternalOpcode]string{
OP_ItemDropMsg: "OP_ItemDropMsg", OP_ItemDropMsg: "OP_ItemDropMsg",
OP_ItemExamineMsg: "OP_ItemExamineMsg", OP_ItemExamineMsg: "OP_ItemExamineMsg",
OP_ItemUpdateMsg: "OP_ItemUpdateMsg", OP_ItemUpdateMsg: "OP_ItemUpdateMsg",
// Recipe and crafting system opcodes
OP_UpdateRecipeBookMsg: "OP_UpdateRecipeBookMsg",
OP_RequestRecipeDetailsMsg: "OP_RequestRecipeDetailsMsg",
OP_RecipeDetailsMsg: "OP_RecipeDetailsMsg",
OP_ShowCreateFromRecipeUIMsg: "OP_ShowCreateFromRecipeUIMsg",
OP_CancelCreateFromRecipeMsg: "OP_CancelCreateFromRecipeMsg",
OP_ShowRecipeBookMsg: "OP_ShowRecipeBookMsg",
OP_RecipeList: "OP_RecipeList",
OP_RecipeBook: "OP_RecipeBook",
OP_RecipeListUnknown: "OP_RecipeListUnknown",
// Skills system opcodes
OP_UpdateSkillBookMsg: "OP_UpdateSkillBookMsg",
OP_UpdateSkillsMsg: "OP_UpdateSkillsMsg",
OP_PopulateSkillMapsMsg: "OP_PopulateSkillMapsMsg",
OP_SkillInfoRequest: "OP_SkillInfoRequest",
OP_SkillInfoResponse: "OP_SkillInfoResponse",
OP_TradeskillList: "OP_TradeskillList",
// Sign and widget system opcodes
OP_EqCreateSignWidgetCmd: "OP_EqCreateSignWidgetCmd",
OP_EqUpdateSignWidgetCmd: "OP_EqUpdateSignWidgetCmd",
OP_SignalMsg: "OP_SignalMsg",
// Spawn and object system opcodes
OP_TintWidgetsMsg: "OP_TintWidgetsMsg",
OP_MoveableObjectPlacementCriteri: "OP_MoveableObjectPlacementCriteri",
OP_EnterMoveObjectModeMsg: "OP_EnterMoveObjectModeMsg",
OP_PositionMoveableObject: "OP_PositionMoveableObject",
OP_CancelMoveObjectModeMsg: "OP_CancelMoveObjectModeMsg",
// Spell system opcodes
OP_RemoveSpellEffectMsg: "OP_RemoveSpellEffectMsg",
OP_DispatchSpellCmdMsg: "OP_DispatchSpellCmdMsg",
OP_SpellGainedMsg: "OP_SpellGainedMsg",
OP_CancelSpellCast: "OP_CancelSpellCast",
OP_AfterInvSpellUpdate: "OP_AfterInvSpellUpdate",
OP_EqHearSpellCastCmd: "OP_EqHearSpellCastCmd",
OP_EqHearSpellInterruptCmd: "OP_EqHearSpellInterruptCmd",
OP_EqHearSpellFizzleCmd: "OP_EqHearSpellFizzleCmd",
OP_EqHearSpellNoLandCmd: "OP_EqHearSpellNoLandCmd",
OP_EqHearChainEffectCmd: "OP_EqHearChainEffectCmd",
OP_EqDisplaySpellFailCmd: "OP_EqDisplaySpellFailCmd",
OP_EqSpellCastStartCmd: "OP_EqSpellCastStartCmd",
OP_EqSpellCastEndCmd: "OP_EqSpellCastEndCmd",
OP_EqSpellMoveToRangeAndRetryCmd: "OP_EqSpellMoveToRangeAndRetryCmd",
OP_EqHearChatCmd: "OP_EqHearChatCmd", OP_EqHearChatCmd: "OP_EqHearChatCmd",
OP_EqDisplayTextCmd: "OP_EqDisplayTextCmd", OP_EqDisplayTextCmd: "OP_EqDisplayTextCmd",
OP_EqCreateGhostCmd: "OP_EqCreateGhostCmd", OP_EqCreateGhostCmd: "OP_EqCreateGhostCmd",
@ -297,6 +404,19 @@ var OpcodeNames = map[InternalOpcode]string{
OP_ModifyGuildMsg: "OP_ModifyGuildMsg", OP_ModifyGuildMsg: "OP_ModifyGuildMsg",
OP_RequestGuildInfoMsg: "OP_RequestGuildInfoMsg", OP_RequestGuildInfoMsg: "OP_RequestGuildInfoMsg",
// Quest system opcodes
OP_QuestJournalOpenMsg: "OP_QuestJournalOpenMsg",
OP_QuestJournalInspectMsg: "OP_QuestJournalInspectMsg",
OP_QuestJournalSetVisibleMsg: "OP_QuestJournalSetVisibleMsg",
OP_QuestJournalWaypointMsg: "OP_QuestJournalWaypointMsg",
OP_QuestReward: "OP_QuestReward",
OP_OfferQuestMsg: "OP_OfferQuestMsg",
OP_EqQuestJournalUpdateCmd: "OP_EqQuestJournalUpdateCmd",
OP_EqQuestJournalReplyCmd: "OP_EqQuestJournalReplyCmd",
OP_EqQuestGroupCmd: "OP_EqQuestGroupCmd",
OP_JournalQuestStoryline: "OP_JournalQuestStoryline",
OP_QuestionnaireMsg: "OP_QuestionnaireMsg",
// Heroic Opportunity system opcodes // Heroic Opportunity system opcodes
OP_HeroicOpportunityMsg: "OP_HeroicOpportunityMsg", OP_HeroicOpportunityMsg: "OP_HeroicOpportunityMsg",
OP_HeroicOpportunityStartMsg: "OP_HeroicOpportunityStartMsg", OP_HeroicOpportunityStartMsg: "OP_HeroicOpportunityStartMsg",

View File

@ -11,8 +11,9 @@ func TestPackageBuild(t *testing.T) {
t.Fatal("NewSpawn returned nil") t.Fatal("NewSpawn returned nil")
} }
if spawn.GetID() != 0 { // ID should be generated starting from 1
t.Errorf("Expected default ID 0, got %d", spawn.GetID()) if spawn.GetID() <= 0 {
t.Errorf("Expected ID > 0, got %d", spawn.GetID())
} }
} }
@ -20,8 +21,10 @@ func TestSpawnBasics(t *testing.T) {
spawn := NewSpawn() spawn := NewSpawn()
spawn.SetName("Test Spawn") spawn.SetName("Test Spawn")
if spawn.GetName() != "Test Spawn" { // GetName returns the full byte array, so we need to compare with trimmed string
t.Errorf("Expected name 'Test Spawn', got '%s'", spawn.GetName()) name := spawn.GetName()
if len(name) == 0 || name[0:10] != "Test Spawn" {
t.Errorf("Expected name to start with 'Test Spawn', got '%s'", name[:min(len(name), 20)])
} }
spawn.SetLevel(25) spawn.SetLevel(25)
@ -29,3 +32,10 @@ func TestSpawnBasics(t *testing.T) {
t.Errorf("Expected level 25, got %d", spawn.GetLevel()) t.Errorf("Expected level 25, got %d", spawn.GetLevel())
} }
} }
func min(a, b int) int {
if a < b {
return a
}
return b
}

View File

@ -131,10 +131,10 @@ const (
GivenByWarderSpell GivenByType = 11 GivenByWarderSpell GivenByType = 11
) )
// Spell component types for LUA data // Spell component types for script data
const ( const (
SpellLUADataTypeInt = 0 SpellScriptDataTypeInt = 0
SpellLUADataTypeFloat = 1 SpellScriptDataTypeFloat = 1
SpellLUADataTypeBool = 2 SpellScriptDataTypeBool = 2
SpellLUADataTypeString = 3 SpellScriptDataTypeString = 3
) )

View File

@ -0,0 +1,180 @@
package spells
import "fmt"
// Example spell handlers to demonstrate native Go spell scripting
// HealSpellHandler handles healing spells
type HealSpellHandler struct {
healAmount float32
scalingFactor float32
targetRequired bool
}
// NewHealSpellHandler creates a new heal spell handler
func NewHealSpellHandler(healAmount, scalingFactor float32, targetRequired bool) *HealSpellHandler {
return &HealSpellHandler{
healAmount: healAmount,
scalingFactor: scalingFactor,
targetRequired: targetRequired,
}
}
// Execute runs the heal spell logic
func (h *HealSpellHandler) Execute(caster SpellCaster, target SpellTarget, spell *Spell, data *SpellScriptData) error {
// Example healing logic
if h.targetRequired && target == nil {
return fmt.Errorf("heal spell requires a target")
}
// Calculate heal amount based on caster level and data values
healAmount := h.healAmount + (float32(caster.GetLevel()) * h.scalingFactor)
if data.FloatValue > 0 {
healAmount += data.FloatValue
}
// TODO: Apply healing to target when entity system is integrated
// target.AddHP(int32(healAmount))
return nil
}
// GetType returns the handler type
func (h *HealSpellHandler) GetType() string {
return "heal"
}
// Validate checks if the script data is valid
func (h *HealSpellHandler) Validate(data *SpellScriptData) error {
if data.Type != SpellScriptDataTypeFloat {
return fmt.Errorf("heal handler expects float data type")
}
return nil
}
// DamageSpellHandler handles damage spells
type DamageSpellHandler struct {
damageAmount float32
damageType int32
requiresTarget bool
}
// NewDamageSpellHandler creates a new damage spell handler
func NewDamageSpellHandler(damageAmount float32, damageType int32, requiresTarget bool) *DamageSpellHandler {
return &DamageSpellHandler{
damageAmount: damageAmount,
damageType: damageType,
requiresTarget: requiresTarget,
}
}
// Execute runs the damage spell logic
func (d *DamageSpellHandler) Execute(caster SpellCaster, target SpellTarget, spell *Spell, data *SpellScriptData) error {
if d.requiresTarget && target == nil {
return fmt.Errorf("damage spell requires a target")
}
// Calculate damage based on spell data
damage := d.damageAmount
if data.IntValue > 0 {
damage += float32(data.IntValue)
}
// TODO: Apply damage to target when combat system is integrated
// combat.InflictDamage(caster, target, damage, d.damageType)
return nil
}
// GetType returns the handler type
func (d *DamageSpellHandler) GetType() string {
return "damage"
}
// Validate checks if the script data is valid
func (d *DamageSpellHandler) Validate(data *SpellScriptData) error {
if data.Type != SpellScriptDataTypeInt {
return fmt.Errorf("damage handler expects int data type")
}
return nil
}
// BuffSpellHandler handles buff spells
type BuffSpellHandler struct {
statType int16
bonusValue float32
duration int32
}
// NewBuffSpellHandler creates a new buff spell handler
func NewBuffSpellHandler(statType int16, bonusValue float32, duration int32) *BuffSpellHandler {
return &BuffSpellHandler{
statType: statType,
bonusValue: bonusValue,
duration: duration,
}
}
// Execute runs the buff spell logic
func (b *BuffSpellHandler) Execute(caster SpellCaster, target SpellTarget, spell *Spell, data *SpellScriptData) error {
// Apply buff to target
if target == nil {
target = caster.(SpellTarget) // Self-buff
}
// TODO: Add buff to target when buff system is integrated
// target.AddBuff(spell.GetSpellID(), b.statType, b.bonusValue, b.duration)
return nil
}
// GetType returns the handler type
func (b *BuffSpellHandler) GetType() string {
return "buff"
}
// Validate checks if the script data is valid
func (b *BuffSpellHandler) Validate(data *SpellScriptData) error {
// Buff handlers can accept various data types
return nil
}
// SpellHandlerRegistry manages spell handlers
type SpellHandlerRegistry struct {
handlers map[string]SpellScriptHandler
}
// NewSpellHandlerRegistry creates a new handler registry
func NewSpellHandlerRegistry() *SpellHandlerRegistry {
return &SpellHandlerRegistry{
handlers: make(map[string]SpellScriptHandler),
}
}
// RegisterHandler registers a spell handler
func (shr *SpellHandlerRegistry) RegisterHandler(name string, handler SpellScriptHandler) {
shr.handlers[name] = handler
}
// GetHandler retrieves a spell handler by name
func (shr *SpellHandlerRegistry) GetHandler(name string) SpellScriptHandler {
return shr.handlers[name]
}
// InitializeDefaultHandlers sets up common spell handlers
func (shr *SpellHandlerRegistry) InitializeDefaultHandlers() {
// Register common heal handlers
shr.RegisterHandler("minor_heal", NewHealSpellHandler(50.0, 2.0, true))
shr.RegisterHandler("major_heal", NewHealSpellHandler(200.0, 5.0, true))
shr.RegisterHandler("group_heal", NewHealSpellHandler(75.0, 3.0, false))
// Register common damage handlers
shr.RegisterHandler("fire_damage", NewDamageSpellHandler(30.0, 3, true)) // Heat damage
shr.RegisterHandler("cold_damage", NewDamageSpellHandler(25.0, 4, true)) // Cold damage
shr.RegisterHandler("magic_damage", NewDamageSpellHandler(40.0, 5, true)) // Magic damage
// Register common buff handlers
shr.RegisterHandler("strength_buff", NewBuffSpellHandler(ModifyStr, 10.0, 600000)) // 10 minute duration
shr.RegisterHandler("intelligence_buff", NewBuffSpellHandler(ModifyInt, 8.0, 600000))
shr.RegisterHandler("speed_buff", NewBuffSpellHandler(ModifySpeed, 15.0, 300000)) // 5 minute duration
}

View File

@ -14,7 +14,7 @@ type Spell struct {
// Spell progression and requirements // Spell progression and requirements
levels []*LevelArray // Level requirements by class levels []*LevelArray // Level requirements by class
effects []*SpellDisplayEffect // Display effects for tooltips effects []*SpellDisplayEffect // Display effects for tooltips
luaData []*LUAData // LUA script data scriptData []*SpellScriptData // Native Go script data
// Computed properties (cached for performance) // Computed properties (cached for performance)
healSpell bool // Cached: is this a healing spell healSpell bool // Cached: is this a healing spell
@ -37,7 +37,7 @@ func NewSpell() *Spell {
data: NewSpellData(), data: NewSpellData(),
levels: make([]*LevelArray, 0), levels: make([]*LevelArray, 0),
effects: make([]*SpellDisplayEffect, 0), effects: make([]*SpellDisplayEffect, 0),
luaData: make([]*LUAData, 0), scriptData: make([]*SpellScriptData, 0),
healSpell: false, healSpell: false,
buffSpell: false, buffSpell: false,
damageSpell: false, damageSpell: false,
@ -69,7 +69,7 @@ func NewSpellCopy(hostSpell *Spell, uniqueSpell bool) *Spell {
data: hostSpell.data.Clone(), data: hostSpell.data.Clone(),
levels: make([]*LevelArray, 0), levels: make([]*LevelArray, 0),
effects: make([]*SpellDisplayEffect, 0), effects: make([]*SpellDisplayEffect, 0),
luaData: make([]*LUAData, 0), scriptData: make([]*SpellScriptData, 0),
healSpell: hostSpell.healSpell, healSpell: hostSpell.healSpell,
buffSpell: hostSpell.buffSpell, buffSpell: hostSpell.buffSpell,
damageSpell: hostSpell.damageSpell, damageSpell: hostSpell.damageSpell,
@ -101,21 +101,22 @@ func NewSpellCopy(hostSpell *Spell, uniqueSpell bool) *Spell {
s.effects = append(s.effects, newEffect) s.effects = append(s.effects, newEffect)
} }
// Copy LUA data // Copy script data
for _, lua := range hostSpell.luaData { for _, script := range hostSpell.scriptData {
newLua := &LUAData{ newScript := &SpellScriptData{
Type: lua.Type, Type: script.Type,
IntValue: lua.IntValue, IntValue: script.IntValue,
BoolValue: lua.BoolValue, BoolValue: script.BoolValue,
FloatValue: lua.FloatValue, FloatValue: script.FloatValue,
StringValue: lua.StringValue, StringValue: script.StringValue,
StringValue2: lua.StringValue2, StringValue2: script.StringValue2,
IntValue2: lua.IntValue2, IntValue2: script.IntValue2,
FloatValue2: lua.FloatValue2, FloatValue2: script.FloatValue2,
StringHelper: lua.StringHelper, Helper: script.Helper,
NeedsDBSave: lua.NeedsDBSave, Handler: script.Handler,
NeedsDBSave: script.NeedsDBSave,
} }
s.luaData = append(s.luaData, newLua) s.scriptData = append(s.scriptData, newScript)
} }
// If unique spell, generate new ID // If unique spell, generate new ID
@ -212,12 +213,12 @@ func (s *Spell) AddSpellEffect(percentage, subbullet int8, description string) {
s.effects = append(s.effects, effect) s.effects = append(s.effects, effect)
} }
// AddSpellLuaData adds LUA data to the spell // AddSpellScriptData adds script data to the spell
func (s *Spell) AddSpellLuaData(dataType int8, intValue, intValue2 int32, floatValue, floatValue2 float32, boolValue bool, stringValue, stringValue2, helper string) { func (s *Spell) AddSpellScriptData(dataType int8, intValue, intValue2 int32, floatValue, floatValue2 float32, boolValue bool, stringValue, stringValue2, helper string, handler SpellScriptHandler) {
s.mutex.Lock() s.mutex.Lock()
defer s.mutex.Unlock() defer s.mutex.Unlock()
luaData := &LUAData{ scriptData := &SpellScriptData{
Type: dataType, Type: dataType,
IntValue: intValue, IntValue: intValue,
BoolValue: boolValue, BoolValue: boolValue,
@ -226,33 +227,34 @@ func (s *Spell) AddSpellLuaData(dataType int8, intValue, intValue2 int32, floatV
StringValue2: stringValue2, StringValue2: stringValue2,
IntValue2: intValue2, IntValue2: intValue2,
FloatValue2: floatValue2, FloatValue2: floatValue2,
StringHelper: helper, Helper: helper,
Handler: handler,
NeedsDBSave: true, NeedsDBSave: true,
} }
s.luaData = append(s.luaData, luaData) s.scriptData = append(s.scriptData, scriptData)
} }
// Convenience methods for adding specific LUA data types // Convenience methods for adding specific script data types
// AddSpellLuaDataInt adds integer LUA data // AddSpellScriptDataInt adds integer script data
func (s *Spell) AddSpellLuaDataInt(value, value2 int32, helper string) { func (s *Spell) AddSpellScriptDataInt(value, value2 int32, helper string, handler SpellScriptHandler) {
s.AddSpellLuaData(SpellLUADataTypeInt, value, value2, 0.0, 0.0, false, "", "", helper) s.AddSpellScriptData(SpellScriptDataTypeInt, value, value2, 0.0, 0.0, false, "", "", helper, handler)
} }
// AddSpellLuaDataFloat adds float LUA data // AddSpellScriptDataFloat adds float script data
func (s *Spell) AddSpellLuaDataFloat(value, value2 float32, helper string) { func (s *Spell) AddSpellScriptDataFloat(value, value2 float32, helper string, handler SpellScriptHandler) {
s.AddSpellLuaData(SpellLUADataTypeFloat, 0, 0, value, value2, false, "", "", helper) s.AddSpellScriptData(SpellScriptDataTypeFloat, 0, 0, value, value2, false, "", "", helper, handler)
} }
// AddSpellLuaDataBool adds boolean LUA data // AddSpellScriptDataBool adds boolean script data
func (s *Spell) AddSpellLuaDataBool(value bool, helper string) { func (s *Spell) AddSpellScriptDataBool(value bool, helper string, handler SpellScriptHandler) {
s.AddSpellLuaData(SpellLUADataTypeBool, 0, 0, 0.0, 0.0, value, "", "", helper) s.AddSpellScriptData(SpellScriptDataTypeBool, 0, 0, 0.0, 0.0, value, "", "", helper, handler)
} }
// AddSpellLuaDataString adds string LUA data // AddSpellScriptDataString adds string script data
func (s *Spell) AddSpellLuaDataString(value, value2, helper string) { func (s *Spell) AddSpellScriptDataString(value, value2, helper string, handler SpellScriptHandler) {
s.AddSpellLuaData(SpellLUADataTypeString, 0, 0, 0.0, 0.0, false, value, value2, helper) s.AddSpellScriptData(SpellScriptDataTypeString, 0, 0, 0.0, 0.0, false, value, value2, helper, handler)
} }
// GetSpellLevels returns the spell level requirements // GetSpellLevels returns the spell level requirements
@ -288,15 +290,15 @@ func (s *Spell) GetSpellEffectSafe(index int) *SpellDisplayEffect {
return s.effects[index] return s.effects[index]
} }
// GetLUAData returns the spell's LUA data // GetScriptData returns the spell's script data
func (s *Spell) GetLUAData() []*LUAData { func (s *Spell) GetScriptData() []*SpellScriptData {
s.mutex.RLock() s.mutex.RLock()
defer s.mutex.RUnlock() defer s.mutex.RUnlock()
// Return a copy to prevent external modification // Return a copy to prevent external modification
luaData := make([]*LUAData, len(s.luaData)) scriptData := make([]*SpellScriptData, len(s.scriptData))
copy(luaData, s.luaData) copy(scriptData, s.scriptData)
return luaData return scriptData
} }
// Spell classification methods (cached for performance) // Spell classification methods (cached for performance)
@ -441,9 +443,9 @@ func (s *Spell) String() string {
s.GetSpellID(), s.GetName(), s.GetSpellTier()) s.GetSpellID(), s.GetName(), s.GetSpellTier())
} }
// LuaSpell represents an active spell instance with runtime state // ActiveSpell represents an active spell instance with runtime state
// This is converted from the C++ LuaSpell class // This replaces the C++ LuaSpell class functionality
type LuaSpell struct { type ActiveSpell struct {
// Core identification // Core identification
Spell *Spell // Reference to the spell definition Spell *Spell // Reference to the spell definition
CasterID int32 // ID of the entity casting this spell CasterID int32 // ID of the entity casting this spell
@ -482,9 +484,9 @@ type SpellTimer struct {
SetAtTrigger int64 // Time when timer was set/triggered SetAtTrigger int64 // Time when timer was set/triggered
} }
// NewLuaSpell creates a new LuaSpell instance // NewActiveSpell creates a new ActiveSpell instance
func NewLuaSpell(spell *Spell, casterID int32) *LuaSpell { func NewActiveSpell(spell *Spell, casterID int32) *ActiveSpell {
return &LuaSpell{ return &ActiveSpell{
Spell: spell, Spell: spell,
CasterID: casterID, CasterID: casterID,
InitialTarget: 0, InitialTarget: 0,
@ -506,38 +508,38 @@ func NewLuaSpell(spell *Spell, casterID int32) *LuaSpell {
} }
// GetTargets returns a copy of the target list // GetTargets returns a copy of the target list
func (ls *LuaSpell) GetTargets() []int32 { func (as *ActiveSpell) GetTargets() []int32 {
ls.mutex.RLock() as.mutex.RLock()
defer ls.mutex.RUnlock() defer as.mutex.RUnlock()
targets := make([]int32, len(ls.Targets)) targets := make([]int32, len(as.Targets))
copy(targets, ls.Targets) copy(targets, as.Targets)
return targets return targets
} }
// AddTarget adds a target to the spell // AddTarget adds a target to the spell
func (ls *LuaSpell) AddTarget(targetID int32) { func (as *ActiveSpell) AddTarget(targetID int32) {
ls.mutex.Lock() as.mutex.Lock()
defer ls.mutex.Unlock() defer as.mutex.Unlock()
// Check if target already exists // Check if target already exists
for _, id := range ls.Targets { for _, id := range as.Targets {
if id == targetID { if id == targetID {
return return
} }
} }
ls.Targets = append(ls.Targets, targetID) as.Targets = append(as.Targets, targetID)
} }
// RemoveTarget removes a target from the spell // RemoveTarget removes a target from the spell
func (ls *LuaSpell) RemoveTarget(targetID int32) bool { func (as *ActiveSpell) RemoveTarget(targetID int32) bool {
ls.mutex.Lock() as.mutex.Lock()
defer ls.mutex.Unlock() defer as.mutex.Unlock()
for i, id := range ls.Targets { for i, id := range as.Targets {
if id == targetID { if id == targetID {
ls.Targets = append(ls.Targets[:i], ls.Targets[i+1:]...) as.Targets = append(as.Targets[:i], as.Targets[i+1:]...)
return true return true
} }
} }
@ -546,11 +548,11 @@ func (ls *LuaSpell) RemoveTarget(targetID int32) bool {
} }
// HasTarget checks if the spell targets a specific entity // HasTarget checks if the spell targets a specific entity
func (ls *LuaSpell) HasTarget(targetID int32) bool { func (as *ActiveSpell) HasTarget(targetID int32) bool {
ls.mutex.RLock() as.mutex.RLock()
defer ls.mutex.RUnlock() defer as.mutex.RUnlock()
for _, id := range ls.Targets { for _, id := range as.Targets {
if id == targetID { if id == targetID {
return true return true
} }
@ -560,96 +562,96 @@ func (ls *LuaSpell) HasTarget(targetID int32) bool {
} }
// GetTargetCount returns the number of targets // GetTargetCount returns the number of targets
func (ls *LuaSpell) GetTargetCount() int { func (as *ActiveSpell) GetTargetCount() int {
ls.mutex.RLock() as.mutex.RLock()
defer ls.mutex.RUnlock() defer as.mutex.RUnlock()
return len(ls.Targets) return len(as.Targets)
} }
// ClearTargets removes all targets from the spell // ClearTargets removes all targets from the spell
func (ls *LuaSpell) ClearTargets() { func (as *ActiveSpell) ClearTargets() {
ls.mutex.Lock() as.mutex.Lock()
defer ls.mutex.Unlock() defer as.mutex.Unlock()
ls.Targets = ls.Targets[:0] as.Targets = as.Targets[:0]
} }
// SetCustomFunction sets a custom LUA function for this spell instance // SetCustomFunction sets a custom LUA function for this spell instance
func (ls *LuaSpell) SetCustomFunction(functionName string) { func (as *ActiveSpell) SetCustomFunction(functionName string) {
ls.mutex.Lock() as.mutex.Lock()
defer ls.mutex.Unlock() defer as.mutex.Unlock()
ls.CustomFunction = functionName as.CustomFunction = functionName
} }
// GetCustomFunction returns the custom LUA function name // GetCustomFunction returns the custom LUA function name
func (ls *LuaSpell) GetCustomFunction() string { func (as *ActiveSpell) GetCustomFunction() string {
ls.mutex.RLock() as.mutex.RLock()
defer ls.mutex.RUnlock() defer as.mutex.RUnlock()
return ls.CustomFunction return as.CustomFunction
} }
// MarkForDeletion marks the spell for removal // MarkForDeletion marks the spell for removal
func (ls *LuaSpell) MarkForDeletion() { func (as *ActiveSpell) MarkForDeletion() {
ls.mutex.Lock() as.mutex.Lock()
defer ls.mutex.Unlock() defer as.mutex.Unlock()
ls.Deleted = true as.Deleted = true
} }
// IsDeleted returns whether the spell is marked for deletion // IsDeleted returns whether the spell is marked for deletion
func (ls *LuaSpell) IsDeleted() bool { func (as *ActiveSpell) IsDeleted() bool {
ls.mutex.RLock() as.mutex.RLock()
defer ls.mutex.RUnlock() defer as.mutex.RUnlock()
return ls.Deleted return as.Deleted
} }
// SetInterrupted marks the spell as interrupted // SetInterrupted marks the spell as interrupted
func (ls *LuaSpell) SetInterrupted(interrupted bool) { func (as *ActiveSpell) SetInterrupted(interrupted bool) {
ls.mutex.Lock() as.mutex.Lock()
defer ls.mutex.Unlock() defer as.mutex.Unlock()
ls.Interrupted = interrupted as.Interrupted = interrupted
} }
// IsInterrupted returns whether the spell was interrupted // IsInterrupted returns whether the spell was interrupted
func (ls *LuaSpell) IsInterrupted() bool { func (as *ActiveSpell) IsInterrupted() bool {
ls.mutex.RLock() as.mutex.RLock()
defer ls.mutex.RUnlock() defer as.mutex.RUnlock()
return ls.Interrupted return as.Interrupted
} }
// SetResurrectValues sets HP and power restoration values for resurrect spells // SetResurrectValues sets HP and power restoration values for resurrect spells
func (ls *LuaSpell) SetResurrectValues(hp, power float32) { func (as *ActiveSpell) SetResurrectValues(hp, power float32) {
ls.mutex.Lock() as.mutex.Lock()
defer ls.mutex.Unlock() defer as.mutex.Unlock()
ls.ResurrectHP = hp as.ResurrectHP = hp
ls.ResurrectPower = power as.ResurrectPower = power
} }
// GetResurrectValues returns HP and power restoration values // GetResurrectValues returns HP and power restoration values
func (ls *LuaSpell) GetResurrectValues() (float32, float32) { func (as *ActiveSpell) GetResurrectValues() (float32, float32) {
ls.mutex.RLock() as.mutex.RLock()
defer ls.mutex.RUnlock() defer as.mutex.RUnlock()
return ls.ResurrectHP, ls.ResurrectPower return as.ResurrectHP, as.ResurrectPower
} }
// String returns a string representation of the LuaSpell // String returns a string representation of the ActiveSpell
func (ls *LuaSpell) String() string { func (as *ActiveSpell) String() string {
ls.mutex.RLock() as.mutex.RLock()
defer ls.mutex.RUnlock() defer as.mutex.RUnlock()
spellName := "Unknown" spellName := "Unknown"
if ls.Spell != nil { if as.Spell != nil {
spellName = ls.Spell.GetName() spellName = as.Spell.GetName()
} }
return fmt.Sprintf("LuaSpell[%s, Caster=%d, Targets=%d]", return fmt.Sprintf("ActiveSpell[%s, Caster=%d, Targets=%d]",
spellName, ls.CasterID, len(ls.Targets)) spellName, as.CasterID, len(as.Targets))
} }

View File

@ -20,8 +20,8 @@ type SpellDisplayEffect struct {
NeedsDBSave bool // Whether this needs database saving NeedsDBSave bool // Whether this needs database saving
} }
// LUAData represents Lua script data for spells // SpellScriptData represents native Go script data for spells
type LUAData struct { type SpellScriptData struct {
Type int8 // Data type (int, float, bool, string) Type int8 // Data type (int, float, bool, string)
IntValue int32 // Integer value IntValue int32 // Integer value
BoolValue bool // Boolean value BoolValue bool // Boolean value
@ -30,10 +30,40 @@ type LUAData struct {
StringValue2 string // Second string value StringValue2 string // Second string value
IntValue2 int32 // Second integer value IntValue2 int32 // Second integer value
FloatValue2 float32 // Second float value FloatValue2 float32 // Second float value
StringHelper string // Helper string for identification Helper string // Helper string for identification
Handler SpellScriptHandler // Native Go handler function
NeedsDBSave bool // Whether this needs database saving NeedsDBSave bool // Whether this needs database saving
} }
// SpellScriptHandler defines the interface for native spell script handlers
type SpellScriptHandler interface {
// Execute runs the spell script logic with the given parameters
Execute(caster SpellCaster, target SpellTarget, spell *Spell, data *SpellScriptData) error
// GetType returns the type of script handler
GetType() string
// Validate checks if the script data is valid for this handler
Validate(data *SpellScriptData) error
}
// SpellCaster interface for entities that can cast spells
type SpellCaster interface {
GetID() int32
GetName() string
GetLevel() int16
GetPosition() (float32, float32, float32)
CanCastSpell(spell *Spell) bool
}
// SpellTarget interface for entities that can be targeted by spells
type SpellTarget interface {
GetID() int32
GetName() string
GetPosition() (float32, float32, float32)
CanReceiveSpell(spell *Spell, caster SpellCaster) bool
}
// SpellData contains all core spell information // SpellData contains all core spell information
// This is the main spell data structure converted from C++ SpellData // This is the main spell data structure converted from C++ SpellData
type SpellData struct { type SpellData struct {

View File

@ -15,8 +15,8 @@ type BonusValues struct {
ClassReq int64 // Required class bitmask ClassReq int64 // Required class bitmask
RaceReq []int16 // Required race IDs RaceReq []int16 // Required race IDs
FactionReq []int16 // Required faction IDs FactionReq []int16 // Required faction IDs
// TODO: Add LuaSpell reference when spell system is implemented // Associated active spell instance
// LuaSpell *LuaSpell // Associated Lua spell ActiveSpell *ActiveSpell // Associated active spell
} }
// NewBonusValues creates a new bonus value entry // NewBonusValues creates a new bonus value entry
@ -85,8 +85,8 @@ type MaintainedEffects struct {
Tier int8 // Spell tier Tier int8 // Spell tier
TotalTime float32 // Total duration of effect TotalTime float32 // Total duration of effect
ExpireTimestamp int32 // When the effect expires ExpireTimestamp int32 // When the effect expires
// TODO: Add LuaSpell reference when spell system is implemented // Associated active spell instance
// Spell *LuaSpell // Associated Lua spell Spell *ActiveSpell // Associated active spell
} }
// NewMaintainedEffects creates a new maintained effect // NewMaintainedEffects creates a new maintained effect
@ -158,8 +158,8 @@ type SpellEffects struct {
Icon int16 // Icon to display Icon int16 // Icon to display
IconBackdrop int16 // Icon backdrop IconBackdrop int16 // Icon backdrop
Tier int8 // Spell tier Tier int8 // Spell tier
// TODO: Add LuaSpell reference when spell system is implemented // Associated active spell instance
// Spell *LuaSpell // Associated Lua spell Spell *ActiveSpell // Associated active spell
} }
// NewSpellEffects creates a new spell effect // NewSpellEffects creates a new spell effect
@ -213,8 +213,8 @@ type DetrimentalEffects struct {
Incurable bool // Cannot be cured Incurable bool // Cannot be cured
ControlEffect int8 // Control effect type ControlEffect int8 // Control effect type
TotalTime float32 // Total duration TotalTime float32 // Total duration
// TODO: Add LuaSpell reference when spell system is implemented // Associated active spell instance
// Spell *LuaSpell // Associated Lua spell Spell *ActiveSpell // Associated active spell
} }
// NewDetrimentalEffects creates a new detrimental effect // NewDetrimentalEffects creates a new detrimental effect

View File

@ -8,8 +8,8 @@ import (
// SpellScriptTimer represents a timer for spell script execution // SpellScriptTimer represents a timer for spell script execution
type SpellScriptTimer struct { type SpellScriptTimer struct {
// TODO: Add LuaSpell reference when implemented // TODO: Add ActiveSpell reference when implemented
// Spell *LuaSpell // The spell being timed // Spell *ActiveSpell // The spell being timed
SpellID int32 // Spell ID for identification SpellID int32 // Spell ID for identification
CustomFunction string // Custom function to call CustomFunction string // Custom function to call
Time int32 // Timer duration Time int32 // Timer duration
@ -461,8 +461,8 @@ func (sm *SpellManager) CastSpell(casterID, targetID, spellID int32) error {
return fmt.Errorf("spell %d not found", spellID) return fmt.Errorf("spell %d not found", spellID)
} }
// Create LuaSpell instance // Create ActiveSpell instance
luaSpell := NewLuaSpell(spell, casterID) luaSpell := NewActiveSpell(spell, casterID)
luaSpell.InitialTarget = targetID luaSpell.InitialTarget = targetID
// Check resources // Check resources
@ -529,8 +529,8 @@ func (sm *SpellManager) CanCastSpell(casterID, targetID, spellID int32) (bool, s
return false, fmt.Sprintf("Spell on cooldown for %d seconds", int(remaining.Seconds())) return false, fmt.Sprintf("Spell on cooldown for %d seconds", int(remaining.Seconds()))
} }
// Create temporary LuaSpell for resource checks // Create temporary ActiveSpell for resource checks
luaSpell := NewLuaSpell(spell, casterID) luaSpell := NewActiveSpell(spell, casterID)
luaSpell.InitialTarget = targetID luaSpell.InitialTarget = targetID
// Check resources // Check resources

View File

@ -81,7 +81,7 @@ type HeroicOpportunity struct {
// SpellProcess manages all spell casting for a zone // SpellProcess manages all spell casting for a zone
type SpellProcess struct { type SpellProcess struct {
// Core collections // Core collections
activeSpells map[int32]*LuaSpell // Active spells by spell instance ID activeSpells map[int32]*ActiveSpell // Active spells by spell instance ID
castTimers []*CastTimer // Active cast timers castTimers []*CastTimer // Active cast timers
recastTimers []*RecastTimer // Active recast timers recastTimers []*RecastTimer // Active recast timers
interruptQueue []*InterruptStruct // Queued interruptions interruptQueue []*InterruptStruct // Queued interruptions
@ -110,7 +110,7 @@ type SpellProcess struct {
// NewSpellProcess creates a new spell process instance // NewSpellProcess creates a new spell process instance
func NewSpellProcess() *SpellProcess { func NewSpellProcess() *SpellProcess {
return &SpellProcess{ return &SpellProcess{
activeSpells: make(map[int32]*LuaSpell), activeSpells: make(map[int32]*ActiveSpell),
castTimers: make([]*CastTimer, 0), castTimers: make([]*CastTimer, 0),
recastTimers: make([]*RecastTimer, 0), recastTimers: make([]*RecastTimer, 0),
interruptQueue: make([]*InterruptStruct, 0), interruptQueue: make([]*InterruptStruct, 0),
@ -543,13 +543,13 @@ func (sp *SpellProcess) RemoveAllSpells(reloadSpells bool) {
// Clear all spell collections // Clear all spell collections
if reloadSpells { if reloadSpells {
// Keep some data for reload // Keep some data for reload
sp.activeSpells = make(map[int32]*LuaSpell) sp.activeSpells = make(map[int32]*ActiveSpell)
} else { } else {
// Complete cleanup // Complete cleanup
for spellID := range sp.activeSpells { for spellID := range sp.activeSpells {
sp.deleteCasterSpell(spellID, "shutdown") sp.deleteCasterSpell(spellID, "shutdown")
} }
sp.activeSpells = make(map[int32]*LuaSpell) sp.activeSpells = make(map[int32]*ActiveSpell)
} }
sp.castTimers = make([]*CastTimer, 0) sp.castTimers = make([]*CastTimer, 0)

View File

@ -29,7 +29,7 @@ func NewSpellResourceChecker() *SpellResourceChecker {
// CheckPower verifies if the caster has enough power to cast the spell // CheckPower verifies if the caster has enough power to cast the spell
// Converted from C++ SpellProcess::CheckPower // Converted from C++ SpellProcess::CheckPower
func (src *SpellResourceChecker) CheckPower(luaSpell *LuaSpell, customPowerReq float32) *ResourceCheckResult { func (src *SpellResourceChecker) CheckPower(luaSpell *ActiveSpell, customPowerReq float32) *ResourceCheckResult {
if luaSpell == nil || luaSpell.Spell == nil { if luaSpell == nil || luaSpell.Spell == nil {
return &ResourceCheckResult{ return &ResourceCheckResult{
HasSufficient: false, HasSufficient: false,
@ -66,7 +66,7 @@ func (src *SpellResourceChecker) CheckPower(luaSpell *LuaSpell, customPowerReq f
// TakePower consumes power for spell casting // TakePower consumes power for spell casting
// Converted from C++ SpellProcess::TakePower // Converted from C++ SpellProcess::TakePower
func (src *SpellResourceChecker) TakePower(luaSpell *LuaSpell, customPowerReq float32) bool { func (src *SpellResourceChecker) TakePower(luaSpell *ActiveSpell, customPowerReq float32) bool {
result := src.CheckPower(luaSpell, customPowerReq) result := src.CheckPower(luaSpell, customPowerReq)
if !result.HasSufficient { if !result.HasSufficient {
return false return false
@ -82,7 +82,7 @@ func (src *SpellResourceChecker) TakePower(luaSpell *LuaSpell, customPowerReq fl
// CheckHP verifies if the caster has enough health to cast the spell // CheckHP verifies if the caster has enough health to cast the spell
// Converted from C++ SpellProcess::CheckHP // Converted from C++ SpellProcess::CheckHP
func (src *SpellResourceChecker) CheckHP(luaSpell *LuaSpell, customHPReq float32) *ResourceCheckResult { func (src *SpellResourceChecker) CheckHP(luaSpell *ActiveSpell, customHPReq float32) *ResourceCheckResult {
if luaSpell == nil || luaSpell.Spell == nil { if luaSpell == nil || luaSpell.Spell == nil {
return &ResourceCheckResult{ return &ResourceCheckResult{
HasSufficient: false, HasSufficient: false,
@ -119,7 +119,7 @@ func (src *SpellResourceChecker) CheckHP(luaSpell *LuaSpell, customHPReq float32
// TakeHP consumes health for spell casting // TakeHP consumes health for spell casting
// Converted from C++ SpellProcess::TakeHP // Converted from C++ SpellProcess::TakeHP
func (src *SpellResourceChecker) TakeHP(luaSpell *LuaSpell, customHPReq float32) bool { func (src *SpellResourceChecker) TakeHP(luaSpell *ActiveSpell, customHPReq float32) bool {
result := src.CheckHP(luaSpell, customHPReq) result := src.CheckHP(luaSpell, customHPReq)
if !result.HasSufficient { if !result.HasSufficient {
return false return false
@ -135,7 +135,7 @@ func (src *SpellResourceChecker) TakeHP(luaSpell *LuaSpell, customHPReq float32)
// CheckConcentration verifies if the caster has enough concentration to cast the spell // CheckConcentration verifies if the caster has enough concentration to cast the spell
// Converted from C++ SpellProcess::CheckConcentration // Converted from C++ SpellProcess::CheckConcentration
func (src *SpellResourceChecker) CheckConcentration(luaSpell *LuaSpell) *ResourceCheckResult { func (src *SpellResourceChecker) CheckConcentration(luaSpell *ActiveSpell) *ResourceCheckResult {
if luaSpell == nil || luaSpell.Spell == nil { if luaSpell == nil || luaSpell.Spell == nil {
return &ResourceCheckResult{ return &ResourceCheckResult{
HasSufficient: false, HasSufficient: false,
@ -180,7 +180,7 @@ func (src *SpellResourceChecker) CheckConcentration(luaSpell *LuaSpell) *Resourc
// AddConcentration adds concentration for maintained spells // AddConcentration adds concentration for maintained spells
// Converted from C++ SpellProcess::AddConcentration // Converted from C++ SpellProcess::AddConcentration
func (src *SpellResourceChecker) AddConcentration(luaSpell *LuaSpell) bool { func (src *SpellResourceChecker) AddConcentration(luaSpell *ActiveSpell) bool {
result := src.CheckConcentration(luaSpell) result := src.CheckConcentration(luaSpell)
if !result.HasSufficient { if !result.HasSufficient {
return false return false
@ -197,7 +197,7 @@ func (src *SpellResourceChecker) AddConcentration(luaSpell *LuaSpell) bool {
// CheckSavagery verifies if the caster has enough savagery to cast the spell // CheckSavagery verifies if the caster has enough savagery to cast the spell
// Converted from C++ SpellProcess::CheckSavagery // Converted from C++ SpellProcess::CheckSavagery
func (src *SpellResourceChecker) CheckSavagery(luaSpell *LuaSpell) *ResourceCheckResult { func (src *SpellResourceChecker) CheckSavagery(luaSpell *ActiveSpell) *ResourceCheckResult {
if luaSpell == nil || luaSpell.Spell == nil { if luaSpell == nil || luaSpell.Spell == nil {
return &ResourceCheckResult{ return &ResourceCheckResult{
HasSufficient: false, HasSufficient: false,
@ -231,7 +231,7 @@ func (src *SpellResourceChecker) CheckSavagery(luaSpell *LuaSpell) *ResourceChec
// TakeSavagery consumes savagery for spell casting // TakeSavagery consumes savagery for spell casting
// Converted from C++ SpellProcess::TakeSavagery // Converted from C++ SpellProcess::TakeSavagery
func (src *SpellResourceChecker) TakeSavagery(luaSpell *LuaSpell) bool { func (src *SpellResourceChecker) TakeSavagery(luaSpell *ActiveSpell) bool {
result := src.CheckSavagery(luaSpell) result := src.CheckSavagery(luaSpell)
if !result.HasSufficient { if !result.HasSufficient {
return false return false
@ -247,7 +247,7 @@ func (src *SpellResourceChecker) TakeSavagery(luaSpell *LuaSpell) bool {
// CheckDissonance verifies if the caster has enough dissonance to cast the spell // CheckDissonance verifies if the caster has enough dissonance to cast the spell
// Converted from C++ SpellProcess::CheckDissonance // Converted from C++ SpellProcess::CheckDissonance
func (src *SpellResourceChecker) CheckDissonance(luaSpell *LuaSpell) *ResourceCheckResult { func (src *SpellResourceChecker) CheckDissonance(luaSpell *ActiveSpell) *ResourceCheckResult {
if luaSpell == nil || luaSpell.Spell == nil { if luaSpell == nil || luaSpell.Spell == nil {
return &ResourceCheckResult{ return &ResourceCheckResult{
HasSufficient: false, HasSufficient: false,
@ -281,7 +281,7 @@ func (src *SpellResourceChecker) CheckDissonance(luaSpell *LuaSpell) *ResourceCh
// AddDissonance adds dissonance for spell casting // AddDissonance adds dissonance for spell casting
// Converted from C++ SpellProcess::AddDissonance // Converted from C++ SpellProcess::AddDissonance
func (src *SpellResourceChecker) AddDissonance(luaSpell *LuaSpell) bool { func (src *SpellResourceChecker) AddDissonance(luaSpell *ActiveSpell) bool {
result := src.CheckDissonance(luaSpell) result := src.CheckDissonance(luaSpell)
if !result.HasSufficient { if !result.HasSufficient {
return false return false
@ -296,7 +296,7 @@ func (src *SpellResourceChecker) AddDissonance(luaSpell *LuaSpell) bool {
} }
// CheckAllResources performs a comprehensive resource check for a spell // CheckAllResources performs a comprehensive resource check for a spell
func (src *SpellResourceChecker) CheckAllResources(luaSpell *LuaSpell, customPowerReq, customHPReq float32) []ResourceCheckResult { func (src *SpellResourceChecker) CheckAllResources(luaSpell *ActiveSpell, customPowerReq, customHPReq float32) []ResourceCheckResult {
results := make([]ResourceCheckResult, 0) results := make([]ResourceCheckResult, 0)
// Check power // Check power
@ -333,7 +333,7 @@ func (src *SpellResourceChecker) CheckAllResources(luaSpell *LuaSpell, customPow
} }
// ConsumeAllResources attempts to consume all required resources for a spell // ConsumeAllResources attempts to consume all required resources for a spell
func (src *SpellResourceChecker) ConsumeAllResources(luaSpell *LuaSpell, customPowerReq, customHPReq float32) bool { func (src *SpellResourceChecker) ConsumeAllResources(luaSpell *ActiveSpell, customPowerReq, customHPReq float32) bool {
// First check all resources // First check all resources
results := src.CheckAllResources(luaSpell, customPowerReq, customHPReq) results := src.CheckAllResources(luaSpell, customPowerReq, customHPReq)

View File

@ -35,15 +35,15 @@ func NewSpellTargeting() *SpellTargeting {
return &SpellTargeting{} return &SpellTargeting{}
} }
// GetSpellTargets finds all valid targets for a spell and adds them to the LuaSpell // GetSpellTargets finds all valid targets for a spell and adds them to the ActiveSpell
// This is the main targeting function converted from C++ SpellProcess::GetSpellTargets // This is the main targeting function converted from C++ SpellProcess::GetSpellTargets
func (st *SpellTargeting) GetSpellTargets(luaSpell *LuaSpell, options *TargetingOptions) *TargetingResult { func (st *SpellTargeting) GetSpellTargets(luaSpell *ActiveSpell, options *TargetingOptions) *TargetingResult {
if luaSpell == nil || luaSpell.Spell == nil { if luaSpell == nil || luaSpell.Spell == nil {
return &TargetingResult{ return &TargetingResult{
ValidTargets: make([]int32, 0), ValidTargets: make([]int32, 0),
InvalidTargets: make([]int32, 0), InvalidTargets: make([]int32, 0),
ErrorCode: FailureReasonInvalidTarget, ErrorCode: FailureReasonInvalidTarget,
ErrorMessage: "Invalid spell or LuaSpell", ErrorMessage: "Invalid spell or ActiveSpell",
} }
} }
@ -93,7 +93,7 @@ func (st *SpellTargeting) GetSpellTargets(luaSpell *LuaSpell, options *Targeting
} }
// getSelfTargets handles self-targeting spells // getSelfTargets handles self-targeting spells
func (st *SpellTargeting) getSelfTargets(luaSpell *LuaSpell, result *TargetingResult, options *TargetingOptions) { func (st *SpellTargeting) getSelfTargets(luaSpell *ActiveSpell, result *TargetingResult, options *TargetingOptions) {
if luaSpell.CasterID != 0 { if luaSpell.CasterID != 0 {
result.ValidTargets = append(result.ValidTargets, luaSpell.CasterID) result.ValidTargets = append(result.ValidTargets, luaSpell.CasterID)
luaSpell.AddTarget(luaSpell.CasterID) luaSpell.AddTarget(luaSpell.CasterID)
@ -104,7 +104,7 @@ func (st *SpellTargeting) getSelfTargets(luaSpell *LuaSpell, result *TargetingRe
} }
// getSingleTarget handles single-target spells // getSingleTarget handles single-target spells
func (st *SpellTargeting) getSingleTarget(luaSpell *LuaSpell, result *TargetingResult, options *TargetingOptions) { func (st *SpellTargeting) getSingleTarget(luaSpell *ActiveSpell, result *TargetingResult, options *TargetingOptions) {
targetID := luaSpell.InitialTarget targetID := luaSpell.InitialTarget
if targetID == 0 { if targetID == 0 {
targetID = luaSpell.CasterID // Default to self if no target targetID = luaSpell.CasterID // Default to self if no target
@ -121,7 +121,7 @@ func (st *SpellTargeting) getSingleTarget(luaSpell *LuaSpell, result *TargetingR
} }
// getGroupTargets handles group-targeting spells // getGroupTargets handles group-targeting spells
func (st *SpellTargeting) getGroupTargets(luaSpell *LuaSpell, result *TargetingResult, options *TargetingOptions) { func (st *SpellTargeting) getGroupTargets(luaSpell *ActiveSpell, result *TargetingResult, options *TargetingOptions) {
// TODO: Implement group targeting when group system is available // TODO: Implement group targeting when group system is available
// This would: // This would:
// 1. Get the caster's group // 1. Get the caster's group
@ -137,14 +137,14 @@ func (st *SpellTargeting) getGroupTargets(luaSpell *LuaSpell, result *TargetingR
} }
// getGroupAETargets handles group area effect spells // getGroupAETargets handles group area effect spells
func (st *SpellTargeting) getGroupAETargets(luaSpell *LuaSpell, result *TargetingResult, options *TargetingOptions) { func (st *SpellTargeting) getGroupAETargets(luaSpell *ActiveSpell, result *TargetingResult, options *TargetingOptions) {
// TODO: Implement group AE targeting // TODO: Implement group AE targeting
// This is similar to group targeting but may include pets and other considerations // This is similar to group targeting but may include pets and other considerations
st.getGroupTargets(luaSpell, result, options) st.getGroupTargets(luaSpell, result, options)
} }
// getAETargets handles area effect spells (true AOE) // getAETargets handles area effect spells (true AOE)
func (st *SpellTargeting) getAETargets(luaSpell *LuaSpell, result *TargetingResult, options *TargetingOptions) { func (st *SpellTargeting) getAETargets(luaSpell *ActiveSpell, result *TargetingResult, options *TargetingOptions) {
// TODO: Implement AOE targeting when zone system is available // TODO: Implement AOE targeting when zone system is available
// This would: // This would:
// 1. Get the spell's radius from spell data // 1. Get the spell's radius from spell data
@ -171,7 +171,7 @@ func (st *SpellTargeting) getAETargets(luaSpell *LuaSpell, result *TargetingResu
} }
// getPBAETargets handles point-blank area effect spells (centered on caster) // getPBAETargets handles point-blank area effect spells (centered on caster)
func (st *SpellTargeting) getPBAETargets(luaSpell *LuaSpell, result *TargetingResult, options *TargetingOptions) { func (st *SpellTargeting) getPBAETargets(luaSpell *ActiveSpell, result *TargetingResult, options *TargetingOptions) {
// TODO: Implement PBAE targeting when zone system is available // TODO: Implement PBAE targeting when zone system is available
// This is similar to AE but centered on the caster instead of a target location // This is similar to AE but centered on the caster instead of a target location
@ -183,7 +183,7 @@ func (st *SpellTargeting) getPBAETargets(luaSpell *LuaSpell, result *TargetingRe
} }
// isValidTarget validates whether a target is valid for a spell // isValidTarget validates whether a target is valid for a spell
func (st *SpellTargeting) isValidTarget(luaSpell *LuaSpell, targetID int32, options *TargetingOptions) bool { func (st *SpellTargeting) isValidTarget(luaSpell *ActiveSpell, targetID int32, options *TargetingOptions) bool {
if targetID == 0 { if targetID == 0 {
return false return false
} }
@ -235,7 +235,7 @@ func (st *SpellTargeting) ValidateLineOfSight(casterID, targetID int32, options
// GetPlayerGroupTargets gets valid group member targets for a spell // GetPlayerGroupTargets gets valid group member targets for a spell
// This is converted from C++ SpellProcess::GetPlayerGroupTargets // This is converted from C++ SpellProcess::GetPlayerGroupTargets
func (st *SpellTargeting) GetPlayerGroupTargets(targetPlayerID, casterID int32, luaSpell *LuaSpell, options *TargetingOptions) bool { func (st *SpellTargeting) GetPlayerGroupTargets(targetPlayerID, casterID int32, luaSpell *ActiveSpell, options *TargetingOptions) bool {
// TODO: Implement when group system is available // TODO: Implement when group system is available
// This would: // This would:
// 1. Get the target player's group // 1. Get the target player's group
@ -253,7 +253,7 @@ func (st *SpellTargeting) GetPlayerGroupTargets(targetPlayerID, casterID int32,
} }
// AddSelfAndPet adds caster and their pet to spell targets // AddSelfAndPet adds caster and their pet to spell targets
func (st *SpellTargeting) AddSelfAndPet(luaSpell *LuaSpell, casterID int32, onlyPet bool) { func (st *SpellTargeting) AddSelfAndPet(luaSpell *ActiveSpell, casterID int32, onlyPet bool) {
if !onlyPet && casterID != 0 { if !onlyPet && casterID != 0 {
luaSpell.AddTarget(casterID) luaSpell.AddTarget(casterID)
} }
@ -266,7 +266,7 @@ func (st *SpellTargeting) AddSelfAndPet(luaSpell *LuaSpell, casterID int32, only
} }
// AddNPCGroupOrSelfTarget adds NPC group members or self to targets // AddNPCGroupOrSelfTarget adds NPC group members or self to targets
func (st *SpellTargeting) AddNPCGroupOrSelfTarget(luaSpell *LuaSpell, targetID int32) { func (st *SpellTargeting) AddNPCGroupOrSelfTarget(luaSpell *ActiveSpell, targetID int32) {
// TODO: Implement NPC group targeting when NPC AI system is available // TODO: Implement NPC group targeting when NPC AI system is available
// NPCs may have different grouping mechanics than players // NPCs may have different grouping mechanics than players