mirror of
https://github.com/therealKyp/Earth-and-Beyond-server
synced 2026-08-13 22:23:03 -04:00
1045 lines
48 KiB
C++
1045 lines
48 KiB
C++
// SectorContentParser.cpp
|
|
|
|
#include "Net7.h"
|
|
|
|
#ifndef USE_MYSQL_SECTOR
|
|
|
|
#include "SectorContentParser.h"
|
|
#include "XmlParser.h"
|
|
#include "SectorData.h"
|
|
#include "ObjectClass.h"
|
|
#include "ObjectManager.h"
|
|
|
|
static XmlParser::XmlTagLookupTable sector_content_tag_lookup_table[] =
|
|
{
|
|
{ XML_TAG_ID_SECTOR_CONTENT, XML_TAG_SECTOR_CONTENT },
|
|
{ XML_TAG_ID_GALAXY, XML_TAG_GALAXY },
|
|
{ XML_TAG_ID_UNIVERSE, XML_TAG_UNIVERSE },
|
|
{ XML_TAG_ID_SYSTEM, XML_TAG_SYSTEM },
|
|
{ XML_TAG_ID_SERVER_PARAMETERS, XML_TAG_SERVER_PARAMETERS },
|
|
{ XML_TAG_ID_SECTOR, XML_TAG_SECTOR },
|
|
{ XML_TAG_ID_GAME_OBJECT, XML_TAG_GAME_OBJECT },
|
|
{ XML_TAG_ID_NAME, XML_TAG_NAME },
|
|
{ XML_TAG_ID_ACTIVATE_RENDER_STATE, XML_TAG_ACTIVATE_RENDER_STATE },
|
|
{ XML_TAG_ID_OBJECT_EFFECT, XML_TAG_OBJECT_EFFECT },
|
|
{ XML_TAG_ID_RELATIONSHIP, XML_TAG_RELATIONSHIP },
|
|
{ XML_TAG_ID_SIMPLE_POSITIONAL_UPDATE, XML_TAG_SIMPLE_POSITIONAL_UPDATE },
|
|
{ XML_TAG_ID_ADVANCED_POSITIONAL_UPDATE, XML_TAG_ADVANCED_POSITIONAL_UPDATE },
|
|
{ XML_TAG_ID_PLANET_POSITIONAL_UPDATE, XML_TAG_PLANET_POSITIONAL_UPDATE },
|
|
{ XML_TAG_ID_CONSTANT_POSITIONAL_UPDATE, XML_TAG_CONSTANT_POSITIONAL_UPDATE },
|
|
{ XML_TAG_ID_COMPONENT_POSITIONAL_UPDATE, XML_TAG_COMPONENT_POSITIONAL_UPDATE },
|
|
{ XML_TAG_ID_NAVIGATION, XML_TAG_NAVIGATION },
|
|
{ XML_TAG_ID_DESTINATION, XML_TAG_DESTINATION },
|
|
{ XML_TAG_ID_GREETINGS, XML_TAG_GREETINGS },
|
|
{ XML_TAG_ID_NOTES, XML_TAG_NOTES },
|
|
{ XML_TAG_ID_SPAWN_DATA, XML_TAG_SPAWN_DATA },
|
|
{ XML_TAG_ID_FIELD, XML_TAG_FIELD_POINT },
|
|
{ XML_TAG_ID_SPAWN_POINT, XML_TAG_SPAWN_POINT },
|
|
{ XML_TAG_ID_MOB_ID, XML_TAG_MOB_ID },
|
|
{ XML_TAG_ID_RESOURCE_ID, XML_TAG_RESOURCE_ID },
|
|
{ XML_TAG_ID_INVALID, 0 }
|
|
};
|
|
|
|
SectorContentParser::SectorContentParser()
|
|
{
|
|
m_XmlTagLookupTable = sector_content_tag_lookup_table;
|
|
m_SectorList = NULL;
|
|
}
|
|
|
|
SectorContentParser::~SectorContentParser()
|
|
{
|
|
// TODO: destroy everything
|
|
}
|
|
|
|
bool SectorContentParser::LoadSectorContent()
|
|
{
|
|
// TODO: Make HTTPS connection to the Auth Server to obtain XML sector content file
|
|
// FOR NOW, we will simply load a local XML file with the sector contents
|
|
|
|
bool success = false;
|
|
char orig_path[MAX_PATH];
|
|
GetCurrentDirectory(sizeof(orig_path), orig_path);
|
|
SetCurrentDirectory(SERVER_DATABASE_PATH);
|
|
|
|
FILE *f = fopen("SectorContent.xml", "r");
|
|
if (f)
|
|
{
|
|
fseek(f, 0, SEEK_END);
|
|
long file_size = ftell(f);
|
|
fseek(f, 0, SEEK_SET);
|
|
char *data = new char[file_size + 1];
|
|
if (data)
|
|
{
|
|
// Load the entire file into memory for parsing
|
|
long size = fread(data, 1, file_size, f);
|
|
data[size] = 0;
|
|
//printf("Read %d of %d bytes\n", size, file_size);
|
|
success = ParseSectorContent(data);
|
|
delete [] data;
|
|
}
|
|
fclose(f);
|
|
}
|
|
else
|
|
{
|
|
printf("Error opening SectorContent.xml\n");
|
|
}
|
|
|
|
SetCurrentDirectory(orig_path);
|
|
return (success);
|
|
}
|
|
|
|
bool SectorContentParser::ParseSectorContent(char *data)
|
|
{
|
|
char * p = data;
|
|
long sector_count = 0;
|
|
long next_game_id = 100000;
|
|
SectorData * current_sector = NULL;
|
|
char attrib[64];
|
|
char attrib2[64];
|
|
char attrib3[64];
|
|
char attrib4[64];
|
|
char system_name[64];
|
|
long system_id;
|
|
|
|
Object *current_object = 0;
|
|
|
|
//printf("Parsing SectorContent.xml\n");
|
|
|
|
// Assume we will succeed
|
|
m_Success = true;
|
|
|
|
// Parse the data until we are done
|
|
bool done = false;
|
|
while (!done)
|
|
{
|
|
if (ParseXmlTag(&p))
|
|
{
|
|
switch (m_XmlTagID)
|
|
{
|
|
case XML_TAG_ID_SECTOR_CONTENT :
|
|
case XML_TAG_ID_UNIVERSE :
|
|
case XML_TAG_ID_GALAXY :
|
|
// Ignore this tag, it is just the container for the systems and sectors
|
|
// It is not a fatal error if this is missing
|
|
// (although it will not be legal XML and Internet Explorer will complain)
|
|
break;
|
|
|
|
case XML_TAG_ID_NOTES:
|
|
// Notes are ignored
|
|
break;
|
|
|
|
case XML_TAG_ID_SYSTEM :
|
|
if ((GetXmlAttribute("ID", attrib, sizeof(attrib), true)) &&
|
|
(GetXmlAttribute("Name", attrib2, sizeof(attrib2), false)))
|
|
{
|
|
system_id = atoi(attrib);
|
|
strcpy(system_name, attrib2);
|
|
}
|
|
break;
|
|
|
|
case XML_TAG_ID_SECTOR :
|
|
// Create a new sector
|
|
// Forget about the last sector we were working on (it is in the linked list).
|
|
current_sector = new SectorData;
|
|
|
|
if (current_sector)
|
|
{
|
|
current_sector->system_id = system_id;
|
|
strcpy(current_sector->system_name, system_name);
|
|
sector_count++;
|
|
memset(current_sector, 0, sizeof(SectorData));
|
|
//instantiate a new ObjectManager
|
|
current_sector->obj_manager = new ObjectManager;
|
|
|
|
current_sector->m_xmax = current_sector->m_xmin = 0.0f;
|
|
current_sector->m_ymax = current_sector->m_ymin = 0.0f;
|
|
|
|
// Add the new sector to the linked list
|
|
if (m_SectorList)
|
|
{
|
|
// Find the last entry in the linked list
|
|
SectorData *p = m_SectorList;
|
|
while (p->next)
|
|
{
|
|
p = p->next;
|
|
}
|
|
// Add this sector to the end of the linked list
|
|
p->next = current_sector;
|
|
}
|
|
else
|
|
{
|
|
// This is the first sector in the linked list
|
|
m_SectorList = current_sector;
|
|
}
|
|
|
|
// Parse the "ID" and "Name" attribute
|
|
if ((GetXmlAttribute("ID", attrib, sizeof(attrib), true)) &&
|
|
(GetXmlAttribute("Name", attrib2, sizeof(attrib2), false)))
|
|
{
|
|
current_sector->sector_id = atoi(attrib);
|
|
char *temp = DecodeXmlString(attrib2);
|
|
if (temp)
|
|
{
|
|
strcpy(current_sector->name, temp);
|
|
delete [] temp;
|
|
}
|
|
}
|
|
// else missing the required attribute sets m_Success to false
|
|
}
|
|
else
|
|
{
|
|
printf("FATAL ERROR: ParseSectorContent unable to allocate memory for SectorData\n");
|
|
m_Success = false;
|
|
}
|
|
break;
|
|
|
|
case XML_TAG_ID_SERVER_PARAMETERS :
|
|
if (current_sector)
|
|
{
|
|
if ((GetXmlAttribute("ZbandMin", attrib, sizeof(attrib), true)) &&
|
|
(GetXmlAttribute("ZbandMax", attrib2, sizeof(attrib2), false)) &&
|
|
(GetXmlAttribute("XMin", attrib3, sizeof(attrib3), false)) &&
|
|
(GetXmlAttribute("YMin", attrib4, sizeof(attrib4), false)))
|
|
{
|
|
current_sector->server_params.ZBandMin = (float) atof(attrib);
|
|
current_sector->server_params.ZBandMax = (float) atof(attrib2);
|
|
current_sector->server_params.XMin = (float) atof(attrib3);
|
|
current_sector->server_params.YMin = (float) atof(attrib4);
|
|
// Parse the other required attributes
|
|
if ((GetXmlAttribute("XMax", attrib, sizeof(attrib), true)) &&
|
|
(GetXmlAttribute("YMax", attrib2, sizeof(attrib2), true)) &&
|
|
(GetXmlAttribute("FogNear", attrib3, sizeof(attrib3), true)) &&
|
|
(GetXmlAttribute("FogFar", attrib4, sizeof(attrib4), true)))
|
|
{
|
|
current_sector->server_params.XMax = (float) atof(attrib);
|
|
current_sector->server_params.YMax = (float) atof(attrib2);
|
|
current_sector->server_params.FogNear = (float) atof(attrib3);
|
|
current_sector->server_params.FogFar = (float) atof(attrib4);
|
|
// Parse the other required attributes
|
|
if ((GetXmlAttribute("DebrisMode", attrib, sizeof(attrib), true)) &&
|
|
(GetXmlAttribute("LightBackdrop", attrib2, sizeof(attrib2), true)) &&
|
|
(GetXmlAttribute("FogBackdrop", attrib3, sizeof(attrib3), true)) &&
|
|
(GetXmlAttribute("SwapBackdrop", attrib4, sizeof(attrib4), true)))
|
|
{
|
|
current_sector->server_params.DebrisMode = atoi(attrib);
|
|
current_sector->server_params.LightBackdrop = (attrib2[0] == 't') ? 1 : 0;
|
|
current_sector->server_params.FogBackdrop = (attrib3[0] == 't') ? 1 : 0;
|
|
current_sector->server_params.SwapBackdrop = (attrib4[0] == 't') ? 1 : 0;
|
|
// Parse the other required attributes
|
|
if ((GetXmlAttribute("BackdropFogNear", attrib, sizeof(attrib), true)) &&
|
|
(GetXmlAttribute("backdropFogFar", attrib2, sizeof(attrib2), true)) &&
|
|
(GetXmlAttribute("MaxTilt", attrib3, sizeof(attrib3), true)) &&
|
|
(GetXmlAttribute("AutoLevel", attrib4, sizeof(attrib4), true)))
|
|
{
|
|
// ImpulseRate="0.0" DecayVelocity="0.0" DecaySpin="0.0" BackdropBaseAsset="0"
|
|
current_sector->server_params.BackdropFogNear = (float) atof(attrib);
|
|
current_sector->server_params.BackdropFogFar = (float) atof(attrib2);
|
|
current_sector->server_params.MaxTilt = (float) atof(attrib3);
|
|
current_sector->server_params.AutoLevel = (attrib4[0] == 't') ? 1 : 0;
|
|
// Parse the other required attributes
|
|
if ((GetXmlAttribute("ImpulseRate", attrib, sizeof(attrib), true)) &&
|
|
(GetXmlAttribute("DecayVelocity", attrib2, sizeof(attrib2), true)) &&
|
|
(GetXmlAttribute("DecaySpin", attrib3, sizeof(attrib3), true)) &&
|
|
(GetXmlAttribute("BackdropBaseAsset", attrib4, sizeof(attrib4), true)))
|
|
{
|
|
current_sector->server_params.ImpulseRate = (float) atof(attrib);
|
|
current_sector->server_params.DecayVelocity = (float) atof(attrib2);
|
|
current_sector->server_params.DecaySpin = (float) atof(attrib3);
|
|
current_sector->server_params.BackdropBaseAsset = atoi(attrib4);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("ParseSectorContent: <ServerParameters> must be contained within a <Sector>\n");
|
|
m_Success = false;
|
|
}
|
|
break;
|
|
|
|
case XML_TAG_ID_GAME_OBJECT :
|
|
if (current_sector)
|
|
{
|
|
current_object = (Object*)(0);
|
|
// Parse the four attributes required for creating the object
|
|
if ((GetXmlAttribute("GameID", attrib, sizeof(attrib), true)) &&
|
|
(GetXmlAttribute("Scale", attrib2, sizeof(attrib2), true)) &&
|
|
(GetXmlAttribute("BaseAsset", attrib3, sizeof(attrib3), true)) &&
|
|
(GetXmlAttribute("Type", attrib4, sizeof(attrib4), true)))
|
|
{
|
|
long type = atoi(attrib4);
|
|
|
|
if (atoi(attrib3) != 0 && type == -1) type = 37; //bad object type, need to fix sectorcontent.xml
|
|
|
|
switch (type)
|
|
{
|
|
case 11:
|
|
current_object = current_sector->obj_manager->AddNewObject(OT_STARGATE);
|
|
break;
|
|
|
|
case 12:
|
|
current_object = current_sector->obj_manager->AddNewObject(OT_STATION);
|
|
break;
|
|
|
|
case 3:
|
|
current_object = current_sector->obj_manager->AddNewObject(OT_PLANET);
|
|
break;
|
|
|
|
case 37:
|
|
current_object = current_sector->obj_manager->AddNewObject(OT_DECO);
|
|
break;
|
|
|
|
case 38:
|
|
current_object = current_sector->obj_manager->AddNewObject(OT_RESOURCE, true);
|
|
break;
|
|
|
|
case -1:
|
|
current_object = current_sector->obj_manager->AddNewObject(OT_FIELD, true);
|
|
break;
|
|
|
|
case 0:
|
|
current_object = current_sector->obj_manager->AddNewObject(OT_MOB, true);
|
|
break;
|
|
|
|
default:
|
|
//Holy Diver! Type not found
|
|
LogMessage("WARNING: Unexpected XML type %d.\n",type);
|
|
current_object = current_sector->obj_manager->AddNewObject(OT_RESOURCE, true); //assume this is a resource for now
|
|
};
|
|
|
|
if (!current_object)
|
|
{
|
|
printf("FATAL ERROR: ParseSectorContent unable to allocate memory for GameObject\n");
|
|
m_Success = false;
|
|
}
|
|
else
|
|
{
|
|
current_object->SetScale(float(atof(attrib2)));
|
|
current_object->SetCreateType(char(type));
|
|
|
|
// The HSV attribute is optional
|
|
if (GetXmlAttribute("HSV", attrib, sizeof(attrib), false) && current_object)
|
|
{
|
|
// Parse the three color values into the array
|
|
float HSV[3];
|
|
HSV[0] = 0.0f;
|
|
HSV[1] = 0.0f;
|
|
HSV[2] = 0.0f;
|
|
|
|
ParseFloatArray(attrib, 3, HSV);
|
|
current_object->SetHSV(HSV[0], HSV[1], HSV[2]);
|
|
current_object->SetLevelFromHSV(HSV[0]);
|
|
}
|
|
// The Signature attribute is optional
|
|
if (GetXmlAttribute("Signature", attrib, sizeof(attrib), false) && current_object)
|
|
{
|
|
current_object->SetSignature((float) atof(attrib));
|
|
}
|
|
// The IsCapShip attribute is optional
|
|
if (GetXmlAttribute("IsCapShip", attrib, sizeof(attrib), false) && current_object)
|
|
{
|
|
if (attrib[0] == '1') current_object->SetObjectType(OT_CAPSHIP);
|
|
}
|
|
// The Appears in Radar is optional, only ="0" is hidden
|
|
if (GetXmlAttribute("AppearsInRadar", attrib, sizeof(attrib), false))
|
|
{
|
|
if (attrib[0] == '1') current_object->SetAppearsInRadar();
|
|
}
|
|
//for now, we use RadarRange as the sig for objects that don't have nav info
|
|
if (GetXmlAttribute("RadarRange", attrib, sizeof(attrib), false))
|
|
{
|
|
current_object->SetRadarRange((float) atof(attrib));
|
|
}
|
|
|
|
current_object->SetBasset(atoi(attrib3));
|
|
|
|
current_sector->num_objects++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("ParseSectorContent: <GameObject> Declaration missing params.\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("ParseSectorContent: <GameObject> must be contained within a <Sector>\n");
|
|
m_Success = false;
|
|
}
|
|
break;
|
|
|
|
case XML_TAG_ID_FIELD:
|
|
if (current_sector)
|
|
{
|
|
current_object = (Object*)(0);
|
|
|
|
if ((GetXmlAttribute("FieldID", attrib, sizeof(attrib), true)) &&
|
|
(GetXmlAttribute("Count", attrib4, sizeof(attrib4), true)) &&
|
|
(GetXmlAttribute("Level", attrib2, sizeof(attrib2), true)) &&
|
|
(GetXmlAttribute("Type", attrib3, sizeof(attrib3), true)) )
|
|
{
|
|
//ok we've got a Field spawn. Add it in
|
|
current_object = current_sector->obj_manager->AddNewObject(OT_FIELD);
|
|
//current_object->SetGameID(atoi(attrib));
|
|
current_object->SetFieldCount(atoi(attrib4));
|
|
current_object->SetLevel(atoi(attrib2));
|
|
current_object->SetFieldType(atoi(attrib3));
|
|
|
|
if (GetXmlAttribute("Radius", attrib, sizeof(attrib), true))
|
|
{
|
|
current_object->SetFieldRadius((float)atof(attrib));
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case XML_TAG_ID_SPAWN_POINT:
|
|
if (current_sector)
|
|
{
|
|
current_object = (Object*)(0);
|
|
|
|
if ((GetXmlAttribute("SpawnID", attrib, sizeof(attrib), true)) &&
|
|
(GetXmlAttribute("Count", attrib4, sizeof(attrib4), true)))
|
|
{
|
|
//ok we've got a MOB spawn. Add it in
|
|
current_object = current_sector->obj_manager->AddNewObject(OT_MOBSPAWN);
|
|
//current_object->SetGameID(atoi(attrib));
|
|
current_object->SetSpawnCount(atoi(attrib4));
|
|
if ((GetXmlAttribute("LevelMin", attrib2, sizeof(attrib2), true)) &&
|
|
(GetXmlAttribute("LevelMax", attrib3, sizeof(attrib3), true)))
|
|
{
|
|
current_object->SetLevelMinMax(atoi(attrib2), atoi(attrib3));
|
|
}
|
|
if (GetXmlAttribute("SpawnRadius", attrib, sizeof(attrib), true))
|
|
{
|
|
current_object->SetSpawnRadius((float)atof(attrib));
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case XML_TAG_ID_MOB_ID:
|
|
if (current_object)
|
|
{
|
|
if (GetXmlAttribute("ID", attrib, sizeof(attrib), true))
|
|
{
|
|
current_object->AddMOBID(atoi(attrib));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("ParseSectorContent: <MOB_ID> must be contained within a <GameObject>\n");
|
|
m_Success = false;
|
|
}
|
|
break;
|
|
|
|
case XML_TAG_ID_RESOURCE_ID:
|
|
if (current_object)
|
|
{
|
|
if (GetXmlAttribute("ID", attrib, sizeof(attrib), true))
|
|
{
|
|
current_object->AddResource(atoi(attrib));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("ParseSectorContent: <Resource ID=> must be contained within a <GameObject>\n");
|
|
m_Success = false;
|
|
}
|
|
break;
|
|
|
|
case XML_TAG_ID_SPAWN_DATA:
|
|
if (current_object)
|
|
{
|
|
if (GetXmlAttribute("SpawnRadius", attrib, sizeof(attrib), true))
|
|
{
|
|
current_object->SetSpawnRadius(atoi(attrib));
|
|
|
|
if ((GetXmlAttribute("Behaviour", attrib2, sizeof(attrib2), true)) &&
|
|
(GetXmlAttribute("GroupAttack", attrib4, sizeof(attrib4), true)))
|
|
{
|
|
current_object->SetBehaviour(atoi(attrib2));
|
|
current_object->SetGroupAttack(atoi(attrib4));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("ParseSectorContent: incomplete SpawnData entry: require SpawnRadius Behaviour Aggressiveness GroupAttack\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("ParseSectorContent: <SpawnData> must be contained within a <GameObject>\n");
|
|
m_Success = false;
|
|
}
|
|
|
|
break;
|
|
|
|
case XML_TAG_ID_NAME :
|
|
// Are we parsing a game object?
|
|
if (current_object)
|
|
{
|
|
char name[60];
|
|
if (!GetXmlData(&p, name, sizeof(name)))
|
|
{
|
|
printf("ParseSectorContent: Unable to parse tag: %s", m_Tag);
|
|
m_Success = false;
|
|
}
|
|
else
|
|
{
|
|
current_object->SetName(name);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("ParseSectorContent: <Name> must be contained within a <GameObject>\n");
|
|
m_Success = false;
|
|
}
|
|
break;
|
|
|
|
case XML_TAG_ID_ACTIVATE_RENDER_STATE:
|
|
if (current_object)
|
|
{
|
|
if (GetXmlAttribute("RenderStateID", attrib, sizeof(attrib), true))
|
|
{
|
|
int render_state = atoi(attrib);
|
|
int bit = 1 << render_state;
|
|
current_object->SetRenderState(current_object->RenderState() | bit);
|
|
}
|
|
else
|
|
{
|
|
printf("ParseSectorContent: Unable to parse tag: %s", m_Tag);
|
|
m_Success = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("ParseSectorContent: <ActivateRenderState> must be contained within a <GameObject>\n");
|
|
m_Success = false;
|
|
}
|
|
break;
|
|
|
|
case XML_TAG_ID_OBJECT_EFFECT:
|
|
if (current_object)
|
|
{
|
|
ObjectEffect * object_effect = current_object->AddNewEffect();
|
|
|
|
// Parse the two required attributes
|
|
if ((GetXmlAttribute("Bitmask", attrib, sizeof(attrib), true)) &&
|
|
(GetXmlAttribute("EffectDescID", attrib2, sizeof(attrib2), true)))
|
|
{
|
|
object_effect->Bitmask = (char) atoi(attrib);
|
|
object_effect->EffectDescID = atoi(attrib2);
|
|
if (object_effect->EffectDescID != 0)
|
|
{
|
|
current_object->SetBroadcastID(object_effect->EffectDescID);
|
|
}
|
|
if ((object_effect->Bitmask & 0x01) &&
|
|
(GetXmlAttribute("EffectID", attrib, sizeof(attrib), false)))
|
|
{
|
|
object_effect->EffectID = atoi(attrib);
|
|
}
|
|
// Ignore Timestamp attribute, bitmask 0x02
|
|
if ((object_effect->Bitmask & 0x04) &&
|
|
(GetXmlAttribute("Duration", attrib, sizeof(attrib), false)))
|
|
{
|
|
object_effect->Duration = atoi(attrib);
|
|
}
|
|
if ((object_effect->Bitmask & 0x08) &&
|
|
(GetXmlAttribute("Scale", attrib, sizeof(attrib), false)))
|
|
{
|
|
object_effect->Scale = (float) atof(attrib);
|
|
}
|
|
if ((object_effect->Bitmask & 0x70) &&
|
|
(GetXmlAttribute("HSVShift", attrib, sizeof(attrib), false)))
|
|
{
|
|
ParseFloatArray(attrib, 3, object_effect->HSVShift);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("ParseSectorContent: <ObjectEffect> must be contained within a <GameObject>\n");
|
|
m_Success = false;
|
|
}
|
|
break;
|
|
|
|
case XML_TAG_ID_RELATIONSHIP :
|
|
if (current_object)
|
|
{
|
|
// Parse the two required attributes
|
|
if ((GetXmlAttribute("Reaction", attrib, sizeof(attrib), true)) &&
|
|
(GetXmlAttribute("IsAttacking", attrib2, sizeof(attrib2), true)))
|
|
{
|
|
// this is meaningless really, MOBs should have their own behaviour
|
|
// TODO: check min/max on these values
|
|
/*current_object->reaction = atoi(attrib);
|
|
current_object->is_attacking = (attrib2[0] == '1');
|
|
|
|
// TODO: Patch for zero reaction for now
|
|
if (current_object->reaction == 0)
|
|
{
|
|
current_object->reaction = RELATIONSHIP_FRIENDLY;
|
|
}*/
|
|
}
|
|
// else missing a required attribute sets m_Success to false
|
|
}
|
|
else
|
|
{
|
|
printf("ParseSectorContent: <Relationship> must be contained within a <GameObject>\n");
|
|
m_Success = false;
|
|
}
|
|
break;
|
|
|
|
case XML_TAG_ID_SIMPLE_POSITIONAL_UPDATE :
|
|
if (current_object)
|
|
{
|
|
// Parse the required attributes
|
|
if ((GetXmlAttribute("Position", attrib, sizeof(attrib), true)) &&
|
|
(GetXmlAttribute("Orientation", attrib2, sizeof(attrib2), true)) &&
|
|
(GetXmlAttribute("Velocity", attrib3, sizeof(attrib3), true)))
|
|
{
|
|
// We ignore the Timestamp attribute
|
|
float pos[3], orientation[4], velocity[3];
|
|
ParseFloatArray(attrib, 3, pos);
|
|
ParseFloatArray(attrib2, 4, orientation);
|
|
ParseFloatArray(attrib3, 3, velocity);
|
|
UpdateBoundaries(current_sector, pos);
|
|
|
|
current_object->SetPositionType(POSITION_SIMPLE);
|
|
current_object->SetPosition(pos);
|
|
current_object->SetOrientation(orientation);
|
|
current_object->SetVelocityVector(velocity);
|
|
current_object->PopulateSpawn(false);
|
|
}
|
|
// else missing a required attribute sets m_Success to false
|
|
}
|
|
else
|
|
{
|
|
printf("ParseSectorContent: <Relationship> must be contained within a <GameObject>\n");
|
|
m_Success = false;
|
|
}
|
|
break;
|
|
|
|
case XML_TAG_ID_ADVANCED_POSITIONAL_UPDATE :
|
|
if (current_object)
|
|
{
|
|
// Parse the required attributes
|
|
if ((GetXmlAttribute("Bitmask", attrib, sizeof(attrib), true)) &&
|
|
(GetXmlAttribute("Position", attrib2, sizeof(attrib2), true)) &&
|
|
(GetXmlAttribute("Orientation", attrib3, sizeof(attrib3), true)) &&
|
|
(GetXmlAttribute("MovementID", attrib4, sizeof(attrib4), true)))
|
|
{
|
|
PositionInformation PosInfo;
|
|
memset(&PosInfo, 0, sizeof(PosInfo));
|
|
// We ignore the Timestamp attribute
|
|
PosInfo.type = POSITION_ADVANCED;
|
|
current_object->SetPositionType(POSITION_ADVANCED);
|
|
short bitmask = (short) atoi(attrib);
|
|
ParseFloatArray(attrib, 3, PosInfo.Position);
|
|
ParseFloatArray(attrib2, 4, PosInfo.Orientation);
|
|
PosInfo.MovementID = atoi(attrib4);
|
|
// Parse the optional attributes
|
|
// The attributes are "required" if the bitmask is set
|
|
if ((bitmask & 0x0001) &&
|
|
(GetXmlAttribute("CurrentSpeed", attrib, sizeof(attrib), true)))
|
|
{
|
|
PosInfo.CurrentSpeed = (float) atof(attrib);
|
|
}
|
|
if ((bitmask & 0x0002) &&
|
|
(GetXmlAttribute("SetSpeed", attrib, sizeof(attrib), true)))
|
|
{
|
|
PosInfo.SetSpeed = (float) atof(attrib);
|
|
}
|
|
if ((bitmask & 0x0004) &&
|
|
(GetXmlAttribute("Acceleration", attrib, sizeof(attrib), true)))
|
|
{
|
|
PosInfo.Acceleration = (float) atof(attrib);
|
|
}
|
|
if ((bitmask & 0x0008) &&
|
|
(GetXmlAttribute("RotY", attrib, sizeof(attrib), true)))
|
|
{
|
|
PosInfo.RotY = (float) atof(attrib);
|
|
}
|
|
if ((bitmask & 0x0010) &&
|
|
(GetXmlAttribute("DesiredY", attrib, sizeof(attrib), true)))
|
|
{
|
|
PosInfo.DesiredY = (float) atof(attrib);
|
|
}
|
|
if ((bitmask & 0x0020) &&
|
|
(GetXmlAttribute("RotZ", attrib, sizeof(attrib), true)))
|
|
{
|
|
PosInfo.RotZ = (float) atof(attrib);
|
|
}
|
|
if ((bitmask & 0x0040) &&
|
|
(GetXmlAttribute("DesiredZ", attrib, sizeof(attrib), true)))
|
|
{
|
|
PosInfo.DesiredZ = (float) atof(attrib);
|
|
}
|
|
if (bitmask & 0x0080)
|
|
{
|
|
if ((GetXmlAttribute("ImpartedVelocity", attrib, sizeof(attrib), true)) &&
|
|
(GetXmlAttribute("ImpartedSpin", attrib2, sizeof(attrib2), true)) &&
|
|
(GetXmlAttribute("ImpartedRoll", attrib3, sizeof(attrib3), true)) &&
|
|
(GetXmlAttribute("ImpartedPitch", attrib4, sizeof(attrib4), true)))
|
|
{
|
|
ParseFloatArray(attrib, 3, PosInfo.ImpartedVelocity);
|
|
PosInfo.ImpartedSpin = (float) atof(attrib2);
|
|
PosInfo.ImpartedRoll = (float) atof(attrib3);
|
|
PosInfo.ImpartedPitch = (float) atof(attrib4);
|
|
}
|
|
}
|
|
if ((bitmask & 0x0100) &&
|
|
(GetXmlAttribute("UpdatePeriod", attrib, sizeof(attrib), true)))
|
|
{
|
|
PosInfo.UpdatePeriod = atoi(attrib);
|
|
}
|
|
|
|
current_object->CopyPostionInfo(&PosInfo);
|
|
|
|
UpdateBoundaries(current_sector, PosInfo.Position);
|
|
}
|
|
// else missing a required attribute sets m_Success to false
|
|
}
|
|
else
|
|
{
|
|
printf("ParseSectorContent: <Relationship> must be contained within a <GameObject>\n");
|
|
m_Success = false;
|
|
}
|
|
break;
|
|
|
|
case XML_TAG_ID_PLANET_POSITIONAL_UPDATE :
|
|
if (current_object)
|
|
{
|
|
// Parse the required attributes
|
|
if ((GetXmlAttribute("Position", attrib, sizeof(attrib), true)) &&
|
|
(GetXmlAttribute("OrbitID", attrib2, sizeof(attrib2), true)) &&
|
|
(GetXmlAttribute("OrbitDist", attrib3, sizeof(attrib3), true)) &&
|
|
(GetXmlAttribute("OrbitAngle", attrib4, sizeof(attrib4), true)))
|
|
{
|
|
// We ignore the Timestamp attribute
|
|
PositionInformation PosInfo;
|
|
memset(&PosInfo, 0, sizeof(PosInfo));
|
|
|
|
current_object->SetPositionType(POSITION_PLANET);
|
|
ParseFloatArray(attrib, 3, PosInfo.Position);
|
|
current_object->SetPosition(PosInfo.Position);
|
|
|
|
PosInfo.OrbitID = atoi(attrib2);
|
|
PosInfo.OrbitDist = (float) atof(attrib3);
|
|
PosInfo.OrbitAngle = (float) atof(attrib4);
|
|
// Parse the other required attributes
|
|
if ((GetXmlAttribute("OrbitRate", attrib, sizeof(attrib), true)) &&
|
|
(GetXmlAttribute("RotateAngle", attrib2, sizeof(attrib2), true)) &&
|
|
(GetXmlAttribute("RotateRate", attrib3, sizeof(attrib3), true)) &&
|
|
(GetXmlAttribute("TiltAngle", attrib4, sizeof(attrib4), true)))
|
|
{
|
|
PosInfo.OrbitRate = (float) atof(attrib);
|
|
PosInfo.RotateAngle = (float) atof(attrib2);
|
|
PosInfo.RotateRate = (float) atof(attrib3);
|
|
PosInfo.TiltAngle = (float) atof(attrib4);
|
|
}
|
|
|
|
current_object->CopyPostionInfo(&PosInfo);
|
|
}
|
|
// else missing a required attribute sets m_Success to false
|
|
}
|
|
else
|
|
{
|
|
printf("ParseSectorContent: <Relationship> must be contained within a <GameObject>\n");
|
|
m_Success = false;
|
|
}
|
|
break;
|
|
|
|
case XML_TAG_ID_CONSTANT_POSITIONAL_UPDATE :
|
|
if (current_object)
|
|
{
|
|
// Parse the required attributes
|
|
if ((GetXmlAttribute("Position", attrib, sizeof(attrib), true)) &&
|
|
(GetXmlAttribute("Orientation", attrib2, sizeof(attrib2), true)))
|
|
{
|
|
float pos[3], orientation[4];
|
|
ParseFloatArray(attrib, 3, pos);
|
|
ParseFloatArray(attrib2, 4, orientation);
|
|
UpdateBoundaries(current_sector, pos);
|
|
|
|
current_object->SetPositionType(POSITION_CONSTANT);
|
|
current_object->SetPosition(pos);
|
|
current_object->SetOrientation(orientation);
|
|
current_object->PopulateSpawn(false);
|
|
}
|
|
// else missing a required attribute sets m_Success to false
|
|
}
|
|
else
|
|
{
|
|
printf("ParseSectorContent: <Relationship> must be contained within a <GameObject>\n");
|
|
m_Success = false;
|
|
}
|
|
break;
|
|
|
|
case XML_TAG_ID_COMPONENT_POSITIONAL_UPDATE :
|
|
if (current_object)
|
|
{
|
|
// Parse the required attributes
|
|
if ((GetXmlAttribute("Position", attrib, sizeof(attrib), true)) &&
|
|
(GetXmlAttribute("Orientation", attrib2, sizeof(attrib2), true)) &&
|
|
(GetXmlAttribute("Velocity", attrib3, sizeof(attrib3), true)) &&
|
|
(GetXmlAttribute("ImpartedDecay", attrib4, sizeof(attrib4), true)))
|
|
{
|
|
// We ignore the Timestamp attribute
|
|
// We ignore the Timestamp attribute
|
|
PositionInformation PosInfo;
|
|
memset(&PosInfo, 0, sizeof(PosInfo));
|
|
|
|
PosInfo.type = POSITION_COMPONENT;
|
|
ParseFloatArray(attrib, 3, PosInfo.Position);
|
|
ParseFloatArray(attrib2, 4, PosInfo.Orientation);
|
|
ParseFloatArray(attrib3, 3, PosInfo.Velocity);
|
|
|
|
current_object->SetPositionType(POSITION_COMPONENT);
|
|
current_object->SetPosition(PosInfo.Position);
|
|
current_object->SetOrientation(PosInfo.Orientation);
|
|
current_object->SetVelocityVector(PosInfo.Velocity);
|
|
|
|
PosInfo.ImpartedDecay = (float) atof(attrib4);
|
|
// Parse the other required attributes
|
|
if ((GetXmlAttribute("TractorSpeed", attrib, sizeof(attrib), true)) &&
|
|
(GetXmlAttribute("TractorID", attrib2, sizeof(attrib2), true)) &&
|
|
(GetXmlAttribute("TractorEffectID", attrib3, sizeof(attrib3), true)))
|
|
{
|
|
PosInfo.TractorSpeed = (float) atof(attrib);
|
|
PosInfo.TractorID = atoi(attrib2);
|
|
PosInfo.TractorEffectID = atoi(attrib3);
|
|
}
|
|
|
|
current_object->CopyPostionInfo(&PosInfo);
|
|
UpdateBoundaries(current_sector, PosInfo.Position);
|
|
}
|
|
// else missing a required attribute sets m_Success to false
|
|
}
|
|
else
|
|
{
|
|
printf("ParseSectorContent: <Relationship> must be contained within a <GameObject>\n");
|
|
m_Success = false;
|
|
}
|
|
break;
|
|
|
|
case XML_TAG_ID_NAVIGATION :
|
|
if (current_object)
|
|
{
|
|
// Parse the required attributes
|
|
if ((GetXmlAttribute("Signature", attrib, sizeof(attrib), true)) &&
|
|
(GetXmlAttribute("PlayerHasVisited", attrib2, sizeof(attrib2), true)) &&
|
|
(GetXmlAttribute("NavType", attrib3, sizeof(attrib3), true)) &&
|
|
(GetXmlAttribute("IsHuge", attrib4, sizeof(attrib4), true)))
|
|
{
|
|
long NavType = atoi(attrib3);
|
|
|
|
//TODO: remove once DASE DB is fixed
|
|
if (0 == strcmp(current_object->Name(), "Border Demarcation"))
|
|
{
|
|
NavType = 0;
|
|
}
|
|
|
|
if (NavType != 0)
|
|
{
|
|
if (current_object->ObjectType() == OT_DECO)
|
|
{
|
|
current_object->SetObjectType(OT_NAV);
|
|
}
|
|
}
|
|
|
|
if (atoi(attrib4)) current_object->SetHuge();
|
|
|
|
//check for potential problems
|
|
if (current_object->ObjectType() == OT_STATION ||
|
|
current_object->ObjectType() == OT_STARGATE)
|
|
{
|
|
if (NavType == 0 && current_sector->sector_id > 1014 && current_sector->sector_id < 1100)
|
|
{
|
|
//LogMessage("Potential problem with object '%s'. Nav Type is set to %d\n", current_object->Name(), NavType);
|
|
NavType = 2;
|
|
}
|
|
current_object->SetRadarRange(atof(attrib));
|
|
}
|
|
|
|
if (current_object->ObjectType() == OT_PLANET)
|
|
{
|
|
if (current_object->IsHuge())
|
|
{
|
|
current_object->SetRadarRange(atof(attrib));
|
|
if (NavType == 0) NavType = 2;
|
|
}
|
|
}
|
|
|
|
current_object->SetNavInfo();
|
|
current_object->SetNavType(NavType);
|
|
current_object->SetSignature((float) atof(attrib));
|
|
|
|
//see if this is a 'resource' or 'mining' point
|
|
//first draft for random content gen
|
|
//remove once we get some resource stuff happening
|
|
Field *field;
|
|
|
|
if (current_sector->sector_id == 4095) //Arduinne gas planet
|
|
{
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
field = (Field*)current_sector->obj_manager->AddNewObject(OT_FIELD);
|
|
field->SetFieldRadius(float(500*(rand()%4 + 4)));
|
|
field->SetLevel(rand()%3 + 6);
|
|
field->SetFieldCount(2*(rand()%5 + 4));
|
|
field->SetFieldType(5);
|
|
field->SetPosition(current_object->Position());
|
|
field->MovePosition((rand()%20 - 10)*100.0f, (rand()%20 - 10)*100.0f, (rand()%20 - 10)*20.0f);
|
|
field->PopulateField(false);
|
|
}
|
|
}
|
|
else if (strstr(current_object->Name(), "Gas Field") != 0 ||
|
|
current_sector->sector_id == 4030 )
|
|
{
|
|
field = (Field*)current_sector->obj_manager->AddNewObject(OT_FIELD);
|
|
field->SetFieldRadius(float(500*(rand()%4 + 4)));
|
|
|
|
if (strchr(current_object->Name(), '1') != 0)
|
|
{
|
|
field->SetLevel(2);
|
|
}
|
|
else if (strchr(current_object->Name(), '2') != 0)
|
|
{
|
|
field->SetLevel(3);
|
|
}
|
|
else if (strchr(current_object->Name(), '3') != 0)
|
|
{
|
|
field->SetLevel(5);
|
|
}
|
|
else
|
|
{
|
|
field->SetLevel(6);
|
|
}
|
|
field->SetFieldCount(4*(rand()%5 + 4));
|
|
field->SetFieldType(5);
|
|
field->SetPosition(current_object->Position());
|
|
field->MovePosition((rand()%20 - 10)*100.0f, (rand()%20 - 10)*100.0f, (rand()%20 - 10)*20.0f);
|
|
field->PopulateField(false);
|
|
}
|
|
else if (strstr(current_object->Name(), "Resource") != 0 ||
|
|
strstr(current_object->Name(), "Mining") != 0 ||
|
|
strstr(current_object->Name(), "Pit") != 0 ||
|
|
(rand()%21 > 20) )
|
|
{
|
|
field = (Field*)current_sector->obj_manager->AddNewObject(OT_FIELD);
|
|
field->SetFieldRadius(float(900*(rand()%4 + 9)));
|
|
field->SetLevel(rand()%6 + 1);
|
|
field->SetFieldCount(4*(rand()%5 + 4));
|
|
field->SetFieldType(rand()%5 + 1);
|
|
field->SetPosition(current_object->Position());
|
|
field->MovePosition((rand()%20 - 10)*100.0f, (rand()%20 - 10)*100.0f, -(rand()%20 + 30)*50.0f);
|
|
field->PopulateField(false);
|
|
}
|
|
}
|
|
// else missing a required attribute sets m_Success to false
|
|
}
|
|
else
|
|
{
|
|
printf("ParseSectorContent: <Relationship> must be contained within a <GameObject>\n");
|
|
m_Success = false;
|
|
}
|
|
break;
|
|
|
|
case XML_TAG_ID_DESTINATION :
|
|
if (current_object)
|
|
{
|
|
if (current_object->CreateType() == 11 || current_object->CreateType() == 3)
|
|
{
|
|
// Parse the required attributes
|
|
if (GetXmlAttribute("ID", attrib, sizeof(attrib), true))
|
|
{
|
|
current_object->SetDestination(atoi(attrib));
|
|
}
|
|
// else missing a required attribute sets m_Success to false
|
|
}
|
|
else
|
|
{
|
|
printf("ParseSectorContent: <Destination> must be associated with a Gate (Type=11) or Planet (Type=3)\n");
|
|
m_Success = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("ParseSectorContent: <Destination> must be contained within a <GameObject>\n");
|
|
m_Success = false;
|
|
}
|
|
break;
|
|
|
|
case XML_TAG_ID_GREETINGS :
|
|
if (current_sector)
|
|
{
|
|
if (!GetXmlData(&p, current_sector->greetings, sizeof(current_sector->greetings)))
|
|
{
|
|
printf("ParseSectorContent: Unable to parse tag: %s", m_Tag);
|
|
m_Success = false;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default :
|
|
printf("ParseSectorContent: Unrecognized tag: %s", m_Tag);
|
|
m_Success = false;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
done = true;
|
|
}
|
|
|
|
if (*p == '\0')
|
|
{
|
|
done = true;
|
|
}
|
|
|
|
// Bail out of the loop if we detected an error
|
|
if (!m_Success)
|
|
{
|
|
done = true;
|
|
}
|
|
|
|
};
|
|
|
|
/////////////////////////
|
|
// PARSING IS COMPLETE
|
|
/////////////////////////
|
|
|
|
return (m_Success);
|
|
}
|
|
|
|
SectorData * SectorContentParser::GetSectorData()
|
|
{
|
|
return (m_SectorList);
|
|
}
|
|
|
|
void SectorContentParser::UpdateBoundaries(SectorData *sector, float *position) //find the boundaries for this sector
|
|
{
|
|
if (position[0] > sector->m_xmax)
|
|
{
|
|
sector->m_xmax = position[0];
|
|
}
|
|
else if (position[0] < sector->m_xmin)
|
|
{
|
|
sector->m_xmin = position[0];
|
|
}
|
|
|
|
if (position[1] > sector->m_ymax)
|
|
{
|
|
sector->m_ymax = position[1];
|
|
}
|
|
else if (position[1] < sector->m_ymin)
|
|
{
|
|
sector->m_ymin = position[1];
|
|
}
|
|
}
|
|
|
|
#endif
|