eq2go/internal/skills/types.go

157 lines
4.0 KiB
Go

package skills
import "eq2emu/internal/common"
// SkillBonusValue represents a single skill bonus value
type SkillBonusValue struct {
SkillID int32 // Skill being modified
Value float32 // Bonus value
}
// SkillBonus represents skill bonuses from a spell
type SkillBonus struct {
SpellID int32 // Spell providing the bonus
Skills map[int32]*SkillBonusValue // Map of skill ID to bonus value
}
// Skill represents a character skill
type Skill struct {
SkillID int32 // Unique skill identifier
CurrentVal int16 // Current skill value
PreviousVal int16 // Previous skill value (for deltas)
MaxVal int16 // Maximum skill value
SkillType int32 // Skill category type
Display int8 // Display setting
ShortName common.EQ2String16 // Short skill name
Name common.EQ2String16 // Full skill name
Description common.EQ2String16 // Skill description
SaveNeeded bool // Whether skill needs database save
ActiveSkill bool // Whether skill is active/usable
}
// NewSkill creates a new skill with default values
func NewSkill() *Skill {
return &Skill{
SkillID: 0,
CurrentVal: 0,
PreviousVal: 0,
MaxVal: 0,
SkillType: 0,
Display: 0,
SaveNeeded: false,
ActiveSkill: true,
}
}
// NewSkillFromSkill creates a copy of an existing skill
func NewSkillFromSkill(skill *Skill) *Skill {
if skill == nil {
return NewSkill()
}
return &Skill{
SkillID: skill.SkillID,
CurrentVal: skill.CurrentVal,
PreviousVal: skill.CurrentVal, // Copy current as previous
MaxVal: skill.MaxVal,
SkillType: skill.SkillType,
Display: skill.Display,
ShortName: skill.ShortName,
Name: skill.Name,
Description: skill.Description,
SaveNeeded: false,
ActiveSkill: true,
}
}
// CheckDisarmSkill checks disarm skill against a chest
// Returns 1 for success, 0 for fail (no trigger), -1 for fail with trigger
func (s *Skill) CheckDisarmSkill(targetLevel int16, chestDifficulty int8) int {
if chestDifficulty < 2 {
return DisarmSuccess // No triggers on easy chests
}
if targetLevel < 1 {
targetLevel = 1
}
chestDiffResult := int32(targetLevel) * int32(chestDifficulty)
baseDifficulty := float32(15.0)
failThreshold := float32(10.0)
// Calculate success chance
chance := (100.0 - baseDifficulty) * (float32(s.CurrentVal) / float32(chestDiffResult))
if chance > (100.0 - baseDifficulty) {
chance = 100.0 - baseDifficulty
}
// Roll d100
roll := makeRandomFloat(0, 100)
if roll <= chance {
return DisarmSuccess
} else if roll > (chance + failThreshold) {
return DisarmTrigger
}
return DisarmFail
}
// GetCurrentValue returns the current skill value
func (s *Skill) GetCurrentValue() int32 {
return int32(s.CurrentVal)
}
// GetMaxValue returns the maximum skill value
func (s *Skill) GetMaxValue() int32 {
return int32(s.MaxVal)
}
// GetName returns the skill name
func (s *Skill) GetName() string {
return s.Name.Data
}
// GetShortName returns the skill short name
func (s *Skill) GetShortName() string {
return s.ShortName.Data
}
// GetDescription returns the skill description
func (s *Skill) GetDescription() string {
return s.Description.Data
}
// GetSkillType returns the skill type
func (s *Skill) GetSkillType() int32 {
return s.SkillType
}
// IsActive returns whether the skill is active
func (s *Skill) IsActive() bool {
return s.ActiveSkill
}
// NeedsSave returns whether the skill needs to be saved
func (s *Skill) NeedsSave() bool {
return s.SaveNeeded
}
// SetSaveNeeded marks the skill as needing to be saved
func (s *Skill) SetSaveNeeded(needed bool) {
s.SaveNeeded = needed
}
// SetActive sets whether the skill is active
func (s *Skill) SetActive(active bool) {
s.ActiveSkill = active
}
// makeRandomFloat generates a random float between min and max
// TODO: Replace with proper random number generation when integrated
func makeRandomFloat(min, max float32) float32 {
// Placeholder implementation
return min + ((max - min) / 2.0)
}