33#define XML_FACTION_ID "Factions"
34#define XML_FACTION_TAG "faction"
36#define FACTION_STATIC (1<<0)
37#define FACTION_INVISIBLE (1<<1)
38#define FACTION_KNOWN (1<<2)
39#define FACTION_DYNAMIC (1<<3)
40#define FACTION_USESHIDDENJUMPS (1<<4)
42#define faction_setFlag(fa,f) ((fa)->flags |= (f))
43#define faction_rmFlag(fa,f) ((fa)->flags &= ~(f))
44#define faction_isFlag(fa,f) ((fa)->flags & (f))
45#define faction_isKnown_(fa) ((fa)->flags & (FACTION_KNOWN))
54typedef struct Faction_ {
126static int faction_cmp(
const void *p1,
const void *p2 )
143 if (strcmp(name,
"Escort") == 0)
144 return FACTION_PLAYER;
186 WARN(_(
"Faction '%s' not found in stack."), name);
259 WARN(_(
"Faction id '%d' is invalid."),
id);
307 WARN(_(
"Faction id '%d' is invalid."),f);
311 if (f == FACTION_PLAYER)
326 WARN(_(
"Faction id '%d' is invalid."),f);
330 if (f == FACTION_PLAYER)
349 WARN(_(
"Faction id '%d' is invalid."),f);
366 WARN(_(
"Faction id '%d' is invalid."),f);
383 WARN(_(
"Faction id '%d' is invalid."),f);
400 WARN(_(
"Faction id '%d' is invalid."), f);
415 WARN(_(
"Faction id '%d' is invalid."), f);
427 WARN(_(
"Faction id '%d' is invalid."), f);
439 WARN(_(
"Faction id '%d' is invalid."), f);
454 WARN(_(
"Faction id '%d' is invalid."),f);
470 WARN(_(
"Faction id '%d' is invalid."),f);
486 WARN(_(
"Faction id '%d' is invalid."),f);
491 if (f == FACTION_PLAYER) {
516 WARN(_(
"Faction id '%d' is invalid."),f);
521 if (f == FACTION_PLAYER) {
549 WARN(_(
"Faction id '%d' is invalid."), f);
572 WARN(_(
"Faction id '%d' is invalid."), f);
577 WARN(_(
"Faction id '%d' is invalid."), o);
582 if (f==FACTION_PLAYER) {
583 WARN(_(
"%d is the player faction"), f);
586 if (o==FACTION_PLAYER) {
587 WARN(_(
"%d is the player faction"), o);
617 WARN(_(
"Faction id '%d' is invalid."), f);
642 WARN(_(
"Faction id '%d' is invalid."), f);
665 WARN(_(
"Faction id '%d' is invalid."), f);
670 WARN(_(
"Faction id '%d' is invalid."), o);
675 if (f==FACTION_PLAYER) {
676 WARN(_(
"%d is the player faction"), f);
679 if (o==FACTION_PLAYER) {
680 WARN(_(
"%d is the player faction"), o);
710 WARN(_(
"Faction id '%d' is invalid."), f);
729 WARN(_(
"Faction id '%d' is invalid."),f);
741 WARN(_(
"Faction id '%d' is invalid."),f);
777 if (faction->
env == LUA_NOREF)
783 lua_rawgeti( naevL, LUA_REGISTRYINDEX, faction->
lua_hit );
784 lua_rawgeti( naevL, LUA_REGISTRYINDEX, faction->
lua_standing );
785 lua_pushnumber( naevL, faction->
player );
786 lua_pushnumber( naevL, mod );
787 lua_pushstring( naevL, source );
788 lua_pushboolean( naevL, secondary );
791 if (nlua_pcall( faction->
env, 5, 1 )) {
792 WARN(_(
"Faction '%s': %s"), faction->
name, lua_tostring(naevL,-1));
798 if (!lua_isnumber( naevL, -1 ))
799 WARN( _(
"Lua script for faction '%s' did not return a number from 'standing:hit(...)'."), faction->
name );
801 faction->
player = lua_tonumber( naevL, -1 );
809 delta = faction->
player - old;
810 if (
FABS(delta) > 1e-10) {
812 hparam[0].
type = HOOK_PARAM_FACTION;
814 hparam[1].
type = HOOK_PARAM_NUMBER;
815 hparam[1].
u.
num = delta;
816 hparam[2].
type = HOOK_PARAM_SENTINEL;
844 WARN(_(
"Faction id '%d' is invalid."), f);
882 WARN(_(
"Faction id '%d' is invalid."), f);
905 WARN(_(
"Faction id '%d' is invalid."), f);
912 hparam[0].
type = HOOK_PARAM_FACTION;
914 hparam[1].
type = HOOK_PARAM_NUMBER;
915 hparam[1].
u.
num = mod;
916 hparam[2].
type = HOOK_PARAM_SENTINEL;
939 WARN(_(
"Faction id '%d' is invalid."), f);
944 mod = value - faction->
player;
948 hparam[0].
type = HOOK_PARAM_FACTION;
950 hparam[1].
type = HOOK_PARAM_NUMBER;
951 hparam[1].
u.
num = mod;
952 hparam[2].
type = HOOK_PARAM_SENTINEL;
973 WARN(_(
"Faction id '%d' is invalid."), f);
987 WARN(_(
"Faction id '%d' is invalid."), f);
1012 return faction->
player < 0;
1025 if (f<0)
return &cInert;
1026 else if (
areAllies(FACTION_PLAYER,f))
return &cFriend;
1027 else if (
areEnemies(FACTION_PLAYER,f))
return &cHostile;
1028 else return &cNeutral;
1042 if (f<0)
return 'I';
1043 else if (
areEnemies(FACTION_PLAYER,f))
return 'H';
1044 else if (
areAllies(FACTION_PLAYER,f))
return 'F';
1059 if (f == FACTION_PLAYER)
1064 if (faction->
env == LUA_NOREF)
1070 lua_rawgeti( naevL, LUA_REGISTRYINDEX, faction->
lua_text_rank );
1071 lua_rawgeti( naevL, LUA_REGISTRYINDEX, faction->
lua_standing );
1072 lua_pushnumber( naevL, faction->
player );
1075 if (nlua_pcall( faction->
env, 2, 1 )) {
1077 WARN( _(
"Faction '%s': %s"), faction->
name, lua_tostring( naevL, -1 ) );
1078 lua_pop( naevL, 1 );
1083 if (!lua_isstring( naevL, -1 )) {
1084 WARN( _(
"Lua script for faction '%s' did not return a string from 'standing:text_rank(...)'."), faction->
name );
1088 r = lua_tostring( naevL, -1 );
1089 lua_pop( naevL, 1 );
1109 if (f == FACTION_PLAYER)
1114 if (faction->
env == LUA_NOREF)
1119 lua_rawgeti( naevL, LUA_REGISTRYINDEX, faction->
lua_text_broad );
1120 lua_rawgeti( naevL, LUA_REGISTRYINDEX, faction->
lua_standing );
1121 lua_pushnumber( naevL, faction->
player );
1122 lua_pushboolean( naevL, bribed );
1123 lua_pushnumber( naevL,
override );
1126 if (nlua_pcall( faction->
env, 4, 1 )) {
1128 WARN( _(
"Faction '%s': %s"), faction->
name, lua_tostring( naevL, -1 ) );
1129 lua_pop( naevL, 1 );
1134 if (!lua_isstring( naevL, -1 )) {
1135 WARN( _(
"Lua script for faction '%s' did not return a string from 'standing:text_broad(...)'."), faction->
name );
1139 r = lua_tostring( naevL, -1 );
1140 lua_pop( naevL, 1 );
1157 if (f == FACTION_PLAYER)
1162 if (faction->
env == LUA_NOREF)
1168 lua_rawgeti( naevL, LUA_REGISTRYINDEX, faction->
lua_standing );
1171 if (nlua_pcall( faction->
env, 1, 1 )) {
1173 WARN( _(
"Faction '%s': %s"), faction->
name, lua_tostring( naevL, -1 ) );
1174 lua_pop( naevL, 1 );
1179 if (!lua_isnumber( naevL, -1 )) {
1180 WARN( _(
"Lua script for faction '%s' did not return a string from 'standing:reputation_max(...)'."), faction->
name );
1184 r = lua_tonumber( naevL, -1 );
1185 lua_pop( naevL, 1 );
1207 if (a==FACTION_PLAYER)
1209 else if (b==FACTION_PLAYER)
1232 if (a==FACTION_PLAYER)
1234 else if (b==FACTION_PLAYER)
1262 xmlNodePtr node, parent;
1269 parent = doc->xmlChildrenNode;
1270 if (parent == NULL) {
1271 ERR( _(
"Malformed '%s' file: does not contain elements"), file);
1276 memset( temp, 0,
sizeof(
Faction) );
1278 temp->
env = LUA_NOREF;
1281 xmlr_attr_strd(parent,
"name",temp->
name);
1282 if (temp->
name == NULL)
1283 WARN(_(
"Faction from file '%s' has no name!"), file);
1286 node = parent->xmlChildrenNode;
1289 xml_onlyNodes(node);
1292 if (xml_isNode(node,
"player")) {
1298 xmlr_strd(node,
"longname",temp->
longname);
1300 xmlr_strd(node,
"mapname",temp->
mapname);
1302 xmlr_strd(node,
"ai",temp->
ai);
1305 if (xml_isNode(node,
"colour")) {
1306 char *ctmp = xml_get(node);
1308 temp->
colour = *col_fromName(xml_raw(node));
1312 xmlr_attr_float(node,
"r",temp->
colour.r);
1313 xmlr_attr_float(node,
"g",temp->
colour.g);
1314 xmlr_attr_float(node,
"b",temp->
colour.b);
1316 col_gammaToLinear( &temp->
colour );
1321 if (xml_isNode(node,
"known")) {
1326 if (xml_isNode(node,
"logo")) {
1328 if (temp->
logo != NULL)
1329 WARN(_(
"Faction '%s' has duplicate 'logo' tag."), temp->
name);
1330 snprintf( buf,
sizeof(buf), FACTION_LOGO_PATH
"%s.webp", xml_get(node) );
1335 if (xml_isNode(node,
"static")) {
1340 if (xml_isNode(node,
"invisible")) {
1345 if (xml_isNode(node,
"useshiddenjumps")) {
1350 if (xml_isNode(node,
"tags")) {
1351 xmlNodePtr cur = node->children;
1352 if (temp->
tags != NULL)
1353 WARN(_(
"Faction '%s' has duplicate '%s' node!"), temp->
name,
"tags");
1358 if (xml_isNode(cur,
"tag")) {
1359 char *tmp = xml_get(cur);
1364 WARN(_(
"Faction '%s' has unknown node in tags '%s'."), temp->
name, cur->name );
1365 }
while (xml_nextNode(cur));
1371 if (xml_isNode(node,
"allies") || xml_isNode(node,
"enemies") ||
1372 xml_isNode(node,
"generator") || xml_isNode(node,
"standing") ||
1373 xml_isNode(node,
"spawn") || xml_isNode(node,
"equip"))
1375 WARN(_(
"Unknown node '%s' in faction '%s'"),node->name,temp->
name);
1378 }
while (xml_nextNode(node));
1381 WARN(_(
"Faction '%s' missing 'player' tag."), temp->
name);
1383 WARN(_(
"Faction '%s' is known but missing 'description' tag."), temp->
name);
1401 snprintf( buf,
sizeof(buf), FACTIONS_PATH
"standing/%s.lua", scriptname );
1402 temp->
env = nlua_newEnv();
1406 if (nlua_dobufenv(temp->
env, dat, ndat, buf) != 0) {
1407 WARN(_(
"Failed to run standing script: %s\n"
1409 "Most likely Lua file has improper syntax, please check"),
1410 buf, lua_tostring(naevL,-1));
1411 nlua_freeEnv( temp->
env );
1412 temp->
env = LUA_NOREF;
1424 lua_rawgeti( naevL, LUA_REGISTRYINDEX, temp->
lua_standing );
1425 lua_getfield( naevL, -1,
"friendly_at" );
1427 lua_pop( naevL, 2 );
1430 WARN(_(
"Standing script did not set the \"standing\" variable: %s"), buf);
1445 xmlNodePtr node, parent;
1452 parent = doc->xmlChildrenNode;
1453 if (parent == NULL) {
1454 ERR( _(
"Malformed '%s' file: does not contain elements"), file);
1460 xmlr_attr_strd(parent,
"name", name);
1466 assert( base != NULL );
1473 node = parent->xmlChildrenNode;
1475 if (xml_isNode(node,
"generator")) {
1480 xmlr_attr_float(node,
"weight",fg->
weight);
1486 if (xml_isNode(node,
"standing")) {
1487 if (base->
env != LUA_NOREF)
1488 WARN(_(
"Faction '%s' has duplicate 'standing' tag."), base->
name);
1494 if (xml_isNode(node,
"spawn")) {
1496 WARN(_(
"Faction '%s' has duplicate 'spawn' tag."), base->
name);
1497 snprintf( buf,
sizeof(buf), FACTIONS_PATH
"spawn/%s.lua", xml_raw(node) );
1501 if (nlua_dobufenv(base->
sched_env, dat, ndat, buf) != 0) {
1502 WARN(_(
"Failed to run spawn script: %s\n"
1504 "Most likely Lua file has improper syntax, please check"),
1505 buf, lua_tostring(naevL,-1));
1514 if (xml_isNode(node,
"equip")) {
1516 WARN(_(
"Faction '%s' has duplicate 'equip' tag."), base->
name);
1517 snprintf( buf,
sizeof(buf), FACTIONS_PATH
"equip/%s.lua", xml_raw(node) );
1521 if (nlua_dobufenv(base->
equip_env, dat, ndat, buf) != 0) {
1522 WARN(_(
"Failed to run equip script: %s\n"
1524 "Most likely Lua file has improper syntax, please check"),
1525 buf, lua_tostring(naevL, -1));
1534 if (xml_isNode(node,
"allies")) {
1535 xmlNodePtr cur = node->xmlChildrenNode;
1538 if (xml_isNode(cur,
"ally")) {
1542 }
while (xml_nextNode(cur));
1547 if (xml_isNode(node,
"enemies")) {
1548 xmlNodePtr cur = node->xmlChildrenNode;
1551 if (xml_isNode(cur,
"enemy")) {
1555 }
while (xml_nextNode(cur));
1558 }
while (xml_nextNode(node));
1561 WARN(_(
"Faction '%s' has no Lua and isn't static!"), base->
name);
1586 Uint32 time = SDL_GetTicks();
1592 memset( f, 0,
sizeof(
Faction) );
1593 f->name = strdup(
"Player");
1595 f->equip_env = LUA_NOREF;
1597 f->sched_env = LUA_NOREF;
1602 for (
int i=0; i<
array_size(faction_files); i++) {
1621 for (
int i=0; i<
array_size(faction_files); i++) {
1632 for (
int j=0; j <
array_size(f->allies); j++) {
1636 if (sf->
allies[k] == i) {
1647 for (
int j=0; j <
array_size(f->enemies); j++) {
1662 for (
int i=0; i<
array_size(faction_files); i++)
1663 free( faction_files[i] );
1669 time = SDL_GetTicks() - time;
1685 free(f->displayname);
1687 free(f->description);
1693 nlua_freeEnv( f->sched_env );
1694 nlua_freeEnv( f->env );
1696 nlua_freeEnv( f->equip_env );
1727 xmlw_startElem(writer,
"factions");
1734 xmlw_startElem(writer,
"faction");
1740 xmlw_elemEmpty(writer,
"known");
1742 xmlw_endElem(writer);
1745 xmlw_endElem(writer);
1758 xmlNodePtr node = parent->xmlChildrenNode;
1761 if (xml_isNode(node,
"factions")) {
1762 xmlNodePtr cur = node->xmlChildrenNode;
1764 if (xml_isNode(cur,
"faction")) {
1767 xmlr_attr_strd(cur,
"name", str);
1770 if (faction != -1) {
1771 xmlNodePtr sub = cur->xmlChildrenNode;
1773 if (xml_isNode(sub,
"standing")) {
1780 if (xml_isNode(sub,
"known")) {
1784 }
while (xml_nextNode(sub));
1788 }
while (xml_nextNode(cur));
1790 }
while (xml_nextNode(node));
1880int faction_dynAdd(
int base,
const char* name,
const char* display,
const char* ai,
const glColour* colour )
1883 memset( f, 0,
sizeof(
Faction) );
1884 f->name = strdup( name );
1885 f->displayname = (display==NULL) ? NULL : strdup( display );
1886 f->ai = (ai==NULL) ? NULL : strdup( ai );
1889 f->equip_env = LUA_NOREF;
1891 f->sched_env = LUA_NOREF;
1897 if (bf->
ai!=NULL && f->ai==NULL)
1898 f->
ai = strdup( bf->
ai );
1921 f->colour = *colour;
1948 WARN(
"Incoherent faction grid! '%s' and '%s' are already enemies, but trying to set to allies!",
faction_stack[i].name,
faction_stack[j].name );
1957 WARN(
"Incoherent faction grid! '%s' and '%s' are already allies, but trying to set to enemies!",
faction_stack[i].name,
faction_stack[j].name );
Provides macros to work with dynamic arrays.
#define array_free(ptr_array)
Frees memory allocated and sets array to NULL.
#define array_copy(basic_type, ptr_array)
Returns a shallow copy of the input array.
#define array_end(array)
Returns a pointer to the end of the reserved memory space.
#define array_create_size(basic_type, capacity)
Creates a new dynamic array of ‘basic_type’ with an initial capacity.
#define array_erase(ptr_array, first, last)
Erases elements in interval [first, last).
static ALWAYS_INLINE int array_size(const void *array)
Returns number of elements in the array.
#define array_grow(ptr_array)
Increases the number of elements by one and returns the last element.
#define array_push_back(ptr_array, element)
Adds a new element at the end of the array.
#define array_begin(array)
Returns a pointer to the beginning of the reserved memory space.
#define array_create(basic_type)
Creates a new dynamic array of ‘basic_type’.
const char * faction_getStandingBroad(int f, int bribed, int override)
Gets the broad faction standing.
const char * faction_longname(int f)
Gets the faction's long name (formal, human-readable).
static void faction_freeOne(Faction *f)
Frees a single faction.
const glColour * faction_getColour(int f)
Gets the colour of the faction based on it's standing with the player.
int faction_isPlayerEnemy(int f)
Gets whether or not the player is an enemy of the faction.
int faction_exists(const char *name)
Checks to see if a faction exists by name.
const char * faction_default_ai(int f)
Gets the name of the default AI profile for the faction's pilots.
const int * faction_getEnemies(int f)
Gets the list of enemies of a faction.
int faction_dynAdd(int base, const char *name, const char *display, const char *ai, const glColour *colour)
Dynamically add a faction.
static int faction_getRaw(const char *name)
Gets a faction ID by name.
void faction_rmAlly(int f, int o)
Removes an ally from the faction's allies list.
int faction_isKnown(int id)
Is the faction known?
char faction_getColourChar(int f)
Gets the faction character associated to its standing with the player.
static void faction_modPlayerLua(int f, double mod, const char *source, int secondary)
Mods player using the power of Lua.
#define FACTION_INVISIBLE
int faction_isFaction(int f)
Checks whether or not a faction is valid.
static size_t faction_mgrid
static Faction * faction_stack
const glTexture * faction_logo(int f)
Gets the faction's logo (ideally 256x256).
nlua_env faction_getEquipper(int f)
Gets the equipper state associated to the faction scheduler.
int factions_load(void)
Loads up all the factions from the data file.
void faction_clearEnemy(int f)
Clears all the enemies of a dynamic faction.
void factions_reset(void)
Resets player standing and flags of factions to default.
void faction_rmEnemy(int f, int o)
Removes an enemy from the faction's enemies list.
int faction_isPlayerFriend(int f)
Gets whether or not the player is a friend of the faction.
void faction_setPlayer(int f, double value)
Sets the player's standing with a faction.
int areEnemies(int a, int b)
Checks whether two factions are enemies.
void factions_clearDynamic(void)
Clears dynamic factions.
int * faction_getGroup(int which)
Returns an array of faction ids.
const char * faction_name(int f)
Gets a factions "real" (internal) name.
const char * faction_shortname(int f)
Gets a factions short name (human-readable).
const char * faction_getStandingText(int f)
Gets the player's standing in human readable form.
double faction_getPlayer(int f)
Gets the player's standing with a faction.
int faction_isDynamic(int id)
Is faction dynamic.
void factions_free(void)
Frees the factions.
const int * faction_getAllies(int f)
Gets the list of allies of a faction.
void faction_modPlayerRaw(int f, double mod)
Modifies the player's standing without affecting others.
const FactionGenerator * faction_generators(int f)
Gets the faction's generators.
int faction_usesHiddenJumps(int f)
Checks to see if a faction uses hidden jumps.
int * faction_getKnown()
Gets all the known factions in an array (array.h).
int faction_isInvisible(int id)
Is the faction invisible?
int pfaction_save(xmlTextWriterPtr writer)
Saves player's standings with the factions.
const glColour * faction_colour(int f)
Gets the colour of the faction.
static void faction_sanitizePlayer(Faction *faction)
Sanitizes player faction standing.
void faction_clearAlly(int f)
Clears all the ally of a dynamic faction.
int pfaction_load(xmlNodePtr parent)
Loads the player's faction standings.
double faction_lane_base_cost(int f)
Gets the faction's weight for patrolled safe-lane construction;.
void faction_modPlayer(int f, double mod, const char *source)
Modifies the player's standing with a faction.
const char ** faction_tags(int f)
Gets the tags the faction has.
static int * faction_grid
static int faction_parseSocial(const char *file)
Parses the social tidbits of a faction: allies and enemies.
#define FACTION_USESHIDDENJUMPS
double faction_getPlayerDef(int f)
Gets the player's default standing with a faction.
int * faction_getAll(void)
Returns all faction IDs in an array (array.h).
void faction_modPlayerSingle(int f, double mod, const char *source)
Modifies the player's standing without affecting others.
static void faction_addStandingScript(Faction *temp, const char *scriptname)
Sets up a standing script for a faction.
static int faction_parse(Faction *temp, const char *file)
Parses a single faction, but doesn't set the allies/enemies bit.
int faction_setInvisible(int id, int state)
Sets the faction's invisible state.
int faction_setKnown(int id, int state)
Sets the factions known state.
double faction_lane_length_per_presence(int f)
Gets the faction's weight for patrolled safe-lane construction (0 means they don't build lanes).
int * faction_getAllVisible(void)
Returns all non-invisible faction IDs in an array (array.h).
const char * faction_mapname(int f)
Gets the faction's map name (translated).
double faction_reputationMax(int f)
Gets the maximum reputation of a faction.
void faction_addAlly(int f, int o)
Adds an ally to the faction's allies list.
nlua_env faction_getScheduler(int f)
Gets the state associated to the faction scheduler.
static void faction_computeGrid(void)
Computes the faction relationship grid.
const char * faction_description(int f)
Gets the faction's description (translated).
void faction_clearKnown()
Clears the known factions.
int faction_isStatic(int id)
Is the faction static?
void faction_addEnemy(int f, int o)
Adds an enemy to the faction's enemies list.
int faction_get(const char *name)
Gets a faction ID by name.
int areAllies(int a, int b)
Checks whether two factions are allies or not.
int hooks_runParam(const char *stack, const HookParam *param)
Runs all the hooks of stack.
void naev_renderLoadscreen(void)
Renders the loadscreen if necessary.
Header file with generic functions and naev-specifics.
void * ndata_read(const char *path, size_t *filesize)
Reads a file from the ndata (will be NUL terminated).
int ndata_matchExt(const char *path, const char *ext)
Sees if a file matches an extension.
char ** ndata_listRecursive(const char *path)
Lists all the visible files in a directory, at any depth.
int nlua_loadStandard(nlua_env env)
Loads the standard Naev Lua API.
int nlua_refenvtype(nlua_env env, const char *name, int type)
Gets the reference of a global in a lua environment if it matches a type.
int nlua_reffield(int objref, const char *name)
Gets the reference to the specified field from an object reference.
xmlDocPtr xml_parsePhysFS(const char *filename)
Analogous to xmlParseMemory/xmlParseFile.
glTexture * gl_dupTexture(const glTexture *texture)
Duplicates a texture.
glTexture * gl_newImage(const char *path, const unsigned int flags)
Loads an image as a texture.
void gl_freeTexture(glTexture *texture)
Frees a texture.
void space_factionChange(void)
Mark when a faction changes.
Description of a lane-building faction.
FactionGenerator * generators
double lane_length_per_presence
The actual hook parameter.
Abstraction for rendering sprite sheets.