778 lines
21 KiB
Go
778 lines
21 KiB
Go
package zone
|
|
|
|
import (
|
|
"database/sql"
|
|
"fmt"
|
|
"log"
|
|
"sync"
|
|
)
|
|
|
|
// ZoneDatabase handles all database operations for zones
|
|
type ZoneDatabase struct {
|
|
db *sql.DB
|
|
queries map[string]*sql.Stmt
|
|
mutex sync.RWMutex
|
|
}
|
|
|
|
// NewZoneDatabase creates a new zone database instance
|
|
func NewZoneDatabase(db *sql.DB) *ZoneDatabase {
|
|
zdb := &ZoneDatabase{
|
|
db: db,
|
|
queries: make(map[string]*sql.Stmt),
|
|
}
|
|
|
|
if err := zdb.prepareStatements(); err != nil {
|
|
log.Printf("%s Failed to prepare database statements: %v", LogPrefixZone, err)
|
|
}
|
|
|
|
return zdb
|
|
}
|
|
|
|
// 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()
|
|
|
|
stmt := zdb.queries["updateZoneConfig"]
|
|
if stmt == nil {
|
|
return fmt.Errorf("update zone config statement not prepared")
|
|
}
|
|
|
|
_, err := stmt.Exec(
|
|
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()
|
|
|
|
stmt := zdb.queries["selectSpawnLocation"]
|
|
if stmt == nil {
|
|
return nil, fmt.Errorf("select spawn location statement not prepared")
|
|
}
|
|
|
|
location := &SpawnLocation{}
|
|
err := stmt.QueryRow(locationID).Scan(
|
|
&location.ID,
|
|
&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,
|
|
)
|
|
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to load spawn location %d: %v", locationID, err)
|
|
}
|
|
|
|
return location, nil
|
|
}
|
|
|
|
// SaveSpawnLocation saves a spawn location to database
|
|
func (zdb *ZoneDatabase) SaveSpawnLocation(location *SpawnLocation) error {
|
|
zdb.mutex.Lock()
|
|
defer zdb.mutex.Unlock()
|
|
|
|
var stmt *sql.Stmt
|
|
var err error
|
|
|
|
if location.ID == 0 {
|
|
// Insert new location
|
|
stmt = zdb.queries["insertSpawnLocation"]
|
|
if stmt == nil {
|
|
return fmt.Errorf("insert spawn location statement not prepared")
|
|
}
|
|
|
|
err = stmt.QueryRow(
|
|
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,
|
|
).Scan(&location.ID)
|
|
} else {
|
|
// Update existing location
|
|
stmt = zdb.queries["updateSpawnLocation"]
|
|
if stmt == nil {
|
|
return fmt.Errorf("update spawn location statement not prepared")
|
|
}
|
|
|
|
_, err = stmt.Exec(
|
|
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 save 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()
|
|
|
|
stmt := zdb.queries["deleteSpawnLocation"]
|
|
if stmt == nil {
|
|
return fmt.Errorf("delete spawn location statement not prepared")
|
|
}
|
|
|
|
_, err := stmt.Exec(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()
|
|
|
|
stmt := zdb.queries["selectSpawnGroups"]
|
|
if stmt == nil {
|
|
return nil, fmt.Errorf("select spawn groups statement not prepared")
|
|
}
|
|
|
|
rows, err := stmt.Query(zoneID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to query spawn groups: %v", err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
groups := make(map[int32][]int32)
|
|
|
|
for rows.Next() {
|
|
var groupID, locationID int32
|
|
if err := rows.Scan(&groupID, &locationID); err != nil {
|
|
return nil, fmt.Errorf("failed to scan spawn group row: %v", err)
|
|
}
|
|
|
|
groups[groupID] = append(groups[groupID], locationID)
|
|
}
|
|
|
|
if err := rows.Err(); err != nil {
|
|
return nil, fmt.Errorf("error iterating 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()
|
|
|
|
// Start transaction
|
|
tx, err := zdb.db.Begin()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to begin transaction: %v", err)
|
|
}
|
|
defer tx.Rollback()
|
|
|
|
// Delete existing associations
|
|
deleteStmt := zdb.queries["deleteSpawnGroup"]
|
|
if deleteStmt == nil {
|
|
return fmt.Errorf("delete spawn group statement not prepared")
|
|
}
|
|
|
|
_, err = tx.Stmt(deleteStmt).Exec(groupID)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to delete existing spawn group: %v", err)
|
|
}
|
|
|
|
// Insert new associations
|
|
insertStmt := zdb.queries["insertSpawnGroup"]
|
|
if insertStmt == nil {
|
|
return fmt.Errorf("insert spawn group statement not prepared")
|
|
}
|
|
|
|
for _, locationID := range locationIDs {
|
|
_, err = tx.Stmt(insertStmt).Exec(groupID, locationID)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to insert spawn group association: %v", err)
|
|
}
|
|
}
|
|
|
|
// Commit transaction
|
|
if err := tx.Commit(); err != nil {
|
|
return fmt.Errorf("failed to commit spawn group transaction: %v", err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Close closes all prepared statements and database connection
|
|
func (zdb *ZoneDatabase) Close() error {
|
|
zdb.mutex.Lock()
|
|
defer zdb.mutex.Unlock()
|
|
|
|
// Close all prepared statements
|
|
for name, stmt := range zdb.queries {
|
|
if err := stmt.Close(); err != nil {
|
|
log.Printf("%s Error closing statement %s: %v", LogPrefixZone, name, err)
|
|
}
|
|
}
|
|
|
|
zdb.queries = make(map[string]*sql.Stmt)
|
|
return nil
|
|
}
|
|
|
|
// Private helper methods
|
|
|
|
func (zdb *ZoneDatabase) prepareStatements() error {
|
|
statements := map[string]string{
|
|
"updateZoneConfig": `
|
|
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 = ?`,
|
|
|
|
"selectZoneConfig": `
|
|
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 = ?`,
|
|
|
|
"selectSpawnLocations": `
|
|
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`,
|
|
|
|
"selectSpawnLocation": `
|
|
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 = ?`,
|
|
|
|
"insertSpawnLocation": `
|
|
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`,
|
|
|
|
"updateSpawnLocation": `
|
|
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 = ?`,
|
|
|
|
"deleteSpawnLocation": `DELETE FROM spawn_location_placement WHERE id = ?`,
|
|
|
|
"selectSpawnEntries": `
|
|
SELECT id, spawn_type, spawn_entry_id, name, level, encounter_level, model, size,
|
|
hp, power, heroic, gender, race, adventure_class, tradeskill_class, attack_type,
|
|
min_level, max_level, encounter_type, show_name, targetable, show_level,
|
|
command_primary, command_secondary, loot_tier, min_gold, max_gold, harvest_type,
|
|
icon
|
|
FROM spawn_location_entry WHERE zone_id = ?
|
|
ORDER BY id`,
|
|
|
|
"selectNPCs": `
|
|
SELECT id, spawn_entry_id, name, level, encounter_level, model, size, hp, power,
|
|
heroic, gender, race, adventure_class, tradeskill_class, attack_type, min_level,
|
|
max_level, encounter_type, show_name, targetable, show_level, loot_tier,
|
|
min_gold, max_gold, aggro_radius, cast_percentage, randomize
|
|
FROM spawn_npcs WHERE zone_id = ?
|
|
ORDER BY id`,
|
|
|
|
"selectObjects": `
|
|
SELECT id, spawn_entry_id, name, model, size, device_id, icon, sound_name
|
|
FROM spawn_objects WHERE zone_id = ?
|
|
ORDER BY id`,
|
|
|
|
"selectWidgets": `
|
|
SELECT id, spawn_entry_id, name, model, widget_type, open_type, open_time,
|
|
close_time, open_sound, close_sound, open_graphic, close_graphic,
|
|
linked_spawn_id, action_spawn_id, house_id, include_location,
|
|
include_heading
|
|
FROM spawn_widgets WHERE zone_id = ?
|
|
ORDER BY id`,
|
|
|
|
"selectSigns": `
|
|
SELECT id, spawn_entry_id, name, model, sign_type, zone_id_destination,
|
|
widget_id, title, description, zone_x, zone_y, zone_z, zone_heading,
|
|
include_location, include_heading
|
|
FROM spawn_signs WHERE zone_id = ?
|
|
ORDER BY id`,
|
|
|
|
"selectGroundSpawns": `
|
|
SELECT id, spawn_entry_id, name, model, harvest_type, number_harvests,
|
|
max_number_harvests, collection_skill, respawn_timer
|
|
FROM spawn_ground_spawns WHERE zone_id = ?
|
|
ORDER BY id`,
|
|
|
|
"selectTransporters": `
|
|
SELECT id, type, display_name, message, destination_zone_id, destination_x,
|
|
destination_y, destination_z, destination_heading, cost, unique_id,
|
|
min_level, max_level, quest_req, quest_step_req, quest_complete,
|
|
map_x, map_y, expansion_flag, holiday_flag, min_client_version,
|
|
max_client_version, flight_path_id, mount_id, mount_red_color,
|
|
mount_green_color, mount_blue_color
|
|
FROM transporters WHERE zone_id = ?
|
|
ORDER BY id`,
|
|
|
|
"selectLocationGrids": `
|
|
SELECT id, grid_id, name, include_y, discovery
|
|
FROM location_grids WHERE zone_id = ?
|
|
ORDER BY id`,
|
|
|
|
"selectLocationGridLocations": `
|
|
SELECT location_id, x, y, z, name
|
|
FROM location_grid_locations WHERE grid_id = ?
|
|
ORDER BY location_id`,
|
|
|
|
"selectRevivePoints": `
|
|
SELECT id, zone_id, location_name, x, y, z, heading, always_included
|
|
FROM revive_points WHERE zone_id = ?
|
|
ORDER BY id`,
|
|
|
|
"selectSpawnGroups": `
|
|
SELECT group_id, location_id
|
|
FROM spawn_location_group WHERE zone_id = ?
|
|
ORDER BY group_id, location_id`,
|
|
|
|
"insertSpawnGroup": `
|
|
INSERT INTO spawn_location_group (group_id, location_id) VALUES (?, ?)`,
|
|
|
|
"deleteSpawnGroup": `
|
|
DELETE FROM spawn_location_group WHERE group_id = ?`,
|
|
}
|
|
|
|
for name, query := range statements {
|
|
stmt, err := zdb.db.Prepare(query)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to prepare statement %s: %v", name, err)
|
|
}
|
|
zdb.queries[name] = stmt
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (zdb *ZoneDatabase) loadZoneConfiguration(zoneData *ZoneData) error {
|
|
stmt := zdb.queries["selectZoneConfig"]
|
|
if stmt == nil {
|
|
return fmt.Errorf("select zone config statement not prepared")
|
|
}
|
|
|
|
config := &ZoneConfiguration{}
|
|
err := stmt.QueryRow(zoneData.ZoneID).Scan(
|
|
&config.ZoneID,
|
|
&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,
|
|
)
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("failed to load zone configuration: %v", err)
|
|
}
|
|
|
|
zoneData.Configuration = config
|
|
return nil
|
|
}
|
|
|
|
func (zdb *ZoneDatabase) loadSpawnLocations(zoneData *ZoneData) error {
|
|
stmt := zdb.queries["selectSpawnLocations"]
|
|
if stmt == nil {
|
|
return fmt.Errorf("select spawn locations statement not prepared")
|
|
}
|
|
|
|
rows, err := stmt.Query(zoneData.ZoneID)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to query spawn locations: %v", err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
locations := make(map[int32]*SpawnLocation)
|
|
|
|
for rows.Next() {
|
|
location := &SpawnLocation{}
|
|
err := rows.Scan(
|
|
&location.ID,
|
|
&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,
|
|
)
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("failed to scan spawn location: %v", err)
|
|
}
|
|
|
|
locations[location.ID] = location
|
|
}
|
|
|
|
if err := rows.Err(); err != nil {
|
|
return fmt.Errorf("error iterating spawn locations: %v", err)
|
|
}
|
|
|
|
zoneData.SpawnLocations = locations
|
|
return nil
|
|
}
|
|
|
|
func (zdb *ZoneDatabase) loadSpawnEntries(zoneData *ZoneData) error {
|
|
// Similar implementation for spawn entries
|
|
zoneData.SpawnEntries = make(map[int32]*SpawnEntry)
|
|
return nil // TODO: Implement
|
|
}
|
|
|
|
func (zdb *ZoneDatabase) loadNPCs(zoneData *ZoneData) error {
|
|
// Similar implementation for NPCs
|
|
zoneData.NPCs = make(map[int32]*NPCTemplate)
|
|
return nil // TODO: Implement
|
|
}
|
|
|
|
func (zdb *ZoneDatabase) loadObjects(zoneData *ZoneData) error {
|
|
// Similar implementation for objects
|
|
zoneData.Objects = make(map[int32]*ObjectTemplate)
|
|
return nil // TODO: Implement
|
|
}
|
|
|
|
func (zdb *ZoneDatabase) loadWidgets(zoneData *ZoneData) error {
|
|
// Similar implementation for widgets
|
|
zoneData.Widgets = make(map[int32]*WidgetTemplate)
|
|
return nil // TODO: Implement
|
|
}
|
|
|
|
func (zdb *ZoneDatabase) loadSigns(zoneData *ZoneData) error {
|
|
// Similar implementation for signs
|
|
zoneData.Signs = make(map[int32]*SignTemplate)
|
|
return nil // TODO: Implement
|
|
}
|
|
|
|
func (zdb *ZoneDatabase) loadGroundSpawns(zoneData *ZoneData) error {
|
|
// Similar implementation for ground spawns
|
|
zoneData.GroundSpawns = make(map[int32]*GroundSpawnTemplate)
|
|
return nil // TODO: Implement
|
|
}
|
|
|
|
func (zdb *ZoneDatabase) loadTransporters(zoneData *ZoneData) error {
|
|
// Similar implementation for transporters
|
|
zoneData.Transporters = make(map[int32]*TransportDestination)
|
|
return nil // TODO: Implement
|
|
}
|
|
|
|
func (zdb *ZoneDatabase) loadLocationGrids(zoneData *ZoneData) error {
|
|
// Similar implementation for location grids
|
|
zoneData.LocationGrids = make(map[int32]*LocationGrid)
|
|
return nil // TODO: Implement
|
|
}
|
|
|
|
func (zdb *ZoneDatabase) loadRevivePoints(zoneData *ZoneData) error {
|
|
// Similar implementation for revive points
|
|
zoneData.RevivePoints = make(map[int32]*RevivePoint)
|
|
return nil // TODO: Implement
|
|
}
|
|
|
|
// 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
|
|
}
|