370 lines
9.8 KiB
Markdown
370 lines
9.8 KiB
Markdown
# Player System
|
|
|
|
The player system (`internal/player`) provides comprehensive player character management for the EQ2Go server emulator. This system is converted from the original C++ EQ2EMu Player implementation with modern Go concurrency patterns and clean architecture principles.
|
|
|
|
## Overview
|
|
|
|
The player system manages all aspects of player characters including:
|
|
|
|
- **Character Data**: Basic character information, stats, appearance
|
|
- **Experience**: Adventure and tradeskill XP, vitality, debt recovery
|
|
- **Skills**: Skill progression, bonuses, and management
|
|
- **Spells**: Spell book, casting, maintained effects, passive spells
|
|
- **Combat**: Auto-attack, combat state, weapon handling
|
|
- **Quests**: Quest tracking, progress, completion, rewards
|
|
- **Social**: Friends, ignore lists, guild membership
|
|
- **Economy**: Currency management, trading, banking
|
|
- **Movement**: Position tracking, spawn visibility, zone transfers
|
|
- **Character Flags**: Various character state flags and preferences
|
|
- **History**: Character history tracking and events
|
|
- **Items**: Inventory, equipment, appearance items
|
|
- **Housing**: House ownership, vault access
|
|
|
|
## Architecture
|
|
|
|
### Core Components
|
|
|
|
**Player** - Main player character struct extending Entity
|
|
**PlayerInfo** - Detailed character information for serialization
|
|
**PlayerManager** - Multi-player management and coordination
|
|
**PlayerControlFlags** - Character flag state management
|
|
**CharacterInstances** - Instance lockout tracking
|
|
|
|
### Key Files
|
|
|
|
- `player.go` - Core Player struct and basic functionality
|
|
- `player_info.go` - PlayerInfo struct for character sheet data
|
|
- `character_flags.go` - Character flag management
|
|
- `currency.go` - Coin and currency handling
|
|
- `experience.go` - XP, leveling, and vitality systems
|
|
- `combat.go` - Combat mechanics and processing
|
|
- `quest_management.go` - Quest system integration
|
|
- `spell_management.go` - Spell book and casting management
|
|
- `skill_management.go` - Skill system integration
|
|
- `spawn_management.go` - Spawn visibility and tracking
|
|
- `manager.go` - Multi-player management system
|
|
- `interfaces.go` - System integration interfaces
|
|
- `constants.go` - All character flag and system constants
|
|
- `types.go` - Data structures and type definitions
|
|
|
|
## Player Creation
|
|
|
|
```go
|
|
// Create a new player
|
|
player := player.NewPlayer()
|
|
|
|
// Set basic information
|
|
player.SetCharacterID(12345)
|
|
player.SetName("TestPlayer")
|
|
player.SetLevel(10)
|
|
player.SetClass(1) // Fighter
|
|
player.SetRace(0) // Human
|
|
|
|
// Initialize player info
|
|
info := player.GetPlayerInfo()
|
|
info.SetBindZone(1)
|
|
info.SetHouseZone(0)
|
|
```
|
|
|
|
## Character Flags
|
|
|
|
The system supports all EverQuest II character flags:
|
|
|
|
```go
|
|
// Set character flags
|
|
player.SetCharacterFlag(player.CF_ANONYMOUS)
|
|
player.SetCharacterFlag(player.CF_LFG)
|
|
player.ResetCharacterFlag(player.CF_AFK)
|
|
|
|
// Check flags
|
|
if player.GetCharacterFlag(player.CF_ROLEPLAYING) {
|
|
// Handle roleplaying state
|
|
}
|
|
```
|
|
|
|
### Available Flags
|
|
|
|
- **CF_COMBAT_EXPERIENCE_ENABLED** - Adventure XP enabled
|
|
- **CF_QUEST_EXPERIENCE_ENABLED** - Tradeskill XP enabled
|
|
- **CF_ANONYMOUS** - Anonymous mode
|
|
- **CF_ROLEPLAYING** - Roleplaying flag
|
|
- **CF_AFK** - Away from keyboard
|
|
- **CF_LFG** - Looking for group
|
|
- **CF_LFW** - Looking for work
|
|
- **CF_HIDE_HOOD/CF_HIDE_HELM** - Hide equipment
|
|
- **CF_ALLOW_DUEL_INVITES** - Allow duel invites
|
|
- **CF_ALLOW_TRADE_INVITES** - Allow trade invites
|
|
- **CF_ALLOW_GROUP_INVITES** - Allow group invites
|
|
- And many more...
|
|
|
|
## Experience System
|
|
|
|
```go
|
|
// Add adventure XP
|
|
if player.AddXP(1000) {
|
|
// Player may have leveled up
|
|
if player.GetLevel() > oldLevel {
|
|
// Handle level up
|
|
}
|
|
}
|
|
|
|
// Add tradeskill XP
|
|
player.AddTSXP(500)
|
|
|
|
// Check XP status
|
|
if player.AdventureXPEnabled() {
|
|
currentXP := player.GetXP()
|
|
neededXP := player.GetNeededXP()
|
|
}
|
|
|
|
// Calculate XP from kills
|
|
victim := &entity.Spawn{...}
|
|
xpReward := player.CalculateXP(victim)
|
|
```
|
|
|
|
## Currency Management
|
|
|
|
```go
|
|
// Add coins
|
|
player.AddCoins(10000) // Add 1 gold
|
|
|
|
// Remove coins (with validation)
|
|
if player.RemoveCoins(5000) {
|
|
// Transaction successful
|
|
}
|
|
|
|
// Check coin amounts
|
|
copper := player.GetCoinsCopper()
|
|
silver := player.GetCoinsSilver()
|
|
gold := player.GetCoinsGold()
|
|
plat := player.GetCoinsPlat()
|
|
|
|
// Validate sufficient funds
|
|
if player.HasCoins(1000) {
|
|
// Player can afford the cost
|
|
}
|
|
```
|
|
|
|
## Combat System
|
|
|
|
```go
|
|
// Enter combat
|
|
player.InCombat(true, false) // Melee combat
|
|
|
|
// Enter ranged combat
|
|
player.InCombat(true, true) // Ranged combat
|
|
|
|
// Exit combat
|
|
player.StopCombat(0) // Stop all combat
|
|
|
|
// Process combat (called periodically)
|
|
player.ProcessCombat()
|
|
|
|
// Check combat state
|
|
if player.GetInfoStruct().GetEngageCommands() != 0 {
|
|
// Player is in combat
|
|
}
|
|
```
|
|
|
|
## Spell Management
|
|
|
|
```go
|
|
// Add spell to spell book
|
|
player.AddSpellBookEntry(spellID, tier, slot, spellType, timer, true)
|
|
|
|
// Check if player has spell
|
|
if player.HasSpell(spellID, tier, false, false) {
|
|
// Player has the spell
|
|
}
|
|
|
|
// Get spell tier
|
|
tier := player.GetSpellTier(spellID)
|
|
|
|
// Lock/unlock spells
|
|
player.LockAllSpells()
|
|
player.UnlockAllSpells(true, nil)
|
|
|
|
// Manage passive spells
|
|
player.AddPassiveSpell(spellID, tier)
|
|
player.ApplyPassiveSpells()
|
|
```
|
|
|
|
## Quest Integration
|
|
|
|
```go
|
|
// Get active quest
|
|
quest := player.GetQuest(questID)
|
|
|
|
// Check quest completion
|
|
if player.HasQuestBeenCompleted(questID) {
|
|
count := player.GetQuestCompletedCount(questID)
|
|
}
|
|
|
|
// Update quest progress
|
|
player.SetStepComplete(questID, stepID)
|
|
player.AddStepProgress(questID, stepID, progress)
|
|
|
|
// Check quest requirements
|
|
if player.CanReceiveQuest(questID, nil) {
|
|
// Player can accept quest
|
|
}
|
|
```
|
|
|
|
## Social Features
|
|
|
|
```go
|
|
// Manage friends
|
|
player.AddFriend("FriendName", true)
|
|
if player.IsFriend("SomeName") {
|
|
// Handle friend interaction
|
|
}
|
|
|
|
// Manage ignore list
|
|
player.AddIgnore("PlayerName", true)
|
|
if player.IsIgnored("SomeName") {
|
|
// Player is ignored
|
|
}
|
|
|
|
// Get social lists
|
|
friends := player.GetFriends()
|
|
ignored := player.GetIgnoredPlayers()
|
|
```
|
|
|
|
## Spawn Management
|
|
|
|
```go
|
|
// Check spawn visibility
|
|
if player.ShouldSendSpawn(spawn) {
|
|
// Send spawn to player
|
|
player.SetSpawnSentState(spawn, player.SPAWN_STATE_SENDING)
|
|
}
|
|
|
|
// Get spawn by player index
|
|
spawn := player.GetSpawnByIndex(index)
|
|
|
|
// Remove spawn from player view
|
|
player.RemoveSpawn(spawn, false)
|
|
|
|
// Process spawn updates
|
|
player.CheckSpawnStateQueue()
|
|
```
|
|
|
|
## Player Manager
|
|
|
|
```go
|
|
// Create manager
|
|
config := player.ManagerConfig{
|
|
MaxPlayers: 1000,
|
|
SaveInterval: 5 * time.Minute,
|
|
StatsInterval: 1 * time.Minute,
|
|
EnableValidation: true,
|
|
EnableEvents: true,
|
|
EnableStatistics: true,
|
|
}
|
|
manager := player.NewManager(config)
|
|
|
|
// Start manager
|
|
manager.Start()
|
|
|
|
// Add player
|
|
err := manager.AddPlayer(player)
|
|
|
|
// Get players
|
|
allPlayers := manager.GetAllPlayers()
|
|
zonePlayers := manager.GetPlayersInZone(zoneID)
|
|
player := manager.GetPlayerByName("PlayerName")
|
|
|
|
// Send messages
|
|
manager.SendToAll(message)
|
|
manager.SendToZone(zoneID, message)
|
|
|
|
// Get statistics
|
|
stats := manager.GetPlayerStats()
|
|
```
|
|
|
|
## Database Integration
|
|
|
|
The system provides interfaces for database operations:
|
|
|
|
```go
|
|
type PlayerDatabase interface {
|
|
LoadPlayer(characterID int32) (*Player, error)
|
|
SavePlayer(player *Player) error
|
|
DeletePlayer(characterID int32) error
|
|
LoadPlayerQuests(characterID int32) ([]*quests.Quest, error)
|
|
SavePlayerQuests(characterID int32, quests []*quests.Quest) error
|
|
// ... more methods
|
|
}
|
|
```
|
|
|
|
## Event System
|
|
|
|
```go
|
|
type PlayerEventHandler interface {
|
|
OnPlayerLogin(player *Player) error
|
|
OnPlayerLogout(player *Player) error
|
|
OnPlayerDeath(player *Player, killer entity.Entity) error
|
|
OnPlayerLevelUp(player *Player, newLevel int8) error
|
|
// ... more events
|
|
}
|
|
|
|
// Register event handler
|
|
manager.AddEventHandler(myHandler)
|
|
```
|
|
|
|
## Thread Safety
|
|
|
|
All player operations are thread-safe using appropriate synchronization:
|
|
|
|
- **RWMutex** for read-heavy operations (spawn maps, quest lists)
|
|
- **Atomic operations** for simple flags and counters
|
|
- **Channel-based communication** for background processing
|
|
- **Proper lock ordering** to prevent deadlocks
|
|
|
|
## Integration with Other Systems
|
|
|
|
The player system integrates with:
|
|
|
|
- **Entity System** - Players extend entities for combat capabilities
|
|
- **Spell System** - Complete spell casting and effect management
|
|
- **Quest System** - Quest tracking and progression
|
|
- **Skill System** - Skill advancement and bonuses
|
|
- **Faction System** - Reputation and standings
|
|
- **Title System** - Character titles and achievements
|
|
- **Trade System** - Player-to-player trading
|
|
- **Housing System** - House ownership and access
|
|
|
|
## Performance Considerations
|
|
|
|
- **Efficient spawn tracking** with hash maps for O(1) lookups
|
|
- **Periodic processing** batched for better performance
|
|
- **Memory-efficient data structures** with proper cleanup
|
|
- **Background save operations** to avoid blocking gameplay
|
|
- **Statistics collection** with minimal overhead
|
|
|
|
## Migration from C++
|
|
|
|
This Go implementation maintains compatibility with the original C++ EQ2EMu player system while providing:
|
|
|
|
- **Modern concurrency** with goroutines and channels
|
|
- **Better error handling** with Go's error interface
|
|
- **Cleaner architecture** with interface-based design
|
|
- **Improved maintainability** with package organization
|
|
- **Enhanced testing** capabilities
|
|
|
|
## TODO Items
|
|
|
|
The conversion includes TODO comments marking areas for future implementation:
|
|
|
|
- **LUA integration** for scripting support
|
|
- **Advanced packet handling** for client communication
|
|
- **Complete database schema** implementation
|
|
- **Full item system** integration
|
|
- **Group and raid** management
|
|
- **PvP mechanics** and flagging
|
|
- **Mail system** implementation
|
|
- **Appearance system** completion
|
|
|
|
## Usage Examples
|
|
|
|
See the individual file documentation and method comments for detailed usage examples. The system is designed to be used alongside the existing EQ2Go server infrastructure with proper initialization and configuration. |