/** * @brief Saves player's standings with the factions. * * @param writer The xml writer to use. * @return 0 on success. */ int pfaction_save( xmlTextWriterPtr writer ) { int i; xmlw_startElem(writer,"factions"); for (i=1; i<faction_nstack; i++) { /* player is faction 0 */ /* Must not be static. */ if (faction_isFlag( &faction_stack[i], FACTION_STATIC )) continue; xmlw_startElem(writer,"faction"); xmlw_attr(writer,"name","%s",faction_stack[i].name); xmlw_elem(writer, "standing", "%f", faction_stack[i].player); if (faction_isKnown_(&faction_stack[i])) xmlw_elemEmpty(writer, "known"); xmlw_endElem(writer); /* "faction" */ } xmlw_endElem(writer); /* "factions" */ return 0; }
/** * @brief Loads the player's faction standings. * * @param parent Parent xml node to read from. * @return 0 on success. */ int pfaction_load( xmlNodePtr parent ) { xmlNodePtr node, cur; char *str; int faction; node = parent->xmlChildrenNode; do { if (xml_isNode(node,"factions")) { cur = node->xmlChildrenNode; do { if (xml_isNode(cur,"faction")) { xmlr_attr(cur,"name",str); faction = faction_get(str); if (faction != -1) { /* Faction is valid. */ /* Must not be static. */ if (!faction_isFlag( &faction_stack[faction], FACTION_STATIC )) faction_stack[faction].player = xml_getFloat(cur); } free(str); } } while (xml_nextNode(cur)); } } while (xml_nextNode(node)); return 0; }
/** * @brief Gets all the known factions. */ int* faction_getKnown( int *n ) { int i; int *f; int m; /* Set up. */ f = malloc( sizeof(int) * faction_nstack ); /* Get IDs. */ m = 0; for (i=0; i<faction_nstack; i++) if (!faction_isFlag( &faction_stack[i], FACTION_INVISIBLE ) && faction_isKnown_( &faction_stack[i] )) f[m++] = i; *n = m; return f; }
/** * @brief Modifies the player's standing without affecting others. * * Does not affect allies nor enemies. * * @param f Faction whose standing to modiy. * @param mod Amount to modiy standing by. * * @sa faction_modPlayer */ void faction_modPlayerRaw( int f, double mod ) { Faction *faction; if (!faction_isFaction(f)) { WARN("%d is an invalid faction", f); return; } faction = &faction_stack[f]; /* Make sure it's not static. */ if (faction_isFlag(faction, FACTION_STATIC)) return; faction->player += mod; faction_sanitizePlayer(faction); }
/** * @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 Mods player using the power of Lua. */ static void faction_modPlayerLua( int f, double mod, const char *source, int secondary ) { Faction *faction; lua_State *L; int errf; double old, delta; HookParam hparam[3]; faction = &faction_stack[f]; /* Make sure it's not static. */ if (faction_isFlag(faction, FACTION_STATIC)) return; L = faction->state; old = faction->player; if (L == NULL) faction->player += mod; else { #if DEBUGGING lua_pushcfunction(L, nlua_errTrace); errf = -6; #else /* DEBUGGING */ errf = 0; #endif /* DEBUGGING */ /* Set up the function: * faction_hit( current, amount, source, secondary ) */ lua_getglobal( L, "faction_hit" ); lua_pushnumber( L, faction->player ); lua_pushnumber( L, mod ); lua_pushstring( L, source ); lua_pushboolean( L, secondary ); /* Call function. */ if (lua_pcall( L, 4, 1, errf )) { /* An error occurred. */ WARN("Faction '%s': %s", faction->name, lua_tostring(L,-1)); #if DEBUGGING lua_pop( L, 2 ); #else /* DEBUGGING */ lua_pop( L, 1 ); #endif /* DEBUGGING */ return; } /* Parse return. */ if (!lua_isnumber( L, -1 )) WARN( "Lua script for faction '%s' did not return a number from 'faction_hit(...)'.", faction->name ); else faction->player = lua_tonumber( L, -1 ); #if DEBUGGING lua_pop( L, 2 ); #else /* DEBUGGING */ lua_pop( L, 1 ); #endif /* DEBUGGING */ } /* Sanitize just in case. */ faction_sanitizePlayer( faction ); /* Run hook if necessary. */ delta = faction->player - old; if (fabs(delta) > 1e-10) { hparam[0].type = HOOK_PARAM_FACTION; hparam[0].u.lf.f = f; hparam[1].type = HOOK_PARAM_NUMBER; hparam[1].u.num = delta; hparam[2].type = HOOK_PARAM_SENTINEL; hooks_runParam( "standing", hparam ); /* Tell space the faction changed. */ space_factionChange(); } }