634 lines
18 KiB
Go
634 lines
18 KiB
Go
package zone
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"sync"
|
|
|
|
"zombiezen.com/go/sqlite"
|
|
"zombiezen.com/go/sqlite/sqlitex"
|
|
)
|
|
|
|
// ZoneDatabase handles all database operations for zones
|
|
type ZoneDatabase struct {
|
|
conn *sqlite.Conn
|
|
mutex sync.RWMutex
|
|
}
|
|
|
|
// NewZoneDatabase creates a new zone database instance
|
|
func NewZoneDatabase(conn *sqlite.Conn) *ZoneDatabase {
|
|
return &ZoneDatabase{
|
|
conn: conn,
|
|
}
|
|
}
|
|
|
|
// LoadZoneData loads all zone configuration and spawn data
|
|
func (zdb *ZoneDatabase) LoadZoneData(zoneID int32) (*ZoneData, error) {
|
|
zoneData := &ZoneData{
|
|
ZoneID: zoneID,
|
|
}
|
|
|
|
// Load zone configuration
|
|
if err := zdb.loadZoneConfiguration(zoneData); err != nil {
|
|
return nil, fmt.Errorf("failed to load zone configuration: %v", err)
|
|
}
|
|
|
|
// Load spawn locations
|
|
if err := zdb.loadSpawnLocations(zoneData); err != nil {
|
|
return nil, fmt.Errorf("failed to load spawn locations: %v", err)
|
|
}
|
|
|
|
// Load spawn entries
|
|
if err := zdb.loadSpawnEntries(zoneData); err != nil {
|
|
return nil, fmt.Errorf("failed to load spawn entries: %v", err)
|
|
}
|
|
|
|
// Load NPCs
|
|
if err := zdb.loadNPCs(zoneData); err != nil {
|
|
return nil, fmt.Errorf("failed to load NPCs: %v", err)
|
|
}
|
|
|
|
// Load objects
|
|
if err := zdb.loadObjects(zoneData); err != nil {
|
|
return nil, fmt.Errorf("failed to load objects: %v", err)
|
|
}
|
|
|
|
// Load widgets
|
|
if err := zdb.loadWidgets(zoneData); err != nil {
|
|
return nil, fmt.Errorf("failed to load widgets: %v", err)
|
|
}
|
|
|
|
// Load signs
|
|
if err := zdb.loadSigns(zoneData); err != nil {
|
|
return nil, fmt.Errorf("failed to load signs: %v", err)
|
|
}
|
|
|
|
// Load ground spawns
|
|
if err := zdb.loadGroundSpawns(zoneData); err != nil {
|
|
return nil, fmt.Errorf("failed to load ground spawns: %v", err)
|
|
}
|
|
|
|
// Load transporters
|
|
if err := zdb.loadTransporters(zoneData); err != nil {
|
|
return nil, fmt.Errorf("failed to load transporters: %v", err)
|
|
}
|
|
|
|
// Load location grids
|
|
if err := zdb.loadLocationGrids(zoneData); err != nil {
|
|
return nil, fmt.Errorf("failed to load location grids: %v", err)
|
|
}
|
|
|
|
// Load revive points
|
|
if err := zdb.loadRevivePoints(zoneData); err != nil {
|
|
return nil, fmt.Errorf("failed to load revive points: %v", err)
|
|
}
|
|
|
|
log.Printf("%s Loaded zone data for zone %d", LogPrefixZone, zoneID)
|
|
return zoneData, nil
|
|
}
|
|
|
|
// SaveZoneConfiguration saves zone configuration to database
|
|
func (zdb *ZoneDatabase) SaveZoneConfiguration(config *ZoneConfiguration) error {
|
|
zdb.mutex.Lock()
|
|
defer zdb.mutex.Unlock()
|
|
|
|
query := `UPDATE zones SET
|
|
name = ?, file = ?, description = ?, safe_x = ?, safe_y = ?, safe_z = ?,
|
|
safe_heading = ?, underworld = ?, min_level = ?, max_level = ?, min_status = ?,
|
|
min_version = ?, instance_type = ?, max_players = ?, default_lockout_time = ?,
|
|
default_reenter_time = ?, default_reset_time = ?, group_zone_option = ?,
|
|
expansion_flag = ?, holiday_flag = ?, can_bind = ?, can_gate = ?, can_evac = ?,
|
|
city_zone = ?, always_loaded = ?, weather_allowed = ?
|
|
WHERE id = ?`
|
|
|
|
err := sqlitex.Execute(zdb.conn, query, &sqlitex.ExecOptions{
|
|
Args: []any{
|
|
config.Name,
|
|
config.File,
|
|
config.Description,
|
|
config.SafeX,
|
|
config.SafeY,
|
|
config.SafeZ,
|
|
config.SafeHeading,
|
|
config.Underworld,
|
|
config.MinLevel,
|
|
config.MaxLevel,
|
|
config.MinStatus,
|
|
config.MinVersion,
|
|
config.InstanceType,
|
|
config.MaxPlayers,
|
|
config.DefaultLockoutTime,
|
|
config.DefaultReenterTime,
|
|
config.DefaultResetTime,
|
|
config.GroupZoneOption,
|
|
config.ExpansionFlag,
|
|
config.HolidayFlag,
|
|
config.CanBind,
|
|
config.CanGate,
|
|
config.CanEvac,
|
|
config.CityZone,
|
|
config.AlwaysLoaded,
|
|
config.WeatherAllowed,
|
|
config.ZoneID,
|
|
},
|
|
})
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("failed to save zone configuration: %v", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// LoadSpawnLocation loads a specific spawn location
|
|
func (zdb *ZoneDatabase) LoadSpawnLocation(locationID int32) (*SpawnLocation, error) {
|
|
zdb.mutex.RLock()
|
|
defer zdb.mutex.RUnlock()
|
|
|
|
query := `SELECT id, x, y, z, heading, pitch, roll, spawn_type, respawn_time, expire_time,
|
|
expire_offset, conditions, conditional_value, spawn_percentage
|
|
FROM spawn_location_placement WHERE id = ?`
|
|
|
|
location := &SpawnLocation{}
|
|
err := sqlitex.Execute(zdb.conn, query, &sqlitex.ExecOptions{
|
|
Args: []any{locationID},
|
|
ResultFunc: func(stmt *sqlite.Stmt) error {
|
|
location.ID = int32(stmt.ColumnInt64(0))
|
|
location.X = float32(stmt.ColumnFloat(1))
|
|
location.Y = float32(stmt.ColumnFloat(2))
|
|
location.Z = float32(stmt.ColumnFloat(3))
|
|
location.Heading = float32(stmt.ColumnFloat(4))
|
|
location.Pitch = float32(stmt.ColumnFloat(5))
|
|
location.Roll = float32(stmt.ColumnFloat(6))
|
|
location.SpawnType = int8(stmt.ColumnInt64(7))
|
|
location.RespawnTime = int32(stmt.ColumnInt64(8))
|
|
location.ExpireTime = int32(stmt.ColumnInt64(9))
|
|
location.ExpireOffset = int32(stmt.ColumnInt64(10))
|
|
location.Conditions = int8(stmt.ColumnInt64(11))
|
|
location.ConditionalValue = int32(stmt.ColumnInt64(12))
|
|
location.SpawnPercentage = float32(stmt.ColumnFloat(13))
|
|
return nil
|
|
},
|
|
})
|
|
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to load spawn location %d: %v", locationID, err)
|
|
}
|
|
|
|
if location.ID == 0 {
|
|
return nil, fmt.Errorf("spawn location %d not found", locationID)
|
|
}
|
|
|
|
return location, nil
|
|
}
|
|
|
|
// SaveSpawnLocation saves a spawn location to database
|
|
func (zdb *ZoneDatabase) SaveSpawnLocation(location *SpawnLocation) error {
|
|
zdb.mutex.Lock()
|
|
defer zdb.mutex.Unlock()
|
|
|
|
if location.ID == 0 {
|
|
// Insert new location
|
|
query := `INSERT INTO spawn_location_placement
|
|
(x, y, z, heading, pitch, roll, spawn_type, respawn_time, expire_time,
|
|
expire_offset, conditions, conditional_value, spawn_percentage)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
RETURNING id`
|
|
|
|
err := sqlitex.Execute(zdb.conn, query, &sqlitex.ExecOptions{
|
|
Args: []any{
|
|
location.X,
|
|
location.Y,
|
|
location.Z,
|
|
location.Heading,
|
|
location.Pitch,
|
|
location.Roll,
|
|
location.SpawnType,
|
|
location.RespawnTime,
|
|
location.ExpireTime,
|
|
location.ExpireOffset,
|
|
location.Conditions,
|
|
location.ConditionalValue,
|
|
location.SpawnPercentage,
|
|
},
|
|
ResultFunc: func(stmt *sqlite.Stmt) error {
|
|
location.ID = int32(stmt.ColumnInt64(0))
|
|
return nil
|
|
},
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("failed to insert spawn location: %v", err)
|
|
}
|
|
} else {
|
|
// Update existing location
|
|
query := `UPDATE spawn_location_placement SET
|
|
x = ?, y = ?, z = ?, heading = ?, pitch = ?, roll = ?, spawn_type = ?,
|
|
respawn_time = ?, expire_time = ?, expire_offset = ?, conditions = ?,
|
|
conditional_value = ?, spawn_percentage = ?
|
|
WHERE id = ?`
|
|
|
|
err := sqlitex.Execute(zdb.conn, query, &sqlitex.ExecOptions{
|
|
Args: []any{
|
|
location.X,
|
|
location.Y,
|
|
location.Z,
|
|
location.Heading,
|
|
location.Pitch,
|
|
location.Roll,
|
|
location.SpawnType,
|
|
location.RespawnTime,
|
|
location.ExpireTime,
|
|
location.ExpireOffset,
|
|
location.Conditions,
|
|
location.ConditionalValue,
|
|
location.SpawnPercentage,
|
|
location.ID,
|
|
},
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("failed to update spawn location: %v", err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// DeleteSpawnLocation deletes a spawn location from database
|
|
func (zdb *ZoneDatabase) DeleteSpawnLocation(locationID int32) error {
|
|
zdb.mutex.Lock()
|
|
defer zdb.mutex.Unlock()
|
|
|
|
query := `DELETE FROM spawn_location_placement WHERE id = ?`
|
|
err := sqlitex.Execute(zdb.conn, query, &sqlitex.ExecOptions{
|
|
Args: []any{locationID},
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("failed to delete spawn location %d: %v", locationID, err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// LoadSpawnGroups loads spawn group associations for a zone
|
|
func (zdb *ZoneDatabase) LoadSpawnGroups(zoneID int32) (map[int32][]int32, error) {
|
|
zdb.mutex.RLock()
|
|
defer zdb.mutex.RUnlock()
|
|
|
|
query := `SELECT group_id, location_id
|
|
FROM spawn_location_group WHERE zone_id = ?
|
|
ORDER BY group_id, location_id`
|
|
|
|
groups := make(map[int32][]int32)
|
|
err := sqlitex.Execute(zdb.conn, query, &sqlitex.ExecOptions{
|
|
Args: []any{zoneID},
|
|
ResultFunc: func(stmt *sqlite.Stmt) error {
|
|
groupID := int32(stmt.ColumnInt64(0))
|
|
locationID := int32(stmt.ColumnInt64(1))
|
|
groups[groupID] = append(groups[groupID], locationID)
|
|
return nil
|
|
},
|
|
})
|
|
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to load spawn groups: %v", err)
|
|
}
|
|
|
|
return groups, nil
|
|
}
|
|
|
|
// SaveSpawnGroup saves spawn group associations
|
|
func (zdb *ZoneDatabase) SaveSpawnGroup(groupID int32, locationIDs []int32) error {
|
|
zdb.mutex.Lock()
|
|
defer zdb.mutex.Unlock()
|
|
|
|
// Use transaction for atomic operations
|
|
endFn, err := sqlitex.ImmediateTransaction(zdb.conn)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to start transaction: %v", err)
|
|
}
|
|
defer endFn(&err)
|
|
|
|
// Delete existing associations
|
|
deleteQuery := `DELETE FROM spawn_location_group WHERE group_id = ?`
|
|
err = sqlitex.Execute(zdb.conn, deleteQuery, &sqlitex.ExecOptions{
|
|
Args: []any{groupID},
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("failed to delete existing spawn group: %v", err)
|
|
}
|
|
|
|
// Insert new associations
|
|
insertQuery := `INSERT INTO spawn_location_group (group_id, location_id) VALUES (?, ?)`
|
|
for _, locationID := range locationIDs {
|
|
err = sqlitex.Execute(zdb.conn, insertQuery, &sqlitex.ExecOptions{
|
|
Args: []any{groupID, locationID},
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("failed to insert spawn group association: %v", err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Close closes the database connection
|
|
func (zdb *ZoneDatabase) Close() error {
|
|
return nil // Connection is managed externally
|
|
}
|
|
|
|
// Private helper methods
|
|
|
|
func (zdb *ZoneDatabase) loadZoneConfiguration(zoneData *ZoneData) error {
|
|
query := `SELECT id, name, file, description, safe_x, safe_y, safe_z, safe_heading, underworld,
|
|
min_level, max_level, min_status, min_version, instance_type, max_players,
|
|
default_lockout_time, default_reenter_time, default_reset_time, group_zone_option,
|
|
expansion_flag, holiday_flag, can_bind, can_gate, can_evac, city_zone, always_loaded,
|
|
weather_allowed
|
|
FROM zones WHERE id = ?`
|
|
|
|
config := &ZoneConfiguration{}
|
|
found := false
|
|
|
|
err := sqlitex.Execute(zdb.conn, query, &sqlitex.ExecOptions{
|
|
Args: []any{zoneData.ZoneID},
|
|
ResultFunc: func(stmt *sqlite.Stmt) error {
|
|
found = true
|
|
config.ZoneID = int32(stmt.ColumnInt64(0))
|
|
config.Name = stmt.ColumnText(1)
|
|
config.File = stmt.ColumnText(2)
|
|
config.Description = stmt.ColumnText(3)
|
|
config.SafeX = float32(stmt.ColumnFloat(4))
|
|
config.SafeY = float32(stmt.ColumnFloat(5))
|
|
config.SafeZ = float32(stmt.ColumnFloat(6))
|
|
config.SafeHeading = float32(stmt.ColumnFloat(7))
|
|
config.Underworld = float32(stmt.ColumnFloat(8))
|
|
config.MinLevel = int16(stmt.ColumnInt64(9))
|
|
config.MaxLevel = int16(stmt.ColumnInt64(10))
|
|
config.MinStatus = int16(stmt.ColumnInt64(11))
|
|
config.MinVersion = int16(stmt.ColumnInt64(12))
|
|
config.InstanceType = int16(stmt.ColumnInt64(13))
|
|
config.MaxPlayers = int32(stmt.ColumnInt64(14))
|
|
config.DefaultLockoutTime = int32(stmt.ColumnInt64(15))
|
|
config.DefaultReenterTime = int32(stmt.ColumnInt64(16))
|
|
config.DefaultResetTime = int32(stmt.ColumnInt64(17))
|
|
config.GroupZoneOption = int8(stmt.ColumnInt64(18))
|
|
config.ExpansionFlag = int32(stmt.ColumnInt64(19))
|
|
config.HolidayFlag = int32(stmt.ColumnInt64(20))
|
|
config.CanBind = stmt.ColumnInt64(21) != 0
|
|
config.CanGate = stmt.ColumnInt64(22) != 0
|
|
config.CanEvac = stmt.ColumnInt64(23) != 0
|
|
config.CityZone = stmt.ColumnInt64(24) != 0
|
|
config.AlwaysLoaded = stmt.ColumnInt64(25) != 0
|
|
config.WeatherAllowed = stmt.ColumnInt64(26) != 0
|
|
return nil
|
|
},
|
|
})
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("failed to load zone configuration: %v", err)
|
|
}
|
|
|
|
if !found {
|
|
return fmt.Errorf("zone configuration not found for zone %d", zoneData.ZoneID)
|
|
}
|
|
|
|
zoneData.Configuration = config
|
|
return nil
|
|
}
|
|
|
|
func (zdb *ZoneDatabase) loadSpawnLocations(zoneData *ZoneData) error {
|
|
query := `SELECT id, x, y, z, heading, pitch, roll, spawn_type, respawn_time, expire_time,
|
|
expire_offset, conditions, conditional_value, spawn_percentage
|
|
FROM spawn_location_placement WHERE zone_id = ?
|
|
ORDER BY id`
|
|
|
|
locations := make(map[int32]*SpawnLocation)
|
|
err := sqlitex.Execute(zdb.conn, query, &sqlitex.ExecOptions{
|
|
Args: []any{zoneData.ZoneID},
|
|
ResultFunc: func(stmt *sqlite.Stmt) error {
|
|
location := &SpawnLocation{
|
|
ID: int32(stmt.ColumnInt64(0)),
|
|
X: float32(stmt.ColumnFloat(1)),
|
|
Y: float32(stmt.ColumnFloat(2)),
|
|
Z: float32(stmt.ColumnFloat(3)),
|
|
Heading: float32(stmt.ColumnFloat(4)),
|
|
Pitch: float32(stmt.ColumnFloat(5)),
|
|
Roll: float32(stmt.ColumnFloat(6)),
|
|
SpawnType: int8(stmt.ColumnInt64(7)),
|
|
RespawnTime: int32(stmt.ColumnInt64(8)),
|
|
ExpireTime: int32(stmt.ColumnInt64(9)),
|
|
ExpireOffset: int32(stmt.ColumnInt64(10)),
|
|
Conditions: int8(stmt.ColumnInt64(11)),
|
|
ConditionalValue: int32(stmt.ColumnInt64(12)),
|
|
SpawnPercentage: float32(stmt.ColumnFloat(13)),
|
|
}
|
|
locations[location.ID] = location
|
|
return nil
|
|
},
|
|
})
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("failed to load spawn locations: %v", err)
|
|
}
|
|
|
|
zoneData.SpawnLocations = locations
|
|
return nil
|
|
}
|
|
|
|
func (zdb *ZoneDatabase) loadSpawnEntries(zoneData *ZoneData) error {
|
|
// Placeholder implementation - initialize empty map
|
|
zoneData.SpawnEntries = make(map[int32]*SpawnEntry)
|
|
return nil
|
|
}
|
|
|
|
func (zdb *ZoneDatabase) loadNPCs(zoneData *ZoneData) error {
|
|
// Placeholder implementation - initialize empty map
|
|
zoneData.NPCs = make(map[int32]*NPCTemplate)
|
|
return nil
|
|
}
|
|
|
|
func (zdb *ZoneDatabase) loadObjects(zoneData *ZoneData) error {
|
|
// Placeholder implementation - initialize empty map
|
|
zoneData.Objects = make(map[int32]*ObjectTemplate)
|
|
return nil
|
|
}
|
|
|
|
func (zdb *ZoneDatabase) loadWidgets(zoneData *ZoneData) error {
|
|
// Placeholder implementation - initialize empty map
|
|
zoneData.Widgets = make(map[int32]*WidgetTemplate)
|
|
return nil
|
|
}
|
|
|
|
func (zdb *ZoneDatabase) loadSigns(zoneData *ZoneData) error {
|
|
// Placeholder implementation - initialize empty map
|
|
zoneData.Signs = make(map[int32]*SignTemplate)
|
|
return nil
|
|
}
|
|
|
|
func (zdb *ZoneDatabase) loadGroundSpawns(zoneData *ZoneData) error {
|
|
// Placeholder implementation - initialize empty map
|
|
zoneData.GroundSpawns = make(map[int32]*GroundSpawnTemplate)
|
|
return nil
|
|
}
|
|
|
|
func (zdb *ZoneDatabase) loadTransporters(zoneData *ZoneData) error {
|
|
// Placeholder implementation - initialize empty map
|
|
zoneData.Transporters = make(map[int32]*TransportDestination)
|
|
return nil
|
|
}
|
|
|
|
func (zdb *ZoneDatabase) loadLocationGrids(zoneData *ZoneData) error {
|
|
// Placeholder implementation - initialize empty map
|
|
zoneData.LocationGrids = make(map[int32]*LocationGrid)
|
|
return nil
|
|
}
|
|
|
|
func (zdb *ZoneDatabase) loadRevivePoints(zoneData *ZoneData) error {
|
|
// Placeholder implementation - initialize empty map
|
|
zoneData.RevivePoints = make(map[int32]*RevivePoint)
|
|
return nil
|
|
}
|
|
|
|
// ZoneData represents all data loaded for a zone
|
|
type ZoneData struct {
|
|
ZoneID int32
|
|
Configuration *ZoneConfiguration
|
|
SpawnLocations map[int32]*SpawnLocation
|
|
SpawnEntries map[int32]*SpawnEntry
|
|
NPCs map[int32]*NPCTemplate
|
|
Objects map[int32]*ObjectTemplate
|
|
Widgets map[int32]*WidgetTemplate
|
|
Signs map[int32]*SignTemplate
|
|
GroundSpawns map[int32]*GroundSpawnTemplate
|
|
Transporters map[int32]*TransportDestination
|
|
LocationGrids map[int32]*LocationGrid
|
|
RevivePoints map[int32]*RevivePoint
|
|
SpawnGroups map[int32][]int32
|
|
}
|
|
|
|
// ZoneConfiguration represents zone configuration from database
|
|
type ZoneConfiguration struct {
|
|
ZoneID int32
|
|
Name string
|
|
File string
|
|
Description string
|
|
SafeX float32
|
|
SafeY float32
|
|
SafeZ float32
|
|
SafeHeading float32
|
|
Underworld float32
|
|
MinLevel int16
|
|
MaxLevel int16
|
|
MinStatus int16
|
|
MinVersion int16
|
|
InstanceType int16
|
|
MaxPlayers int32
|
|
DefaultLockoutTime int32
|
|
DefaultReenterTime int32
|
|
DefaultResetTime int32
|
|
GroupZoneOption int8
|
|
ExpansionFlag int32
|
|
HolidayFlag int32
|
|
CanBind bool
|
|
CanGate bool
|
|
CanEvac bool
|
|
CityZone bool
|
|
AlwaysLoaded bool
|
|
WeatherAllowed bool
|
|
}
|
|
|
|
// Template types for database-loaded spawn data
|
|
type NPCTemplate struct {
|
|
ID int32
|
|
SpawnEntryID int32
|
|
Name string
|
|
Level int16
|
|
EncounterLevel int16
|
|
Model string
|
|
Size float32
|
|
HP int32
|
|
Power int32
|
|
Heroic int8
|
|
Gender int8
|
|
Race int16
|
|
AdventureClass int16
|
|
TradeskillClass int16
|
|
AttackType int8
|
|
MinLevel int16
|
|
MaxLevel int16
|
|
EncounterType int8
|
|
ShowName int8
|
|
Targetable int8
|
|
ShowLevel int8
|
|
LootTier int8
|
|
MinGold int32
|
|
MaxGold int32
|
|
AggroRadius float32
|
|
CastPercentage int8
|
|
Randomize bool
|
|
}
|
|
|
|
type ObjectTemplate struct {
|
|
ID int32
|
|
SpawnEntryID int32
|
|
Name string
|
|
Model string
|
|
Size float32
|
|
DeviceID int32
|
|
Icon int32
|
|
SoundName string
|
|
}
|
|
|
|
type WidgetTemplate struct {
|
|
ID int32
|
|
SpawnEntryID int32
|
|
Name string
|
|
Model string
|
|
WidgetType int8
|
|
OpenType int8
|
|
OpenTime int32
|
|
CloseTime int32
|
|
OpenSound string
|
|
CloseSound string
|
|
OpenGraphic string
|
|
CloseGraphic string
|
|
LinkedSpawnID int32
|
|
ActionSpawnID int32
|
|
HouseID int32
|
|
IncludeLocation bool
|
|
IncludeHeading bool
|
|
}
|
|
|
|
type SignTemplate struct {
|
|
ID int32
|
|
SpawnEntryID int32
|
|
Name string
|
|
Model string
|
|
SignType int8
|
|
ZoneIDDestination int32
|
|
WidgetID int32
|
|
Title string
|
|
Description string
|
|
ZoneX float32
|
|
ZoneY float32
|
|
ZoneZ float32
|
|
ZoneHeading float32
|
|
IncludeLocation bool
|
|
IncludeHeading bool
|
|
}
|
|
|
|
type GroundSpawnTemplate struct {
|
|
ID int32
|
|
SpawnEntryID int32
|
|
Name string
|
|
Model string
|
|
HarvestType string
|
|
NumberHarvests int8
|
|
MaxNumberHarvests int8
|
|
CollectionSkill string
|
|
RespawnTimer int32
|
|
}
|
|
|
|
// Types are already defined in interfaces.go
|
|
|
|
// All types are defined in interfaces.go |