330 lines
7.2 KiB
Go
330 lines
7.2 KiB
Go
package object
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
|
|
"eq2emu/internal/spawn"
|
|
)
|
|
|
|
// Object constants
|
|
const (
|
|
// Object spawn type
|
|
ObjectSpawnType = 2
|
|
|
|
// Object appearance defaults
|
|
ObjectActivityStatus = 64
|
|
ObjectPosState = 1
|
|
ObjectDifficulty = 0
|
|
|
|
// Object interaction constants
|
|
ObjectShowCommandIcon = 1
|
|
|
|
// Object states
|
|
ObjectStateInactive = 0
|
|
ObjectStateActive = 1
|
|
|
|
// Interaction types
|
|
InteractionTypeNone = 0
|
|
InteractionTypeCommand = 1
|
|
InteractionTypeTransport = 2
|
|
InteractionTypeDevice = 3
|
|
)
|
|
|
|
// Object represents a game object that extends spawn functionality
|
|
type Object struct {
|
|
*spawn.Spawn // Embed spawn functionality
|
|
|
|
// Object-specific properties
|
|
clickable bool // Whether the object can be clicked/interacted with
|
|
deviceID int8 // Device ID for interactive objects
|
|
|
|
// Merchant properties
|
|
merchantID int32
|
|
merchantType int8
|
|
merchantMinLevel int32
|
|
merchantMaxLevel int32
|
|
isCollector bool
|
|
|
|
// Transport properties
|
|
transporterID int32
|
|
|
|
// Zone tracking (since spawn doesn't expose zone methods yet)
|
|
zoneName string
|
|
|
|
// Thread safety
|
|
mutex sync.RWMutex
|
|
}
|
|
|
|
// NewObject creates a new object with default values
|
|
func NewObject() *Object {
|
|
// 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
|
|
|
|
return &Object{
|
|
Spawn: baseSpawn,
|
|
clickable: false,
|
|
deviceID: 0,
|
|
zoneName: "",
|
|
}
|
|
}
|
|
|
|
// Object-specific methods
|
|
|
|
// IsObject returns true (implements ObjectInterface)
|
|
func (o *Object) IsObject() bool {
|
|
return true
|
|
}
|
|
|
|
// IsClickable returns whether the object can be clicked
|
|
func (o *Object) IsClickable() bool {
|
|
o.mutex.RLock()
|
|
defer o.mutex.RUnlock()
|
|
return o.clickable
|
|
}
|
|
|
|
// SetClickable sets whether the object can be clicked
|
|
func (o *Object) SetClickable(clickable bool) {
|
|
o.mutex.Lock()
|
|
defer o.mutex.Unlock()
|
|
o.clickable = clickable
|
|
|
|
// Update appearance to show/hide command icon
|
|
if clickable {
|
|
o.GetAppearanceData().ShowCommandIcon = ObjectShowCommandIcon
|
|
} else {
|
|
o.GetAppearanceData().ShowCommandIcon = 0
|
|
}
|
|
}
|
|
|
|
// GetDeviceID returns the device ID
|
|
func (o *Object) GetDeviceID() int8 {
|
|
o.mutex.RLock()
|
|
defer o.mutex.RUnlock()
|
|
return o.deviceID
|
|
}
|
|
|
|
// SetDeviceID sets the device ID
|
|
func (o *Object) SetDeviceID(deviceID int8) {
|
|
o.mutex.Lock()
|
|
defer o.mutex.Unlock()
|
|
o.deviceID = deviceID
|
|
}
|
|
|
|
// Merchant methods
|
|
|
|
// GetMerchantID returns the merchant ID
|
|
func (o *Object) GetMerchantID() int32 {
|
|
o.mutex.RLock()
|
|
defer o.mutex.RUnlock()
|
|
return o.merchantID
|
|
}
|
|
|
|
// SetMerchantID sets the merchant ID
|
|
func (o *Object) SetMerchantID(merchantID int32) {
|
|
o.mutex.Lock()
|
|
defer o.mutex.Unlock()
|
|
o.merchantID = merchantID
|
|
}
|
|
|
|
// GetMerchantType returns the merchant type
|
|
func (o *Object) GetMerchantType() int8 {
|
|
o.mutex.RLock()
|
|
defer o.mutex.RUnlock()
|
|
return o.merchantType
|
|
}
|
|
|
|
// SetMerchantType sets the merchant type
|
|
func (o *Object) SetMerchantType(merchantType int8) {
|
|
o.mutex.Lock()
|
|
defer o.mutex.Unlock()
|
|
o.merchantType = merchantType
|
|
}
|
|
|
|
// IsMerchant returns whether this object is a merchant
|
|
func (o *Object) IsMerchant() bool {
|
|
o.mutex.RLock()
|
|
defer o.mutex.RUnlock()
|
|
return o.merchantID > 0
|
|
}
|
|
|
|
// IsCollector returns whether this object is a collector
|
|
func (o *Object) IsCollector() bool {
|
|
o.mutex.RLock()
|
|
defer o.mutex.RUnlock()
|
|
return o.isCollector
|
|
}
|
|
|
|
// SetCollector sets whether this object is a collector
|
|
func (o *Object) SetCollector(isCollector bool) {
|
|
o.mutex.Lock()
|
|
defer o.mutex.Unlock()
|
|
o.isCollector = isCollector
|
|
}
|
|
|
|
// Transport methods
|
|
|
|
// GetTransporterID returns the transporter ID
|
|
func (o *Object) GetTransporterID() int32 {
|
|
o.mutex.RLock()
|
|
defer o.mutex.RUnlock()
|
|
return o.transporterID
|
|
}
|
|
|
|
// SetTransporterID sets the transporter ID
|
|
func (o *Object) SetTransporterID(transporterID int32) {
|
|
o.mutex.Lock()
|
|
defer o.mutex.Unlock()
|
|
o.transporterID = transporterID
|
|
}
|
|
|
|
// IsTransporter returns whether this object is a transporter
|
|
func (o *Object) IsTransporter() bool {
|
|
o.mutex.RLock()
|
|
defer o.mutex.RUnlock()
|
|
return o.transporterID > 0
|
|
}
|
|
|
|
// Interaction methods
|
|
|
|
// GetInteractionType returns the type of interaction this object supports
|
|
func (o *Object) GetInteractionType() int {
|
|
o.mutex.RLock()
|
|
defer o.mutex.RUnlock()
|
|
|
|
if o.transporterID > 0 {
|
|
return InteractionTypeTransport
|
|
}
|
|
if o.deviceID > 0 {
|
|
return InteractionTypeDevice
|
|
}
|
|
if o.clickable {
|
|
return InteractionTypeCommand
|
|
}
|
|
return InteractionTypeNone
|
|
}
|
|
|
|
// CanInteract returns whether this object can be interacted with
|
|
func (o *Object) CanInteract() bool {
|
|
return o.GetInteractionType() != InteractionTypeNone
|
|
}
|
|
|
|
// Zone methods
|
|
|
|
// GetZone returns the zone name
|
|
func (o *Object) GetZone() string {
|
|
o.mutex.RLock()
|
|
defer o.mutex.RUnlock()
|
|
return o.zoneName
|
|
}
|
|
|
|
// SetZone sets the zone name
|
|
func (o *Object) SetZone(zoneName string) {
|
|
o.mutex.Lock()
|
|
defer o.mutex.Unlock()
|
|
o.zoneName = zoneName
|
|
}
|
|
|
|
// Utility methods
|
|
|
|
// GetObjectType returns a string describing the object type
|
|
func (o *Object) GetObjectType() string {
|
|
switch {
|
|
case o.IsTransporter():
|
|
return "Transport"
|
|
case o.IsMerchant():
|
|
return "Merchant"
|
|
case o.IsCollector():
|
|
return "Collector"
|
|
case o.GetDeviceID() > 0:
|
|
return "Device"
|
|
case o.IsClickable():
|
|
return "Interactive"
|
|
default:
|
|
return "Static"
|
|
}
|
|
}
|
|
|
|
// Validate checks if the object is properly configured
|
|
func (o *Object) Validate() error {
|
|
if o.Spawn == nil {
|
|
return fmt.Errorf("object must have spawn data")
|
|
}
|
|
|
|
if o.GetSpawnType() != ObjectSpawnType {
|
|
return fmt.Errorf("object must have spawn type %d", ObjectSpawnType)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Clone creates a copy of the object
|
|
func (o *Object) Clone() *Object {
|
|
o.mutex.RLock()
|
|
defer o.mutex.RUnlock()
|
|
|
|
newObject := &Object{
|
|
Spawn: o.Spawn, // Note: This is a shallow copy of the spawn
|
|
clickable: o.clickable,
|
|
deviceID: o.deviceID,
|
|
merchantID: o.merchantID,
|
|
merchantType: o.merchantType,
|
|
merchantMinLevel: o.merchantMinLevel,
|
|
merchantMaxLevel: o.merchantMaxLevel,
|
|
isCollector: o.isCollector,
|
|
transporterID: o.transporterID,
|
|
}
|
|
|
|
return newObject
|
|
}
|
|
|
|
// Factory functions for different object types
|
|
|
|
// CreateMerchantObject creates an object configured as a merchant
|
|
func CreateMerchantObject(merchantID int32, merchantType int8) *Object {
|
|
obj := NewObject()
|
|
obj.SetMerchantID(merchantID)
|
|
obj.SetMerchantType(merchantType)
|
|
obj.SetClickable(true)
|
|
return obj
|
|
}
|
|
|
|
// CreateTransportObject creates an object configured as a transporter
|
|
func CreateTransportObject(transporterID int32) *Object {
|
|
obj := NewObject()
|
|
obj.SetTransporterID(transporterID)
|
|
obj.SetClickable(true)
|
|
return obj
|
|
}
|
|
|
|
// CreateDeviceObject creates an object configured as a device
|
|
func CreateDeviceObject(deviceID int8) *Object {
|
|
obj := NewObject()
|
|
obj.SetDeviceID(deviceID)
|
|
obj.SetClickable(true)
|
|
return obj
|
|
}
|
|
|
|
// CreateCollectorObject creates an object configured as a collector
|
|
func CreateCollectorObject() *Object {
|
|
obj := NewObject()
|
|
obj.SetCollector(true)
|
|
obj.SetClickable(true)
|
|
return obj
|
|
}
|
|
|
|
// CreateStaticObject creates a non-interactive object
|
|
func CreateStaticObject() *Object {
|
|
obj := NewObject()
|
|
obj.SetClickable(false)
|
|
return obj
|
|
} |