mirror of
https://github.com/therealKyp/Earth-and-Beyond-server
synced 2026-08-13 22:23:03 -04:00
541 lines
18 KiB
C++
541 lines
18 KiB
C++
// StationLoader.cpp
|
|
|
|
#include "Net7.h"
|
|
#include "StationLoader.h"
|
|
#include "mysql/mysqlplus.h"
|
|
#include "StringManager.h"
|
|
#include "TalkTreeParser.h"
|
|
#include "ServerManager.h"
|
|
|
|
StationLoader::StationLoader()
|
|
{
|
|
m_NPCList.clear(); // clear all npc's
|
|
m_StationList.clear(); // clear all entries
|
|
m_RoomList.clear();
|
|
m_TermList.clear();
|
|
|
|
m_TalkTreeBufferLen = 16384;
|
|
m_TalkTreeBuffer = new char[m_TalkTreeBufferLen];
|
|
}
|
|
|
|
StationLoader::~StationLoader()
|
|
{
|
|
// TODO: destroy everything
|
|
delete[] m_TalkTreeBuffer;
|
|
}
|
|
|
|
int StationLoader::GetStationSectorID(int ObjectID)
|
|
{
|
|
char queryString[3048];
|
|
sql_connection_c connection("net7", g_MySQL_Host, g_MySQL_User, g_MySQL_Pass);
|
|
sql_query_c stnSectorID( &connection );
|
|
sql_result_c Station_result;
|
|
|
|
sprintf(queryString, "SELECT `gate_to` FROM `sector_objects` WHERE `sector_objects`.`sector_object_id` = '%d'", ObjectID);
|
|
|
|
if ( !stnSectorID.execute( queryString ) )
|
|
{
|
|
printf("\n");
|
|
LogMessage( "MySQL Login error/Database error: (User: %s Pass: %s)\n", g_MySQL_User, g_MySQL_Pass );
|
|
exit(1);
|
|
return 0;
|
|
}
|
|
|
|
stnSectorID.store(&Station_result);
|
|
|
|
if (!Station_result.n_rows())
|
|
return -1;
|
|
|
|
sql_row_c StationData;
|
|
Station_result.fetch_row(&StationData); // Read in first row
|
|
|
|
return (int)StationData["gate_to"];
|
|
|
|
}
|
|
|
|
bool StationLoader::LoadStations()
|
|
{
|
|
bool success = false;
|
|
char queryString[3048];
|
|
StationTemplate *current_station = NULL;
|
|
int StationCount = 0;
|
|
int StationsinDB = 0;
|
|
|
|
if(!g_MySQL_User || !g_MySQL_Pass)
|
|
{
|
|
LogMessage("You need to set a mysql user/pass in the net7.cfg\n");
|
|
return 0;
|
|
}
|
|
|
|
sql_connection_c connection("net7", g_MySQL_Host, g_MySQL_User, g_MySQL_Pass);
|
|
sql_query_c stnStations( &connection );
|
|
sql_result_c Station_result;
|
|
|
|
LogMessage("Loading Stations from SQL");
|
|
|
|
#ifdef DEV_QUICK_START
|
|
//sprintf(queryString, "SELECT * FROM `starbases` WHERE `sector_id` = "); //can use this for remote SP testing to speed up loading (load only Jove's Fury)
|
|
int limit = 12;
|
|
#endif
|
|
|
|
sprintf(queryString, "SELECT * FROM `starbases`");
|
|
|
|
if ( !stnStations.execute( queryString ) )
|
|
{
|
|
printf("\n");
|
|
LogMessage( "MySQL Login error/Database error: (User: %s Pass: %s)\n", g_MySQL_User, g_MySQL_Pass );
|
|
exit(1);
|
|
return 0;
|
|
}
|
|
|
|
stnStations.store(&Station_result);
|
|
|
|
if (!Station_result.n_rows())
|
|
return 0;
|
|
|
|
StationsinDB = (int)Station_result.n_rows();
|
|
|
|
#ifdef DEV_QUICK_START
|
|
StationsinDB = 13;
|
|
#endif
|
|
|
|
//printf("Loading Stations from SQL (%d)...\n", (int)Station_result->n_rows());
|
|
|
|
sql_row_c StationData;
|
|
bool new_station;
|
|
for(int x=0;x<StationsinDB;x++)
|
|
{
|
|
new_station = false;
|
|
Station_result.fetch_row(&StationData); // Read in first row
|
|
//see if there's an explicit station sector id for this first
|
|
long station_id = GetStationSectorID((int) StationData["target_sector_object"]);
|
|
//long station_id = (int)StationData["starbase_sector_id"];
|
|
if (station_id == 0)
|
|
{
|
|
station_id = (int)StationData["sector_id"] * 10 + 1; //there was no explicit sector id
|
|
}
|
|
|
|
//see if we already have allocated this station
|
|
current_station = m_StationList[station_id];
|
|
|
|
if (!current_station)
|
|
{
|
|
current_station = new StationTemplate; // New Station
|
|
StationCount++; // Update Station Count
|
|
new_station = true;
|
|
}
|
|
|
|
if (current_station)
|
|
{
|
|
current_station->StationID = station_id;
|
|
printf("."); //progress
|
|
|
|
m_StationList[current_station->StationID] = current_station;
|
|
|
|
current_station->Name = g_StringMgr->GetStr((const char*)StationData["name"]);
|
|
current_station->Type = StationData["type"];
|
|
current_station->IsActive = StationData["is_active"];
|
|
current_station->Race = StationData["faction_id"];
|
|
const char * welcome = StationData["welcome_message"];
|
|
if (welcome) strcpy(current_station->WelcomeMessage, welcome);
|
|
current_station->NumTerms = 0;
|
|
current_station->NumNPCs = 0;
|
|
|
|
//clear terminals, rooms and NPC ID vectors for this station
|
|
current_station->Terms.clear();
|
|
current_station->Rooms.clear();
|
|
current_station->NPCs.clear();
|
|
|
|
int StationID = StationData["starbase_id"];
|
|
|
|
if (new_station)
|
|
{
|
|
long parent_sector = (int)StationData["sector_id"];
|
|
char *sector_name = g_ServerMgr->GetSectorName(parent_sector);
|
|
char *system_name = g_ServerMgr->GetSystemName(parent_sector);
|
|
if (sector_name && system_name)
|
|
{
|
|
g_ServerMgr->AddSector(current_station->StationID, current_station->Name, system_name, sector_name);
|
|
}
|
|
}
|
|
|
|
AddRooms(current_station, StationID, &connection);
|
|
}
|
|
else
|
|
{
|
|
LogMessage("Error allocating memory..\n");
|
|
return (success);
|
|
}
|
|
}
|
|
printf("\n");
|
|
LogMessage("Loaded Stations\n");
|
|
return (success);
|
|
}
|
|
|
|
void StationLoader::AddRooms(StationTemplate *current_station, long station_id, sql_connection_c *connection)
|
|
{
|
|
char queryString[512];
|
|
sql_query_c stnRooms( connection );
|
|
sql_result_c Rooms_result;
|
|
|
|
sprintf(queryString, "SELECT * FROM `starbase_rooms` WHERE `starbase_id` = '%ld'", station_id);
|
|
if ( !stnRooms.execute( queryString ) )
|
|
{
|
|
LogMessage( "Error reading with MySQL (Rooms)\n" );
|
|
return;
|
|
}
|
|
|
|
stnRooms.store(&Rooms_result);
|
|
sql_row_c RoomData;
|
|
RoomTemplate *current_room = NULL;
|
|
|
|
current_station->NumRooms = (int)Rooms_result.n_rows();
|
|
|
|
LogDebug("Loading %d Rooms for Location: %d\n", current_station->NumRooms, current_station->StationID);
|
|
|
|
for(int y=0;y<Rooms_result.n_rows();y++)
|
|
{
|
|
Rooms_result.fetch_row(&RoomData);
|
|
int room_id = RoomData["room_id"];
|
|
|
|
//see if we already have allocated this room
|
|
current_room = m_RoomList[room_id];
|
|
|
|
if (!current_room)
|
|
{
|
|
current_room = new RoomTemplate;
|
|
}
|
|
|
|
if (current_room)
|
|
{
|
|
current_room->Index = RoomData["type"];
|
|
current_room->Style = RoomData["style"];
|
|
current_room->FogNear = RoomData["fog_near"];
|
|
current_room->FogFar = RoomData["fog_far"];
|
|
|
|
current_room->FogRed = RoomData["fog_red"];
|
|
current_room->FogGreen = RoomData["fog_green"];
|
|
current_room->FogBlue = RoomData["fog_blue"];
|
|
|
|
m_RoomList[room_id] = current_room;
|
|
|
|
current_station->Rooms.push_back(room_id);
|
|
|
|
AddTerminals(current_station, room_id, connection);
|
|
AddNPCs(current_station, room_id, connection);
|
|
}
|
|
}
|
|
}
|
|
|
|
void StationLoader::AddTerminals(StationTemplate *current_station, long room_id, sql_connection_c *connection)
|
|
{
|
|
char queryString[512];
|
|
//now load all terminals for this room
|
|
sql_query_c stnTerms( connection );
|
|
sql_result_c Term_result;
|
|
|
|
sprintf(queryString, "SELECT * FROM `starbase_terminals` WHERE `room_id` = '%ld'", room_id);
|
|
|
|
if ( !stnTerms.execute( queryString ) )
|
|
{
|
|
LogMessage( "Error reading with MySQL (Terms)\n" );
|
|
return;
|
|
}
|
|
|
|
stnTerms.store(&Term_result);
|
|
sql_row_c TermData;
|
|
TermTemplate *current_term = NULL;
|
|
|
|
current_station->NumTerms += (int)Term_result.n_rows();
|
|
|
|
LogDebug("Loading %d Terms for Location: %d\n", current_station->NumTerms, current_station->StationID);
|
|
for(int yt=0;yt<Term_result.n_rows();yt++)
|
|
{
|
|
Term_result.fetch_row(&TermData);
|
|
long term_id = TermData["terminal_id"];
|
|
|
|
//see if we already have allocated this terminal
|
|
current_term = m_TermList[term_id];
|
|
|
|
if (!current_term)
|
|
{
|
|
current_term = new TermTemplate;
|
|
}
|
|
|
|
if(current_term)
|
|
{
|
|
current_station->Terms.push_back(term_id);
|
|
m_TermList[term_id] = current_term;
|
|
|
|
current_term->Room = m_RoomList[room_id]->Index;
|
|
current_term->Location = TermData["location"];
|
|
current_term->Type = TermData["type"];
|
|
}
|
|
}
|
|
}
|
|
|
|
void StationLoader::AddNPCs(StationTemplate *current_station, long room_id, sql_connection_c *connection)
|
|
{
|
|
char queryString[512];
|
|
|
|
// Add NPC id's for each room
|
|
sql_query_c stnNPCs( connection );
|
|
sql_result_c NPCs_result;
|
|
|
|
//sprintf(queryString, "SELECT * FROM `starbase_npcs` WHERE `room_id` = '%d'", room_id);
|
|
sprintf(queryString, "SELECT * FROM `starbase_npcs` left join `starbase_npc_avatar_templates`"
|
|
" on starbase_npcs.npc_Id = starbase_npc_avatar_templates.avatar_template_id"
|
|
" left join `starbase_vendors`"
|
|
" on starbase_npcs.npc_Id = starbase_vendors.vendor_id"
|
|
" WHERE `room_id` = '%ld'", room_id);
|
|
|
|
if ( !stnNPCs.execute( queryString ) )
|
|
{
|
|
LogMessage( "Error reading with MySQL (NPCs)\n" );
|
|
return;
|
|
}
|
|
|
|
stnNPCs.store(&NPCs_result);
|
|
sql_row_c NPCData;
|
|
NPCTemplate *current_npc = NULL;
|
|
|
|
current_station->NumNPCs += (int)NPCs_result.n_rows();
|
|
|
|
for(int y=0;y<NPCs_result.n_rows();y++)
|
|
{
|
|
NPCs_result.fetch_row(&NPCData);
|
|
NPCData.allow_null(0);
|
|
int NPCid = NPCData["npc_Id"];
|
|
|
|
//see if we already have allocated this NPC
|
|
current_npc = m_NPCList[NPCid];
|
|
|
|
if (!current_npc)
|
|
{
|
|
current_npc = new NPCTemplate;
|
|
}
|
|
|
|
if(current_npc)
|
|
{
|
|
memset(¤t_npc->Avatar,0,sizeof(AvatarData));
|
|
m_NPCList[NPCid] = current_npc; // Assign NPC to NPC list map
|
|
int room_id = NPCData["room_id"];
|
|
int Room_Type = m_RoomList[room_id]->Index;
|
|
|
|
//LogMessage("Loading NPC: %s %s for Location: %d Room: %d NPCID: %d\n", (char *)NPCData["first_name"], (char *)NPCData["last_name"], (int)NPCData["location"], Room_Type, (int)NPCData["npc_Id"]);
|
|
|
|
strcpy(current_npc->Avatar.avatar_first_name, NPCData["first_name"]);
|
|
strcpy(current_npc->Avatar.avatar_last_name, NPCData["last_name"]);
|
|
current_npc->Location = NPCData["location"];
|
|
|
|
//read in talk tree XML text
|
|
int talk_tree_length = strlen(NPCData["talk_tree_handle"])+1;
|
|
|
|
if (talk_tree_length > m_TalkTreeBufferLen)
|
|
{
|
|
delete[] m_TalkTreeBuffer;
|
|
m_TalkTreeBuffer = new char[talk_tree_length];
|
|
m_TalkTreeBufferLen = talk_tree_length;
|
|
}
|
|
|
|
strcpy(m_TalkTreeBuffer, NPCData["talk_tree_handle"]);
|
|
|
|
//now convert to structure format
|
|
BuildMissionTree(current_npc);
|
|
|
|
//TalkTreeStructure
|
|
|
|
//now when we need to create the talk tree, it's just a case of creating the packet from the structure.
|
|
|
|
/*if (talk_tree_length > current_npc->TalkTreeBufferLen)
|
|
{
|
|
if (current_npc->TalkTree)
|
|
{
|
|
delete (current_npc->TalkTree);
|
|
}
|
|
current_npc->TalkTree = new char[talk_tree_length];
|
|
//only adjust length here, that way we track the memory available.
|
|
current_npc->TalkTreeBufferLen = talk_tree_length;
|
|
}
|
|
|
|
strcpy(current_npc->TalkTree, NPCData["talk_tree_handle"]);*/
|
|
|
|
current_npc->Room = Room_Type; // Room #
|
|
current_npc->VGroup = NPCData["groupid"];
|
|
current_npc->Booth = NPCData["booth_type"];
|
|
current_npc->StarbaseID = NPCid;
|
|
current_npc->Avatar.avatar_type = NPCData["avatar_type"];
|
|
current_npc->Avatar.avatar_version = (int)NPCData["avatar_version"];
|
|
current_npc->Avatar.race = NPCData["race"];
|
|
current_npc->Avatar.profession = NPCData["profession"];
|
|
current_npc->Avatar.gender = NPCData["gender"];
|
|
current_npc->Avatar.mood_type = NPCData["mood_type"];
|
|
current_npc->Avatar.personality = (int) NPCData["personality"];
|
|
current_npc->Avatar.nlp = (int) NPCData["nlp"];
|
|
current_npc->Avatar.body_type = (int)NPCData["shirt_type"];
|
|
current_npc->Avatar.pants_type = (int)NPCData["pants_type"];
|
|
current_npc->Avatar.head_type = (int)NPCData["head_type"];
|
|
current_npc->Avatar.hair_num = (int)NPCData["hair_type"];
|
|
current_npc->Avatar.ear_num = (int)NPCData["ear_type"];
|
|
current_npc->Avatar.goggle_num = (int)NPCData["goggle_num"];
|
|
current_npc->Avatar.beard_num = (int)NPCData["beard_num"];
|
|
current_npc->Avatar.weapon_hip_num = (int)NPCData["weapon_hip_num"];
|
|
current_npc->Avatar.weapon_unique_num = (int)NPCData["weapon_unique_num"];
|
|
current_npc->Avatar.weapon_back_num = (int)NPCData["weapon_back_num"];
|
|
current_npc->Avatar.head_texture_num = (int)NPCData["head_texture_num"];
|
|
current_npc->Avatar.tattoo_texture_num = (int)NPCData["tatoo_texture_num"];
|
|
current_npc->Avatar.tattoo_offset[0] = NPCData["tatoo_x"];
|
|
current_npc->Avatar.tattoo_offset[1] = NPCData["tatoo_y"];
|
|
current_npc->Avatar.tattoo_offset[2] = NPCData["tatoo_z"];
|
|
current_npc->Avatar.hair_color[0] = NPCData["hair_color_0"];
|
|
current_npc->Avatar.hair_color[1] = NPCData["hair_color_1"];
|
|
current_npc->Avatar.hair_color[2] = NPCData["hair_color_2"];
|
|
current_npc->Avatar.beard_color[0] = NPCData["beard_color_0"];
|
|
current_npc->Avatar.beard_color[1] = NPCData["beard_color_1"];
|
|
current_npc->Avatar.beard_color[2] = NPCData["beard_color_2"];
|
|
current_npc->Avatar.eye_color[0] = NPCData["eye_color_0"];
|
|
current_npc->Avatar.eye_color[1] = NPCData["eye_color_1"];
|
|
current_npc->Avatar.eye_color[2] = NPCData["eye_color_2"];
|
|
current_npc->Avatar.skin_color[0] = NPCData["skin_color_0"];
|
|
current_npc->Avatar.skin_color[1] = NPCData["skin_color_1"];
|
|
current_npc->Avatar.skin_color[2] = NPCData["skin_color_2"];
|
|
current_npc->Avatar.shirt_primary_color[0] = NPCData["shirt1_color_0"];
|
|
current_npc->Avatar.shirt_primary_color[1] = NPCData["shirt1_color_1"];
|
|
current_npc->Avatar.shirt_primary_color[2] = NPCData["shirt1_color_2"];
|
|
current_npc->Avatar.shirt_secondary_color[0] = NPCData["shirt2_color_0"];
|
|
current_npc->Avatar.shirt_secondary_color[1] = NPCData["shirt2_color_1"];
|
|
current_npc->Avatar.shirt_secondary_color[2] = NPCData["shirt2_color_2"];
|
|
current_npc->Avatar.pants_primary_color[0] = NPCData["pants1_color_0"];
|
|
current_npc->Avatar.pants_primary_color[1] = NPCData["pants1_color_1"];
|
|
current_npc->Avatar.pants_primary_color[2] = NPCData["pants1_color_2"];
|
|
current_npc->Avatar.pants_secondary_color[0] = NPCData["pants2_color_0"];
|
|
current_npc->Avatar.pants_secondary_color[1] = NPCData["pants2_color_1"];
|
|
current_npc->Avatar.pants_secondary_color[2] = NPCData["pants2_color_2"];
|
|
current_npc->Avatar.shirt_primary_metal = NPCData["shirt1_metal"];
|
|
current_npc->Avatar.shirt_secondary_metal = NPCData["shirt2_metal"];
|
|
current_npc->Avatar.pants_primary_metal = NPCData["pants1_metal"];
|
|
current_npc->Avatar.pants_secondary_metal = NPCData["pants2_metal"];
|
|
current_npc->Avatar.height_weight_1[0] = NPCData["body_weight0"];
|
|
current_npc->Avatar.height_weight_1[1] = NPCData["body_weight1"];
|
|
current_npc->Avatar.height_weight_1[2] = NPCData["body_weight2"];
|
|
current_npc->Avatar.height_weight_1[3] = NPCData["body_weight3"];
|
|
current_npc->Avatar.height_weight_1[4] = NPCData["body_weight4"];
|
|
current_npc->Avatar.height_weight_2[0] = NPCData["head_weight0"];
|
|
current_npc->Avatar.height_weight_2[1] = NPCData["head_weight1"];
|
|
current_npc->Avatar.height_weight_2[2] = NPCData["head_weight2"];
|
|
current_npc->Avatar.height_weight_2[3] = NPCData["head_weight3"];
|
|
current_npc->Avatar.height_weight_2[4] = NPCData["head_weight4"];
|
|
|
|
current_station->NPCs.push_back(NPCid);
|
|
|
|
// Set Trade Items to 0
|
|
current_npc->Vendor.NItems = 0;
|
|
|
|
// Make sure we are a vendor
|
|
if (current_npc->VGroup != -1)
|
|
{
|
|
// Load Vendor Information
|
|
sql_query_c stnVG( connection );
|
|
sql_result_c NPCVG_result;
|
|
|
|
sprintf(queryString, "SELECT `id`,`itemid`,`sell_price`,`buy_price`,`quanity` FROM `starbase_vender_inventory` WHERE `starbase_vender_inventory`.`groupid` = '%d'", current_npc->VGroup);
|
|
|
|
if ( !stnVG.execute( queryString ) )
|
|
{
|
|
LogMessage( "Error reading with MySQL (Vendors)\n" );
|
|
return;
|
|
}
|
|
|
|
stnVG.store(&NPCVG_result);
|
|
sql_row_c VendorInfo;
|
|
VendorItemList *current_item = NULL;
|
|
|
|
current_npc->Vendor.Items.clear();
|
|
|
|
current_npc->Vendor.NItems = (int)NPCVG_result.n_rows();
|
|
|
|
// Loop through our data
|
|
for(int yv=0;yv<NPCVG_result.n_rows();yv++)
|
|
{
|
|
NPCVG_result.fetch_row(&VendorInfo);
|
|
VendorInfo.allow_null(0);
|
|
int ItemID = VendorInfo["id"];
|
|
|
|
current_item = m_ItemList[ItemID];
|
|
|
|
if (!current_item)
|
|
{
|
|
current_item = new VendorItemList;
|
|
}
|
|
|
|
// Add to our list
|
|
if(current_item)
|
|
{
|
|
m_ItemList[ItemID] = current_item;
|
|
|
|
current_npc->Vendor.Items.push_back(ItemID);
|
|
|
|
current_item->ItemID = VendorInfo["itemid"];
|
|
current_item->BuyPrice = VendorInfo["buy_price"];
|
|
current_item->Quanity = VendorInfo["quanity"];
|
|
current_item->SellPrice = VendorInfo["sell_price"];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void StationLoader::BuildMissionTree(NPCTemplate *npc)
|
|
{
|
|
//TODO: delete existing node
|
|
|
|
//first lets process normal talk trees
|
|
//InteractionNode *node = new NPCInteractionNode;
|
|
|
|
//npc->NPCInteraction[0] = node;
|
|
|
|
m_TalkTreeParser.ParseTalkTree(&npc->NPCInteraction.talk_tree, m_TalkTreeBuffer);
|
|
|
|
//m_TalkTreeParser.ParseMissions(&npc->NPCInteraction.mission_tree, m_TalkTreeBuffer);
|
|
}
|
|
|
|
NPCTemplate * StationLoader::GetNPC(int ID)
|
|
{
|
|
return (m_NPCList[ID]);
|
|
}
|
|
|
|
// Send the Station Data from ID
|
|
StationTemplate * StationLoader::GetStation(int ID)
|
|
{
|
|
return (m_StationList[ID]);
|
|
}
|
|
|
|
RoomTemplate * StationLoader::GetRoom(int ID)
|
|
{
|
|
return (m_RoomList[ID]);
|
|
}
|
|
|
|
TermTemplate * StationLoader::GetTerminal(int ID)
|
|
{
|
|
return (m_TermList[ID]);
|
|
}
|
|
|
|
VendorItemList * StationLoader::GetVendorItem(int ID)
|
|
{
|
|
return (m_ItemList[ID]);
|
|
}
|
|
|
|
char * StationLoader::_GetSectorName(long sector_id)
|
|
{
|
|
StationTemplate * station = m_StationList[sector_id];
|
|
|
|
if (station)
|
|
{
|
|
return station->Name;
|
|
}
|
|
else
|
|
{
|
|
return (0);
|
|
}
|
|
}
|