/** * @brief Parses an xml node containing a DTYPE. * * @param temp Address to load DTYPE into. * @param parent XML Node containing the DTYPE data. * @return 0 on success. */ static int DTYPE_parse( DTYPE *temp, const xmlNodePtr parent ) { xmlNodePtr node; /* Clear data. */ memset( temp, 0, sizeof(DTYPE) ); /* Get the name (mallocs). */ temp->name = xml_nodeProp(parent,"name"); /* Extract the data. */ node = parent->xmlChildrenNode; do { xml_onlyNodes(node); xmlr_float(node, "shield", temp->sdam); xmlr_float(node, "armour", temp->adam); xmlr_float(node, "knockback", temp->knock); WARN("Unknown node of type '%s' in damage node '%s'.", node->name, temp->name); } while (xml_nextNode(node)); #define MELEMENT(o,s) \ if (o) WARN("DTYPE '%s' invalid '"s"' element", temp->name) /**< Define to help check for data errors. */ MELEMENT(temp->sdam<0.,"shield"); MELEMENT(temp->adam<0.,"armour"); MELEMENT(temp->knock<0.,"knockback"); #undef MELEMENT return 0; }
/** * @brief Parses an xml node containing a SPFX. * * @param temp Address to load SPFX into. * @param parent XML Node containing the SPFX data. * @return 0 on success. */ static int spfx_base_parse( SPFX_Base *temp, const xmlNodePtr parent ) { xmlNodePtr node; /* Clear data. */ memset( temp, 0, sizeof(SPFX_Base) ); /* Get the name (mallocs). */ temp->name = xml_nodeProp(parent,"name"); /* Extract the data. */ node = parent->xmlChildrenNode; do { xmlr_float(node, "anim", temp->anim); xmlr_float(node, "ttl", temp->ttl); if (xml_isNode(node,"gfx")) temp->gfx = xml_parseTexture( node, SPFX_GFX_PRE"%s"SPFX_GFX_SUF, 6, 5, 0 ); } while (xml_nextNode(node)); /* Convert from ms to s. */ temp->anim /= 1000.; temp->ttl /= 1000.; if (temp->ttl == 0.) temp->ttl = temp->anim; #define MELEMENT(o,s) \ if (o) WARN("SPFX '%s' missing/invalid '"s"' element", temp->name) /**< Define to help check for data errors. */ MELEMENT(temp->anim==0.,"anim"); MELEMENT(temp->ttl==0.,"ttl"); MELEMENT(temp->gfx==NULL,"gfx"); #undef MELEMENT return 0; }
/** * @brief Parses the social tidbits of a faction: allies and enemies. * * @param parent Node containing the faction. */ static void faction_parseSocial( xmlNodePtr parent ) { xmlNodePtr node, cur; char *buf; Faction *base; int mod; int mem; buf = xml_nodeProp(parent,"name"); base = &faction_stack[faction_get(buf)]; free(buf); node = parent->xmlChildrenNode; do { /* Grab the allies */ if (xml_isNode(node,"allies")) { cur = node->xmlChildrenNode; mem = 0; do { if (xml_isNode(cur,"ally")) { mod = faction_get(xml_get(cur)); base->nallies++; if (base->nallies > mem) { mem += CHUNK_SIZE; base->allies = realloc(base->allies, sizeof(int)*mem); } base->allies[base->nallies-1] = mod; } } while (xml_nextNode(cur)); if (base->nallies > 0) base->allies = realloc(base->allies, sizeof(int)*base->nallies); } /* Grab the enemies */ if (xml_isNode(node,"enemies")) { cur = node->xmlChildrenNode; mem = 0; do { if (xml_isNode(cur,"enemy")) { mod = faction_get(xml_get(cur)); base->nenemies++; if (base->nenemies > mem) { mem += CHUNK_SIZE; base->enemies = realloc(base->enemies, sizeof(int)*mem); } base->enemies[base->nenemies-1] = mod; } } while (xml_nextNode(cur)); if (base->nenemies > 0) base->enemies = realloc(base->enemies, sizeof(int)*base->nenemies); } } while (xml_nextNode(node)); }
/** * @brief Parses a single faction, but doesn't set the allies/enemies bit. * * @param temp Faction to load data into. * @param parent Parent node to extract faction from. * @return Faction created from parent node. */ static int faction_parse( Faction* temp, xmlNodePtr parent ) { xmlNodePtr node; int player; char buf[PATH_MAX]; /* Clear memory. */ memset( temp, 0, sizeof(Faction) ); temp->name = xml_nodeProp(parent,"name"); if (temp->name == NULL) WARN("Faction from "FACTION_DATA" has invalid or no name"); player = 0; node = parent->xmlChildrenNode; do { /* Can be 0 or negative, so we have to take that into account. */ if (xml_isNode(node,"player")) { temp->player_def = xml_getFloat(node); player = 1; continue; } xmlr_strd(node,"longname",temp->longname); if (xml_isNode(node, "colour")) temp->colour = col_fromName(xml_raw(node)); if (xml_isNode(node,"logo")) { snprintf( buf, PATH_MAX, FACTION_LOGO_PATH"%s_small.png", xml_get(node)); temp->logo_small = gl_newImage(buf, 0); continue; } if (xml_isNode(node,"static")) { faction_setFlag(temp, FACTION_STATIC); continue; } if (xml_isNode(node,"invisible")) { faction_setFlag(temp, FACTION_INVISIBLE); continue; } } while (xml_nextNode(node)); if (player==0) DEBUG("Faction '%s' missing player tag.", temp->name); return 0; }
/** * @brief Loads up an event from an XML node. * * @param temp Event to load up. * @param parent Event parent node. * @return 0 on success. */ static int event_parse( EventData_t *temp, const xmlNodePtr parent ) { xmlNodePtr node, cur; char str[PATH_MAX] = "\0"; char *buf; #ifdef DEBUGGING /* To check if mission is valid. */ lua_State *L; int ret; uint32_t len; #endif /* DEBUGGING */ memset( temp, 0, sizeof(EventData_t) ); /* get the name */ temp->name = xml_nodeProp(parent,"name"); if (temp->name == NULL) WARN("Event in "EVENT_DATA" has invalid or no name"); node = parent->xmlChildrenNode; do { /* load all the data */ /* Only check nodes. */ xml_onlyNodes(node); if (xml_isNode(node,"lua")) { snprintf( str, PATH_MAX, EVENT_LUA_PATH"%s.lua", xml_get(node) ); temp->lua = strdup( str ); str[0] = '\0'; #ifdef DEBUGGING /* Check to see if syntax is valid. */ L = luaL_newstate(); buf = ndata_read( temp->lua, &len ); ret = luaL_loadbuffer(L, buf, len, temp->name ); if (ret == LUA_ERRSYNTAX) { WARN("Event Lua '%s' of mission '%s' syntax error: %s", temp->name, temp->lua, lua_tostring(L,-1) ); } free(buf); lua_close(L); #endif /* DEBUGGING */ continue; } /* Trigger. */ else if (xml_isNode(node,"trigger")) { buf = xml_get(node); if (buf == NULL) WARN("Event '%s': Null trigger type.", temp->name); else if (strcmp(buf,"enter")==0) temp->trigger = EVENT_TRIGGER_ENTER; else if (strcmp(buf,"land")==0) temp->trigger = EVENT_TRIGGER_LAND; else WARN("Event '%s' has invalid 'trigger' parameter: %s", temp->name, buf); continue; } /* Flags. */ else if (xml_isNode(node,"flags")) { /* set the various flags */ cur = node->children; do { if (xml_isNode(cur,"unique")) temp->flags |= EVENT_FLAG_UNIQUE; } while (xml_nextNode(cur)); continue; } /* Condition. */ xmlr_strd(node,"cond",temp->cond); /* Get chance. */ xmlr_float(node,"chance",temp->chance); DEBUG("Unknown node '%s' in event '%s'", node->name, temp->name); } while (xml_nextNode(node)); /* Process. */ temp->chance /= 100.; #define MELEMENT(o,s) \ if (o) WARN("Mission '%s' missing/invalid '"s"' element", temp->name) MELEMENT(temp->lua==NULL,"lua"); MELEMENT(temp->chance==0.,"chance"); MELEMENT(temp->trigger==EVENT_TRIGGER_NULL,"trigger"); #undef MELEMENT return 0; }
/** * @brief Parses a single faction, but doesn't set the allies/enemies bit. * * @param temp Faction to load data into. * @param parent Parent node to extract faction from. * @return Faction created from parent node. */ static int faction_parse( Faction* temp, xmlNodePtr parent ) { xmlNodePtr node; int player; char buf[PATH_MAX], *dat; uint32_t ndat; /* Clear memory. */ memset( temp, 0, sizeof(Faction) ); temp->name = xml_nodeProp(parent,"name"); if (temp->name == NULL) WARN("Faction from "FACTION_DATA_PATH" has invalid or no name"); player = 0; node = parent->xmlChildrenNode; do { /* Only care about nodes. */ xml_onlyNodes(node); /* Can be 0 or negative, so we have to take that into account. */ if (xml_isNode(node,"player")) { temp->player_def = xml_getFloat(node); player = 1; continue; } xmlr_strd(node,"longname",temp->longname); xmlr_strd(node,"display",temp->displayname); if (xml_isNode(node, "colour")) { temp->colour = col_fromName(xml_raw(node)); continue; } if (xml_isNode(node, "spawn")) { if (temp->sched_state != NULL) WARN("Faction '%s' has duplicate 'spawn' tag.", temp->name); nsnprintf( buf, sizeof(buf), "dat/factions/spawn/%s.lua", xml_raw(node) ); temp->sched_state = nlua_newState(); nlua_loadStandard( temp->sched_state, 0 ); dat = ndata_read( buf, &ndat ); if (luaL_dobuffer(temp->sched_state, dat, ndat, buf) != 0) { WARN("Failed to run spawn script: %s\n" "%s\n" "Most likely Lua file has improper syntax, please check", buf, lua_tostring(temp->sched_state,-1)); lua_close( temp->sched_state ); temp->sched_state = NULL; } free(dat); continue; } if (xml_isNode(node, "standing")) { if (temp->state != NULL) WARN("Faction '%s' has duplicate 'standing' tag.", temp->name); nsnprintf( buf, sizeof(buf), "dat/factions/standing/%s.lua", xml_raw(node) ); temp->state = nlua_newState(); nlua_loadStandard( temp->state, 0 ); dat = ndata_read( buf, &ndat ); if (luaL_dobuffer(temp->state, dat, ndat, buf) != 0) { WARN("Failed to run standing script: %s\n" "%s\n" "Most likely Lua file has improper syntax, please check", buf, lua_tostring(temp->state,-1)); lua_close( temp->state ); temp->state = NULL; } free(dat); continue; } if (xml_isNode(node, "known")) { faction_setFlag(temp, FACTION_KNOWN); continue; } if (xml_isNode(node, "equip")) { if (temp->equip_state != NULL) WARN("Faction '%s' has duplicate 'equip' tag.", temp->name); nsnprintf( buf, sizeof(buf), "dat/factions/equip/%s.lua", xml_raw(node) ); temp->equip_state = nlua_newState(); nlua_loadStandard( temp->equip_state, 0 ); dat = ndata_read( buf, &ndat ); if (luaL_dobuffer(temp->equip_state, dat, ndat, buf) != 0) { WARN("Failed to run equip script: %s\n" "%s\n" "Most likely Lua file has improper syntax, please check", buf, lua_tostring(temp->equip_state,-1)); lua_close( temp->equip_state ); temp->equip_state = NULL; } free(dat); continue; } if (xml_isNode(node,"logo")) { if (temp->logo_small != NULL) WARN("Faction '%s' has duplicate 'logo' tag.", temp->name); nsnprintf( buf, PATH_MAX, FACTION_LOGO_PATH"%s_small.png", xml_get(node)); temp->logo_small = gl_newImage(buf, 0); nsnprintf( buf, PATH_MAX, FACTION_LOGO_PATH"%s_tiny.png", xml_get(node)); temp->logo_tiny = gl_newImage(buf, 0); continue; } if (xml_isNode(node,"static")) { faction_setFlag(temp, FACTION_STATIC); continue; } if (xml_isNode(node,"invisible")) { faction_setFlag(temp, FACTION_INVISIBLE); continue; } /* Avoid warnings. */ if (xml_isNode(node,"allies") || xml_isNode(node,"enemies")) continue; DEBUG("Unknown node '%s' in faction '%s'",node->name,temp->name); } while (xml_nextNode(node)); if (player==0) DEBUG("Faction '%s' missing player tag.", temp->name); if ((temp->state!=NULL) && faction_isFlag( temp, FACTION_STATIC )) WARN("Faction '%s' has Lua and is static!", temp->name); if ((temp->state==NULL) && !faction_isFlag( temp, FACTION_STATIC )) WARN("Faction '%s' has no Lua and isn't static!", temp->name); return 0; }
/** * @brief Parses an XML tech node. */ static int tech_parseNodeData( tech_group_t *tech, xmlNodePtr parent ) { xmlNodePtr node; char *buf, *name; int ret; /* Parse the data. */ node = parent->xmlChildrenNode; do { xml_onlyNodes(node); if (xml_isNode(node,"item")) { /* Must have name. */ name = xml_get( node ); if (name == NULL) { WARN("Tech group '%s' has an item without a value.", tech->name); continue; } /* Try to find hardcoded type. */ buf = xml_nodeProp( node, "type" ); if (buf == NULL) { ret = 1; if (ret) ret = tech_addItemGroup( tech, name ); if (ret) ret = tech_addItemOutfit( tech, name ); if (ret) ret = tech_addItemShip( tech, name ); if (ret) ret = tech_addItemCommodity( tech, name ); if (ret) { WARN("Generic item '%s' not found in tech group '%s'", name, tech->name ); continue; } } else if (strcmp(buf,"group")==0) { if (!tech_addItemGroup( tech, name )) { WARN("Group item '%s' not found in tech group '%s'.", name, tech->name ); continue; } } else if (strcmp(buf,"outfit")==0) { if (!tech_addItemGroup( tech, name )) { WARN("Outfit item '%s' not found in tech group '%s'.", name, tech->name ); continue; } } else if (strcmp(buf,"ship")==0) { if (!tech_addItemGroup( tech, name )) { WARN("Ship item '%s' not found in tech group '%s'.", name, tech->name ); continue; } } else if (strcmp(buf,"commodity")==0) { if (!tech_addItemGroup( tech, name )) { WARN("Commodity item '%s' not found in tech group '%s'.", name, tech->name ); continue; } } continue; } WARN("Tech group '%s' has unknown node '%s'.", tech->name, node->name); } while (xml_nextNode( node )); return 0; }
/** * @brief Parses a node of a mission. * * @param temp Data to load into. * @param parent Node containing the mission. * @return 0 on success. */ static int mission_parse( MissionData* temp, const xmlNodePtr parent ) { xmlNodePtr cur, node; #ifdef DEBUGGING /* To check if mission is valid. */ lua_State *L; int ret; char *buf; uint32_t len; #endif /* DEBUGGING */ /* Clear memory. */ memset( temp, 0, sizeof(MissionData) ); /* Defaults. */ temp->avail.priority = 5; /* get the name */ temp->name = xml_nodeProp(parent,"name"); if (temp->name == NULL) WARN("Mission in "MISSION_DATA_PATH" has invalid or no name"); node = parent->xmlChildrenNode; char str[PATH_MAX] = "\0"; do { /* load all the data */ /* Only handle nodes. */ xml_onlyNodes(node); if (xml_isNode(node,"lua")) { nsnprintf( str, PATH_MAX, MISSION_LUA_PATH"%s.lua", xml_get(node) ); temp->lua = strdup( str ); str[0] = '\0'; #ifdef DEBUGGING /* Check to see if syntax is valid. */ L = luaL_newstate(); buf = ndata_read( temp->lua, &len ); ret = luaL_loadbuffer(L, buf, len, temp->name ); if (ret == LUA_ERRSYNTAX) { WARN("Mission Lua '%s' of mission '%s' syntax error: %s", temp->name, temp->lua, lua_tostring(L,-1) ); } free(buf); lua_close(L); #endif /* DEBUGGING */ continue; } else if (xml_isNode(node,"flags")) { /* set the various flags */ cur = node->children; do { xml_onlyNodes(cur); if (xml_isNode(cur,"unique")) { mis_setFlag(temp,MISSION_UNIQUE); continue; } WARN("Mission '%s' has unknown flag node '%s'.", temp->name, cur->name); } while (xml_nextNode(cur)); continue; } else if (xml_isNode(node,"avail")) { /* mission availability */ cur = node->children; do { xml_onlyNodes(cur); if (xml_isNode(cur,"location")) { temp->avail.loc = mission_location( xml_get(cur) ); continue; } xmlr_int(cur,"chance",temp->avail.chance); xmlr_strd(cur,"planet",temp->avail.planet); xmlr_strd(cur,"system",temp->avail.system); if (xml_isNode(cur,"faction")) { temp->avail.factions = realloc( temp->avail.factions, sizeof(int) * ++temp->avail.nfactions ); temp->avail.factions[temp->avail.nfactions-1] = faction_get( xml_get(cur) ); continue; } xmlr_strd(cur,"cond",temp->avail.cond); xmlr_strd(cur,"done",temp->avail.done); xmlr_int(cur,"priority",temp->avail.priority); WARN("Mission '%s' has unknown avail node '%s'.", temp->name, cur->name); } while (xml_nextNode(cur)); continue; } DEBUG("Unknown node '%s' in mission '%s'",node->name,temp->name); } while (xml_nextNode(node)); #define MELEMENT(o,s) \ if (o) WARN("Mission '%s' missing/invalid '"s"' element", temp->name) MELEMENT(temp->lua==NULL,"lua"); MELEMENT(temp->avail.loc==-1,"location"); MELEMENT((temp->avail.loc!=MIS_AVAIL_NONE) && (temp->avail.chance==0),"chance"); #undef MELEMENT return 0; }
/** * @brief Parses and returns Outfit from parent node. * * @param temp Outfit to load into. * @param parent Parent node to parse outfit from. * @return 0 on success. */ static int outfit_parse( Outfit* temp, const xmlNodePtr parent ) { xmlNodePtr cur, node; char *prop; /* Clear data. */ memset( temp, 0, sizeof(Outfit) ); temp->name = xml_nodeProp(parent,"name"); /* already mallocs */ if (temp->name == NULL) WARN("Outfit in "OUTFIT_DATA" has invalid or no name"); node = parent->xmlChildrenNode; do { /* load all the data */ if (xml_isNode(node,"general")) { cur = node->children; do { xmlr_int(cur,"max",temp->max); xmlr_int(cur,"tech",temp->tech); xmlr_strd(cur,"license",temp->license); xmlr_int(cur,"mass",temp->mass); xmlr_int(cur,"price",temp->price); xmlr_strd(cur,"description",temp->description); if (xml_isNode(cur,"gfx_store")) { temp->gfx_store = xml_parseTexture( cur, OUTFIT_GFX"store/%s.png", 1, 1, 0 ); } } while (xml_nextNode(cur)); } else if (xml_isNode(node,"specific")) { /* has to be processed seperately */ /* get the type */ prop = xml_nodeProp(node,"type"); if (prop == NULL) ERR("Outfit '%s' element 'specific' missing property 'type'",temp->name); temp->type = outfit_strToOutfitType(prop); free(prop); /* is secondary weapon? */ prop = xml_nodeProp(node,"secondary"); if (prop != NULL) { if ((int)atoi(prop)) outfit_setProp(temp, OUTFIT_PROP_WEAP_SECONDARY); free(prop); } if (temp->type==OUTFIT_TYPE_NULL) WARN("Outfit '%s' is of type NONE", temp->name); else if (outfit_isBolt(temp)) outfit_parseSBolt( temp, node ); else if (outfit_isBeam(temp)) outfit_parseSBeam( temp, node ); else if (outfit_isLauncher(temp)) outfit_parseSLauncher( temp, node ); else if (outfit_isAmmo(temp)) outfit_parseSAmmo( temp, node ); else if (outfit_isMod(temp)) outfit_parseSMod( temp, node ); else if (outfit_isAfterburner(temp)) outfit_parseSAfterburner( temp, node ); else if (outfit_isJammer(temp)) outfit_parseSJammer( temp, node ); else if (outfit_isFighterBay(temp)) outfit_parseSFighterBay( temp, node ); else if (outfit_isFighter(temp)) outfit_parseSFighter( temp, node ); else if (outfit_isMap(temp)) outfit_parseSMap( temp, node ); else if (outfit_isLicense(temp)) outfit_parseSLicense( temp, node ); } } while (xml_nextNode(node)); #define MELEMENT(o,s) \ if (o) WARN("Outfit '%s' missing/invalid '"s"' element", temp->name) /**< Define to help check for data errors. */ MELEMENT(temp->name==NULL,"name"); MELEMENT(temp->max==0,"max"); MELEMENT(temp->tech==0,"tech"); MELEMENT(temp->gfx_store==NULL,"gfx_store"); /*MELEMENT(temp->mass==0,"mass"); Not really needed */ MELEMENT(temp->type==0,"type"); MELEMENT(temp->price==0,"price"); MELEMENT(temp->description==NULL,"description"); #undef MELEMENT return 0; }