281 lines
7.7 KiB
Go
281 lines
7.7 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
|
|
}
|
|
|
|
// 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.GetAppearance()
|
|
appearance.ActivityStatus = ObjectActivityStatus
|
|
appearance.Pos.State = ObjectPosState
|
|
appearance.Difficulty = ObjectDifficulty
|
|
baseSpawn.SetAppearance(appearance)
|
|
|
|
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 {
|
|
// Copy base spawn
|
|
newSpawn := os.Spawn.Copy()
|
|
|
|
// Create new object spawn
|
|
newObjectSpawn := &ObjectSpawn{
|
|
Spawn: newSpawn,
|
|
clickable: os.clickable,
|
|
deviceID: os.deviceID,
|
|
}
|
|
|
|
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.GetTransporterID()
|
|
object.appearanceShowCommandIcon = int8(0)
|
|
if os.GetAppearance().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.GetAppearance()
|
|
if show {
|
|
appearance.ShowCommandIcon = ObjectShowCommandIcon
|
|
} else {
|
|
appearance.ShowCommandIcon = 0
|
|
}
|
|
os.SetAppearance(appearance)
|
|
}
|
|
|
|
// ShowsCommandIcon returns whether the command icon is shown
|
|
func (os *ObjectSpawn) ShowsCommandIcon() bool {
|
|
return os.GetAppearance().ShowCommandIcon == ObjectShowCommandIcon
|
|
}
|
|
|
|
// GetObjectInfo returns comprehensive information about the object spawn
|
|
func (os *ObjectSpawn) GetObjectInfo() map[string]interface{} {
|
|
info := make(map[string]interface{})
|
|
|
|
// 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.GetTransporterID()
|
|
info["merchant_id"] = os.GetMerchantID()
|
|
info["is_collector"] = os.IsCollector()
|
|
|
|
// Add position info
|
|
appearance := os.GetAppearance()
|
|
info["x"] = appearance.Pos.X
|
|
info["y"] = appearance.Pos.Y
|
|
info["z"] = appearance.Pos.Z
|
|
info["heading"] = appearance.Pos.Dir1
|
|
|
|
return info
|
|
}
|
|
|
|
// ObjectSpawnManager manages object spawns specifically
|
|
type ObjectSpawnManager struct {
|
|
spawnManager *spawn.SpawnManager // Reference to global spawn manager
|
|
objects map[int32]*ObjectSpawn // Object spawns by spawn ID
|
|
}
|
|
|
|
// NewObjectSpawnManager creates a new object spawn manager
|
|
func NewObjectSpawnManager(spawnManager *spawn.SpawnManager) *ObjectSpawnManager {
|
|
return &ObjectSpawnManager{
|
|
spawnManager: spawnManager,
|
|
objects: make(map[int32]*ObjectSpawn),
|
|
}
|
|
}
|
|
|
|
// AddObjectSpawn adds an object spawn to both the object and spawn managers
|
|
func (osm *ObjectSpawnManager) AddObjectSpawn(objectSpawn *ObjectSpawn) error {
|
|
// Add to spawn manager first
|
|
if err := osm.spawnManager.AddSpawn(objectSpawn.Spawn); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Add to object tracking
|
|
osm.objects[objectSpawn.GetID()] = objectSpawn
|
|
|
|
return nil
|
|
}
|
|
|
|
// RemoveObjectSpawn removes an object spawn from both managers
|
|
func (osm *ObjectSpawnManager) RemoveObjectSpawn(spawnID int32) error {
|
|
// Remove from object tracking
|
|
delete(osm.objects, spawnID)
|
|
|
|
// Remove from spawn manager
|
|
return osm.spawnManager.RemoveSpawn(spawnID)
|
|
}
|
|
|
|
// 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)
|
|
|
|
// Get all spawns in zone and filter for objects
|
|
spawns := osm.spawnManager.GetSpawnsByZone(zoneName)
|
|
for _, spawn := range spawns {
|
|
if spawn.GetSpawnType() == ObjectSpawnType {
|
|
if objectSpawn, exists := osm.objects[spawn.GetID()]; exists {
|
|
result = append(result, objectSpawn)
|
|
}
|
|
}
|
|
}
|
|
|
|
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.GetAppearance()
|
|
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]interface{}) *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 {
|
|
appearance := objectSpawn.GetAppearance()
|
|
appearance.Pos.X = x
|
|
objectSpawn.SetAppearance(appearance)
|
|
}
|
|
|
|
// TODO: Load other properties as needed
|
|
|
|
return objectSpawn
|
|
}
|