470 lines
14 KiB
Go
470 lines
14 KiB
Go
package spells
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
)
|
|
|
|
// SpellResourceChecker handles checking and consuming spell casting resources
|
|
type SpellResourceChecker struct {
|
|
// TODO: Add references to entity system when available
|
|
// entityManager *EntityManager
|
|
|
|
mutex sync.RWMutex
|
|
}
|
|
|
|
// ResourceCheckResult represents the result of a resource check
|
|
type ResourceCheckResult struct {
|
|
HasSufficient bool // Whether entity has sufficient resources
|
|
CurrentValue float32 // Current value of the resource
|
|
RequiredValue float32 // Required value for the spell
|
|
ResourceType int32 // Type of resource checked
|
|
ErrorMessage string // Error message if check failed
|
|
}
|
|
|
|
// NewSpellResourceChecker creates a new resource checker
|
|
func NewSpellResourceChecker() *SpellResourceChecker {
|
|
return &SpellResourceChecker{}
|
|
}
|
|
|
|
// CheckPower verifies if the caster has enough power to cast the spell
|
|
// Converted from C++ SpellProcess::CheckPower
|
|
func (src *SpellResourceChecker) CheckPower(luaSpell *LuaSpell, customPowerReq float32) *ResourceCheckResult {
|
|
if luaSpell == nil || luaSpell.Spell == nil {
|
|
return &ResourceCheckResult{
|
|
HasSufficient: false,
|
|
CurrentValue: 0,
|
|
RequiredValue: 0,
|
|
ResourceType: ResourceCheckPower,
|
|
ErrorMessage: "Invalid spell",
|
|
}
|
|
}
|
|
|
|
powerRequired := customPowerReq
|
|
if powerRequired == 0 {
|
|
powerRequired = luaSpell.Spell.GetPowerRequired()
|
|
}
|
|
|
|
// TODO: Get actual power from entity when entity system is available
|
|
// For now, assume entity has sufficient power
|
|
currentPower := float32(1000.0) // Placeholder
|
|
|
|
result := &ResourceCheckResult{
|
|
HasSufficient: currentPower >= powerRequired,
|
|
CurrentValue: currentPower,
|
|
RequiredValue: powerRequired,
|
|
ResourceType: ResourceCheckPower,
|
|
ErrorMessage: "",
|
|
}
|
|
|
|
if !result.HasSufficient {
|
|
result.ErrorMessage = fmt.Sprintf("Insufficient power: need %.1f, have %.1f", powerRequired, currentPower)
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// TakePower consumes power for spell casting
|
|
// Converted from C++ SpellProcess::TakePower
|
|
func (src *SpellResourceChecker) TakePower(luaSpell *LuaSpell, customPowerReq float32) bool {
|
|
result := src.CheckPower(luaSpell, customPowerReq)
|
|
if !result.HasSufficient {
|
|
return false
|
|
}
|
|
|
|
// TODO: Actually deduct power from entity when entity system is available
|
|
// This would call something like:
|
|
// entity.GetInfoStruct().SetPower(currentPower - powerRequired)
|
|
// entity.GetZone().TriggerCharSheetTimer() // Update client display
|
|
|
|
return true
|
|
}
|
|
|
|
// CheckHP verifies if the caster has enough health to cast the spell
|
|
// Converted from C++ SpellProcess::CheckHP
|
|
func (src *SpellResourceChecker) CheckHP(luaSpell *LuaSpell, customHPReq float32) *ResourceCheckResult {
|
|
if luaSpell == nil || luaSpell.Spell == nil {
|
|
return &ResourceCheckResult{
|
|
HasSufficient: false,
|
|
CurrentValue: 0,
|
|
RequiredValue: 0,
|
|
ResourceType: ResourceCheckHealth,
|
|
ErrorMessage: "Invalid spell",
|
|
}
|
|
}
|
|
|
|
hpRequired := customHPReq
|
|
if hpRequired == 0 {
|
|
hpRequired = float32(luaSpell.Spell.GetHPRequired())
|
|
}
|
|
|
|
// TODO: Get actual HP from entity when entity system is available
|
|
// For now, assume entity has sufficient HP
|
|
currentHP := float32(1000.0) // Placeholder
|
|
|
|
result := &ResourceCheckResult{
|
|
HasSufficient: currentHP >= hpRequired,
|
|
CurrentValue: currentHP,
|
|
RequiredValue: hpRequired,
|
|
ResourceType: ResourceCheckHealth,
|
|
ErrorMessage: "",
|
|
}
|
|
|
|
if !result.HasSufficient {
|
|
result.ErrorMessage = fmt.Sprintf("Insufficient health: need %.1f, have %.1f", hpRequired, currentHP)
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// TakeHP consumes health for spell casting
|
|
// Converted from C++ SpellProcess::TakeHP
|
|
func (src *SpellResourceChecker) TakeHP(luaSpell *LuaSpell, customHPReq float32) bool {
|
|
result := src.CheckHP(luaSpell, customHPReq)
|
|
if !result.HasSufficient {
|
|
return false
|
|
}
|
|
|
|
// TODO: Actually deduct HP from entity when entity system is available
|
|
// This would call something like:
|
|
// entity.GetInfoStruct().SetHP(currentHP - hpRequired)
|
|
// entity.GetZone().TriggerCharSheetTimer() // Update client display
|
|
|
|
return true
|
|
}
|
|
|
|
// CheckConcentration verifies if the caster has enough concentration to cast the spell
|
|
// Converted from C++ SpellProcess::CheckConcentration
|
|
func (src *SpellResourceChecker) CheckConcentration(luaSpell *LuaSpell) *ResourceCheckResult {
|
|
if luaSpell == nil || luaSpell.Spell == nil {
|
|
return &ResourceCheckResult{
|
|
HasSufficient: false,
|
|
CurrentValue: 0,
|
|
RequiredValue: 0,
|
|
ResourceType: ResourceCheckConcentration,
|
|
ErrorMessage: "Invalid spell",
|
|
}
|
|
}
|
|
|
|
spellData := luaSpell.Spell.GetSpellData()
|
|
if spellData == nil {
|
|
return &ResourceCheckResult{
|
|
HasSufficient: false,
|
|
CurrentValue: 0,
|
|
RequiredValue: 0,
|
|
ResourceType: ResourceCheckConcentration,
|
|
ErrorMessage: "Invalid spell data",
|
|
}
|
|
}
|
|
|
|
concentrationRequired := float32(spellData.ReqConcentration)
|
|
|
|
// TODO: Get actual concentration from entity when entity system is available
|
|
// For now, assume entity has sufficient concentration
|
|
currentConcentration := float32(100.0) // Placeholder
|
|
|
|
result := &ResourceCheckResult{
|
|
HasSufficient: currentConcentration >= concentrationRequired,
|
|
CurrentValue: currentConcentration,
|
|
RequiredValue: concentrationRequired,
|
|
ResourceType: ResourceCheckConcentration,
|
|
ErrorMessage: "",
|
|
}
|
|
|
|
if !result.HasSufficient {
|
|
result.ErrorMessage = fmt.Sprintf("Insufficient concentration: need %.1f, have %.1f", concentrationRequired, currentConcentration)
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// AddConcentration adds concentration for maintained spells
|
|
// Converted from C++ SpellProcess::AddConcentration
|
|
func (src *SpellResourceChecker) AddConcentration(luaSpell *LuaSpell) bool {
|
|
result := src.CheckConcentration(luaSpell)
|
|
if !result.HasSufficient {
|
|
return false
|
|
}
|
|
|
|
// TODO: Actually deduct concentration from entity when entity system is available
|
|
// This would call something like:
|
|
// currentConc := entity.GetInfoStruct().GetCurConcentration()
|
|
// entity.GetInfoStruct().SetCurConcentration(currentConc + concentrationRequired)
|
|
// entity.GetZone().TriggerCharSheetTimer() // Update client display
|
|
|
|
return true
|
|
}
|
|
|
|
// CheckSavagery verifies if the caster has enough savagery to cast the spell
|
|
// Converted from C++ SpellProcess::CheckSavagery
|
|
func (src *SpellResourceChecker) CheckSavagery(luaSpell *LuaSpell) *ResourceCheckResult {
|
|
if luaSpell == nil || luaSpell.Spell == nil {
|
|
return &ResourceCheckResult{
|
|
HasSufficient: false,
|
|
CurrentValue: 0,
|
|
RequiredValue: 0,
|
|
ResourceType: ResourceCheckSavagery,
|
|
ErrorMessage: "Invalid spell",
|
|
}
|
|
}
|
|
|
|
savageryRequired := float32(luaSpell.Spell.GetSavageryRequired())
|
|
|
|
// TODO: Get actual savagery from entity when entity system is available
|
|
// For now, assume entity has sufficient savagery
|
|
currentSavagery := float32(100.0) // Placeholder
|
|
|
|
result := &ResourceCheckResult{
|
|
HasSufficient: currentSavagery >= savageryRequired,
|
|
CurrentValue: currentSavagery,
|
|
RequiredValue: savageryRequired,
|
|
ResourceType: ResourceCheckSavagery,
|
|
ErrorMessage: "",
|
|
}
|
|
|
|
if !result.HasSufficient {
|
|
result.ErrorMessage = fmt.Sprintf("Insufficient savagery: need %.1f, have %.1f", savageryRequired, currentSavagery)
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// TakeSavagery consumes savagery for spell casting
|
|
// Converted from C++ SpellProcess::TakeSavagery
|
|
func (src *SpellResourceChecker) TakeSavagery(luaSpell *LuaSpell) bool {
|
|
result := src.CheckSavagery(luaSpell)
|
|
if !result.HasSufficient {
|
|
return false
|
|
}
|
|
|
|
// TODO: Actually deduct savagery from entity when entity system is available
|
|
// This would call something like:
|
|
// entity.GetInfoStruct().SetSavagery(currentSavagery - savageryRequired)
|
|
// entity.GetZone().TriggerCharSheetTimer() // Update client display
|
|
|
|
return true
|
|
}
|
|
|
|
// CheckDissonance verifies if the caster has enough dissonance to cast the spell
|
|
// Converted from C++ SpellProcess::CheckDissonance
|
|
func (src *SpellResourceChecker) CheckDissonance(luaSpell *LuaSpell) *ResourceCheckResult {
|
|
if luaSpell == nil || luaSpell.Spell == nil {
|
|
return &ResourceCheckResult{
|
|
HasSufficient: false,
|
|
CurrentValue: 0,
|
|
RequiredValue: 0,
|
|
ResourceType: ResourceCheckDissonance,
|
|
ErrorMessage: "Invalid spell",
|
|
}
|
|
}
|
|
|
|
dissonanceRequired := float32(luaSpell.Spell.GetDissonanceRequired())
|
|
|
|
// TODO: Get actual dissonance from entity when entity system is available
|
|
// For now, assume entity has sufficient dissonance
|
|
currentDissonance := float32(100.0) // Placeholder
|
|
|
|
result := &ResourceCheckResult{
|
|
HasSufficient: currentDissonance >= dissonanceRequired,
|
|
CurrentValue: currentDissonance,
|
|
RequiredValue: dissonanceRequired,
|
|
ResourceType: ResourceCheckDissonance,
|
|
ErrorMessage: "",
|
|
}
|
|
|
|
if !result.HasSufficient {
|
|
result.ErrorMessage = fmt.Sprintf("Insufficient dissonance: need %.1f, have %.1f", dissonanceRequired, currentDissonance)
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// AddDissonance adds dissonance for spell casting
|
|
// Converted from C++ SpellProcess::AddDissonance
|
|
func (src *SpellResourceChecker) AddDissonance(luaSpell *LuaSpell) bool {
|
|
result := src.CheckDissonance(luaSpell)
|
|
if !result.HasSufficient {
|
|
return false
|
|
}
|
|
|
|
// TODO: Actually add dissonance to entity when entity system is available
|
|
// This would call something like:
|
|
// entity.GetInfoStruct().SetDissonance(currentDissonance + dissonanceRequired)
|
|
// entity.GetZone().TriggerCharSheetTimer() // Update client display
|
|
|
|
return true
|
|
}
|
|
|
|
// CheckAllResources performs a comprehensive resource check for a spell
|
|
func (src *SpellResourceChecker) CheckAllResources(luaSpell *LuaSpell, customPowerReq, customHPReq float32) []ResourceCheckResult {
|
|
results := make([]ResourceCheckResult, 0)
|
|
|
|
// Check power
|
|
powerResult := src.CheckPower(luaSpell, customPowerReq)
|
|
if powerResult.RequiredValue > 0 {
|
|
results = append(results, *powerResult)
|
|
}
|
|
|
|
// Check health
|
|
hpResult := src.CheckHP(luaSpell, customHPReq)
|
|
if hpResult.RequiredValue > 0 {
|
|
results = append(results, *hpResult)
|
|
}
|
|
|
|
// Check concentration
|
|
concResult := src.CheckConcentration(luaSpell)
|
|
if concResult.RequiredValue > 0 {
|
|
results = append(results, *concResult)
|
|
}
|
|
|
|
// Check savagery
|
|
savageryResult := src.CheckSavagery(luaSpell)
|
|
if savageryResult.RequiredValue > 0 {
|
|
results = append(results, *savageryResult)
|
|
}
|
|
|
|
// Check dissonance
|
|
dissonanceResult := src.CheckDissonance(luaSpell)
|
|
if dissonanceResult.RequiredValue > 0 {
|
|
results = append(results, *dissonanceResult)
|
|
}
|
|
|
|
return results
|
|
}
|
|
|
|
// ConsumeAllResources attempts to consume all required resources for a spell
|
|
func (src *SpellResourceChecker) ConsumeAllResources(luaSpell *LuaSpell, customPowerReq, customHPReq float32) bool {
|
|
// First check all resources
|
|
results := src.CheckAllResources(luaSpell, customPowerReq, customHPReq)
|
|
|
|
// Verify all resources are sufficient
|
|
for _, result := range results {
|
|
if !result.HasSufficient {
|
|
return false
|
|
}
|
|
}
|
|
|
|
// Consume resources
|
|
success := true
|
|
|
|
// Take power if required
|
|
powerResult := src.CheckPower(luaSpell, customPowerReq)
|
|
if powerResult.RequiredValue > 0 {
|
|
success = success && src.TakePower(luaSpell, customPowerReq)
|
|
}
|
|
|
|
// Take health if required
|
|
hpResult := src.CheckHP(luaSpell, customHPReq)
|
|
if hpResult.RequiredValue > 0 {
|
|
success = success && src.TakeHP(luaSpell, customHPReq)
|
|
}
|
|
|
|
// Add concentration if required (for maintained spells)
|
|
spellData := luaSpell.Spell.GetSpellData()
|
|
if spellData != nil && spellData.CastType == SpellCastTypeToggle {
|
|
concResult := src.CheckConcentration(luaSpell)
|
|
if concResult.RequiredValue > 0 {
|
|
success = success && src.AddConcentration(luaSpell)
|
|
}
|
|
}
|
|
|
|
// Take savagery if required
|
|
savageryResult := src.CheckSavagery(luaSpell)
|
|
if savageryResult.RequiredValue > 0 {
|
|
success = success && src.TakeSavagery(luaSpell)
|
|
}
|
|
|
|
// Add dissonance if required
|
|
dissonanceResult := src.CheckDissonance(luaSpell)
|
|
if dissonanceResult.RequiredValue > 0 {
|
|
success = success && src.AddDissonance(luaSpell)
|
|
}
|
|
|
|
return success
|
|
}
|
|
|
|
// GetResourceSummary returns a summary of all resource requirements for a spell
|
|
func (src *SpellResourceChecker) GetResourceSummary(spell *Spell) map[string]float32 {
|
|
summary := make(map[string]float32)
|
|
|
|
if spell == nil {
|
|
return summary
|
|
}
|
|
|
|
summary["power"] = spell.GetPowerRequired()
|
|
summary["health"] = float32(spell.GetHPRequired())
|
|
summary["savagery"] = float32(spell.GetSavageryRequired())
|
|
summary["dissonance"] = float32(spell.GetDissonanceRequired())
|
|
|
|
spellData := spell.GetSpellData()
|
|
if spellData != nil {
|
|
summary["concentration"] = float32(spellData.ReqConcentration)
|
|
}
|
|
|
|
return summary
|
|
}
|
|
|
|
// ValidateResourceRequirements checks if resource requirements are reasonable
|
|
func (src *SpellResourceChecker) ValidateResourceRequirements(spell *Spell) []string {
|
|
errors := make([]string, 0)
|
|
|
|
if spell == nil {
|
|
errors = append(errors, "Spell is nil")
|
|
return errors
|
|
}
|
|
|
|
// Check for negative requirements
|
|
if spell.GetPowerRequired() < 0 {
|
|
errors = append(errors, "Power requirement cannot be negative")
|
|
}
|
|
|
|
if spell.GetHPRequired() < 0 {
|
|
errors = append(errors, "Health requirement cannot be negative")
|
|
}
|
|
|
|
if spell.GetSavageryRequired() < 0 {
|
|
errors = append(errors, "Savagery requirement cannot be negative")
|
|
}
|
|
|
|
if spell.GetDissonanceRequired() < 0 {
|
|
errors = append(errors, "Dissonance requirement cannot be negative")
|
|
}
|
|
|
|
spellData := spell.GetSpellData()
|
|
if spellData != nil {
|
|
if spellData.ReqConcentration < 0 {
|
|
errors = append(errors, "Concentration requirement cannot be negative")
|
|
}
|
|
|
|
// Check for excessive requirements
|
|
if spell.GetPowerRequired() > 10000 {
|
|
errors = append(errors, "Power requirement seems excessive (>10000)")
|
|
}
|
|
|
|
if spell.GetHPRequired() > 5000 {
|
|
errors = append(errors, "Health requirement seems excessive (>5000)")
|
|
}
|
|
}
|
|
|
|
return errors
|
|
}
|
|
|
|
// GetFailureReason returns an appropriate failure reason code based on resource check results
|
|
func (src *SpellResourceChecker) GetFailureReason(results []ResourceCheckResult) int32 {
|
|
for _, result := range results {
|
|
if !result.HasSufficient {
|
|
switch result.ResourceType {
|
|
case ResourceCheckPower:
|
|
return FailureReasonInsufficientPower
|
|
case ResourceCheckHealth:
|
|
return FailureReasonInsufficientHealth
|
|
case ResourceCheckConcentration:
|
|
return FailureReasonInsufficientConc
|
|
default:
|
|
return FailureReasonRequirementNotMet
|
|
}
|
|
}
|
|
}
|
|
|
|
return FailureReasonNone
|
|
} |