388 lines
11 KiB
Go
388 lines
11 KiB
Go
package object
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"eq2emu/internal/spawn"
|
|
)
|
|
|
|
// ObjectSpawn represents an object that extends spawn functionality
|
|
// This properly integrates with the existing spawn system
|
|
type ObjectSpawn struct {
|
|
*spawn.Spawn // Embed the spawn functionality
|
|
|
|
// Object-specific properties
|
|
clickable bool // Whether the object can be clicked/interacted with
|
|
deviceID int8 // Device ID for interactive objects
|
|
|
|
// Merchant properties (duplicated from spawn since fields are unexported)
|
|
merchantID int32
|
|
merchantType int8
|
|
merchantMinLevel int32
|
|
merchantMaxLevel int32
|
|
isCollector bool
|
|
|
|
// Transport properties (duplicated from spawn since fields are unexported)
|
|
transporterID int32
|
|
}
|
|
|
|
// NewObjectSpawn creates a new object spawn with default values
|
|
func NewObjectSpawn() *ObjectSpawn {
|
|
// Create base spawn
|
|
baseSpawn := spawn.NewSpawn()
|
|
|
|
// Set object-specific spawn properties
|
|
baseSpawn.SetSpawnType(ObjectSpawnType)
|
|
|
|
// Set object appearance defaults
|
|
appearance := baseSpawn.GetAppearanceData()
|
|
appearance.ActivityStatus = ObjectActivityStatus
|
|
appearance.Pos.State = ObjectPosState
|
|
appearance.Difficulty = ObjectDifficulty
|
|
// Note: No SetAppearance method, but appearance is modified by reference
|
|
|
|
return &ObjectSpawn{
|
|
Spawn: baseSpawn,
|
|
clickable: false,
|
|
deviceID: DeviceIDNone,
|
|
}
|
|
}
|
|
|
|
// SetClickable sets whether the object can be clicked
|
|
func (os *ObjectSpawn) SetClickable(clickable bool) {
|
|
os.clickable = clickable
|
|
}
|
|
|
|
// IsClickable returns whether the object can be clicked
|
|
func (os *ObjectSpawn) IsClickable() bool {
|
|
return os.clickable
|
|
}
|
|
|
|
// SetDeviceID sets the device ID for interactive objects
|
|
func (os *ObjectSpawn) SetDeviceID(deviceID int8) {
|
|
os.deviceID = deviceID
|
|
}
|
|
|
|
// GetDeviceID returns the device ID
|
|
func (os *ObjectSpawn) GetDeviceID() int8 {
|
|
return os.deviceID
|
|
}
|
|
|
|
// IsObject always returns true for object spawns
|
|
func (os *ObjectSpawn) IsObject() bool {
|
|
return true
|
|
}
|
|
|
|
// Copy creates a deep copy of the object spawn
|
|
func (os *ObjectSpawn) Copy() *ObjectSpawn {
|
|
// Create new object spawn with new spawn
|
|
newObjectSpawn := NewObjectSpawn()
|
|
|
|
// Copy properties from original
|
|
newObjectSpawn.clickable = os.clickable
|
|
newObjectSpawn.deviceID = os.deviceID
|
|
|
|
// Copy spawn properties
|
|
newObjectSpawn.SetDatabaseID(os.GetDatabaseID())
|
|
newObjectSpawn.SetID(os.GetID())
|
|
newObjectSpawn.SetName(os.GetName())
|
|
newObjectSpawn.SetLevel(os.GetLevel())
|
|
newObjectSpawn.SetSize(os.GetSize())
|
|
newObjectSpawn.SetSpawnType(os.GetSpawnType())
|
|
newObjectSpawn.SetX(os.GetX())
|
|
newObjectSpawn.SetY(os.GetY(), false)
|
|
newObjectSpawn.SetZ(os.GetZ())
|
|
newObjectSpawn.SetHeading(int16(os.GetHeading()), int16(os.GetHeading()))
|
|
newObjectSpawn.SetFactionID(os.GetFactionID())
|
|
newObjectSpawn.SetTarget(os.GetTarget())
|
|
newObjectSpawn.SetAlive(os.IsAlive())
|
|
|
|
// Copy merchant properties if they exist
|
|
if os.merchantID > 0 {
|
|
newObjectSpawn.merchantID = os.merchantID
|
|
newObjectSpawn.merchantType = os.merchantType
|
|
newObjectSpawn.merchantMinLevel = os.merchantMinLevel
|
|
newObjectSpawn.merchantMaxLevel = os.merchantMaxLevel
|
|
}
|
|
|
|
// Copy transport properties if they exist
|
|
if os.transporterID > 0 {
|
|
newObjectSpawn.transporterID = os.transporterID
|
|
}
|
|
|
|
newObjectSpawn.isCollector = os.isCollector
|
|
|
|
return newObjectSpawn
|
|
}
|
|
|
|
// HandleUse processes object interaction by a client
|
|
func (os *ObjectSpawn) HandleUse(clientID int32, command string) error {
|
|
// Use the base object's HandleUse logic but with spawn integration
|
|
object := &Object{}
|
|
|
|
// Copy relevant properties for handling
|
|
object.clickable = os.clickable
|
|
object.deviceID = os.deviceID
|
|
object.transporterID = os.transporterID
|
|
object.appearanceShowCommandIcon = int8(0)
|
|
if os.GetAppearanceData().ShowCommandIcon == 1 {
|
|
object.appearanceShowCommandIcon = ObjectShowCommandIcon
|
|
}
|
|
|
|
// TODO: Copy command lists when they're integrated with spawn system
|
|
|
|
return object.HandleUse(clientID, command)
|
|
}
|
|
|
|
// SetShowCommandIcon sets whether to show the command icon
|
|
func (os *ObjectSpawn) SetShowCommandIcon(show bool) {
|
|
appearance := os.GetAppearanceData()
|
|
if show {
|
|
appearance.ShowCommandIcon = ObjectShowCommandIcon
|
|
} else {
|
|
appearance.ShowCommandIcon = 0
|
|
}
|
|
// Appearance is modified by reference, no need to set it back
|
|
}
|
|
|
|
// ShowsCommandIcon returns whether the command icon is shown
|
|
func (os *ObjectSpawn) ShowsCommandIcon() bool {
|
|
return os.GetAppearanceData().ShowCommandIcon == ObjectShowCommandIcon
|
|
}
|
|
|
|
// GetObjectInfo returns comprehensive information about the object spawn
|
|
func (os *ObjectSpawn) GetObjectInfo() map[string]any {
|
|
info := make(map[string]any)
|
|
|
|
// Add spawn info
|
|
info["spawn_id"] = os.GetID()
|
|
info["database_id"] = os.GetDatabaseID()
|
|
info["zone_name"] = os.GetZoneName()
|
|
info["spawn_type"] = os.GetSpawnType()
|
|
info["size"] = os.GetSize()
|
|
|
|
// Add object-specific info
|
|
info["clickable"] = os.clickable
|
|
info["device_id"] = os.deviceID
|
|
info["shows_command_icon"] = os.ShowsCommandIcon()
|
|
info["transporter_id"] = os.transporterID
|
|
info["merchant_id"] = os.merchantID
|
|
info["is_collector"] = os.isCollector
|
|
|
|
// Add position info
|
|
appearance := os.GetAppearanceData()
|
|
info["x"] = appearance.Pos.X
|
|
info["y"] = appearance.Pos.Y
|
|
info["z"] = appearance.Pos.Z
|
|
info["heading"] = appearance.Pos.Dir1
|
|
|
|
return info
|
|
}
|
|
|
|
// Getter and setter methods for object-specific properties
|
|
|
|
// GetMerchantID returns the merchant ID
|
|
func (os *ObjectSpawn) GetMerchantID() int32 {
|
|
return os.merchantID
|
|
}
|
|
|
|
// SetMerchantID sets the merchant ID
|
|
func (os *ObjectSpawn) SetMerchantID(merchantID int32) {
|
|
os.merchantID = merchantID
|
|
}
|
|
|
|
// GetMerchantType returns the merchant type
|
|
func (os *ObjectSpawn) GetMerchantType() int8 {
|
|
return os.merchantType
|
|
}
|
|
|
|
// SetMerchantType sets the merchant type
|
|
func (os *ObjectSpawn) SetMerchantType(merchantType int8) {
|
|
os.merchantType = merchantType
|
|
}
|
|
|
|
// GetMerchantMinLevel returns the minimum merchant level
|
|
func (os *ObjectSpawn) GetMerchantMinLevel() int8 {
|
|
return int8(os.merchantMinLevel)
|
|
}
|
|
|
|
// GetMerchantMaxLevel returns the maximum merchant level
|
|
func (os *ObjectSpawn) GetMerchantMaxLevel() int8 {
|
|
return int8(os.merchantMaxLevel)
|
|
}
|
|
|
|
// SetMerchantLevelRange sets the merchant level range
|
|
func (os *ObjectSpawn) SetMerchantLevelRange(minLevel, maxLevel int8) {
|
|
os.merchantMinLevel = int32(minLevel)
|
|
os.merchantMaxLevel = int32(maxLevel)
|
|
}
|
|
|
|
// GetTransporterID returns the transporter ID
|
|
func (os *ObjectSpawn) GetTransporterID() int32 {
|
|
return os.transporterID
|
|
}
|
|
|
|
// SetTransporterID sets the transporter ID
|
|
func (os *ObjectSpawn) SetTransporterID(transporterID int32) {
|
|
os.transporterID = transporterID
|
|
}
|
|
|
|
// IsCollector returns whether this object is a collector
|
|
func (os *ObjectSpawn) IsCollector() bool {
|
|
return os.isCollector
|
|
}
|
|
|
|
// SetCollector sets whether this object is a collector
|
|
func (os *ObjectSpawn) SetCollector(isCollector bool) {
|
|
os.isCollector = isCollector
|
|
}
|
|
|
|
// GetZoneName returns the zone name (from spawn system)
|
|
func (os *ObjectSpawn) GetZoneName() string {
|
|
// TODO: Implement when zone system is integrated
|
|
// For now return empty string
|
|
return ""
|
|
}
|
|
|
|
// SetZoneName sets the zone name (placeholder for spawn system)
|
|
func (os *ObjectSpawn) SetZoneName(zoneName string) {
|
|
// TODO: Implement when zone system is integrated
|
|
// This would be handled by the spawn system
|
|
}
|
|
|
|
// ObjectSpawnManager manages object spawns specifically
|
|
type ObjectSpawnManager struct {
|
|
objects map[int32]*ObjectSpawn // Object spawns by spawn ID
|
|
// TODO: Add reference to spawn manager when it exists
|
|
}
|
|
|
|
// NewObjectSpawnManager creates a new object spawn manager
|
|
func NewObjectSpawnManager() *ObjectSpawnManager {
|
|
return &ObjectSpawnManager{
|
|
objects: make(map[int32]*ObjectSpawn),
|
|
}
|
|
}
|
|
|
|
// AddObjectSpawn adds an object spawn to the manager
|
|
func (osm *ObjectSpawnManager) AddObjectSpawn(objectSpawn *ObjectSpawn) error {
|
|
if objectSpawn == nil {
|
|
return fmt.Errorf("cannot add nil object spawn")
|
|
}
|
|
|
|
// Add to object tracking
|
|
osm.objects[objectSpawn.GetID()] = objectSpawn
|
|
|
|
// TODO: Add to global spawn manager when it exists
|
|
return nil
|
|
}
|
|
|
|
// RemoveObjectSpawn removes an object spawn from the manager
|
|
func (osm *ObjectSpawnManager) RemoveObjectSpawn(spawnID int32) error {
|
|
// Remove from object tracking
|
|
if _, exists := osm.objects[spawnID]; !exists {
|
|
return fmt.Errorf("object spawn %d not found", spawnID)
|
|
}
|
|
|
|
delete(osm.objects, spawnID)
|
|
|
|
// TODO: Remove from global spawn manager when it exists
|
|
return nil
|
|
}
|
|
|
|
// GetObjectSpawn retrieves an object spawn by ID
|
|
func (osm *ObjectSpawnManager) GetObjectSpawn(spawnID int32) *ObjectSpawn {
|
|
return osm.objects[spawnID]
|
|
}
|
|
|
|
// GetObjectSpawnsByZone returns all object spawns in a zone
|
|
func (osm *ObjectSpawnManager) GetObjectSpawnsByZone(zoneName string) []*ObjectSpawn {
|
|
result := make([]*ObjectSpawn, 0)
|
|
|
|
// TODO: Filter by zone when zone system is implemented
|
|
// For now, return empty slice
|
|
return result
|
|
}
|
|
|
|
// GetInteractiveObjectSpawns returns all interactive object spawns
|
|
func (osm *ObjectSpawnManager) GetInteractiveObjectSpawns() []*ObjectSpawn {
|
|
result := make([]*ObjectSpawn, 0)
|
|
|
|
for _, objectSpawn := range osm.objects {
|
|
if objectSpawn.IsClickable() || objectSpawn.ShowsCommandIcon() {
|
|
result = append(result, objectSpawn)
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// ProcessObjectInteraction handles interaction with an object spawn
|
|
func (osm *ObjectSpawnManager) ProcessObjectInteraction(spawnID, clientID int32, command string) error {
|
|
objectSpawn := osm.GetObjectSpawn(spawnID)
|
|
if objectSpawn == nil {
|
|
return fmt.Errorf("object spawn %d not found", spawnID)
|
|
}
|
|
|
|
return objectSpawn.HandleUse(clientID, command)
|
|
}
|
|
|
|
// ConvertSpawnToObject converts a regular spawn to an object spawn (if applicable)
|
|
func ConvertSpawnToObject(spawn *spawn.Spawn) *ObjectSpawn {
|
|
if spawn.GetSpawnType() != ObjectSpawnType {
|
|
return nil
|
|
}
|
|
|
|
objectSpawn := &ObjectSpawn{
|
|
Spawn: spawn,
|
|
clickable: false, // Default, should be loaded from data
|
|
deviceID: DeviceIDNone,
|
|
}
|
|
|
|
// Set clickable based on appearance flags or other indicators
|
|
appearance := spawn.GetAppearanceData()
|
|
if appearance.ShowCommandIcon == ObjectShowCommandIcon {
|
|
objectSpawn.clickable = true
|
|
}
|
|
|
|
return objectSpawn
|
|
}
|
|
|
|
// LoadObjectSpawnFromData loads object spawn data from database/config
|
|
// This would be called when loading spawns from the database
|
|
func LoadObjectSpawnFromData(spawnData map[string]any) *ObjectSpawn {
|
|
objectSpawn := NewObjectSpawn()
|
|
|
|
// Load basic spawn data
|
|
if databaseID, ok := spawnData["database_id"].(int32); ok {
|
|
objectSpawn.SetDatabaseID(databaseID)
|
|
}
|
|
|
|
if zoneName, ok := spawnData["zone"].(string); ok {
|
|
objectSpawn.SetZoneName(zoneName)
|
|
}
|
|
|
|
// Load object-specific data
|
|
if clickable, ok := spawnData["clickable"].(bool); ok {
|
|
objectSpawn.SetClickable(clickable)
|
|
}
|
|
|
|
if deviceID, ok := spawnData["device_id"].(int8); ok {
|
|
objectSpawn.SetDeviceID(deviceID)
|
|
}
|
|
|
|
// Load position data
|
|
if x, ok := spawnData["x"].(float32); ok {
|
|
objectSpawn.SetX(x)
|
|
}
|
|
if y, ok := spawnData["y"].(float32); ok {
|
|
objectSpawn.SetY(y, false)
|
|
}
|
|
if z, ok := spawnData["z"].(float32); ok {
|
|
objectSpawn.SetZ(z)
|
|
}
|
|
|
|
// TODO: Load other properties as needed
|
|
|
|
return objectSpawn
|
|
}
|