naev 0.11.5
difficulty.c
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
10#include <stdlib.h>
11#include "physfs.h"
12
13#include "naev.h"
16#include "difficulty.h"
17
18#include "conf.h"
19#include "array.h"
20#include "ndata.h"
21#include "nxml.h"
22
23#define DIFFICULTY_XML_ID "difficulty"
24
25static Difficulty *difficulty_stack = NULL;
26static const Difficulty *difficulty_default = NULL;
27static const Difficulty *difficulty_global = NULL;
28static const Difficulty *difficulty_local = NULL;
29static const Difficulty *difficulty_current = NULL;
30
34int difficulty_load (void)
35{
36 char **difficulty_files = ndata_listRecursive( DIFFICULTY_PATH );
37 difficulty_stack = array_create( Difficulty );
38 for (int i=0; i<array_size(difficulty_files); i++) {
40 xmlDocPtr doc;
41 xmlNodePtr node, cur;
42
43 /* Load and read the data. */
44 doc = xml_parsePhysFS( difficulty_files[i] );
45 if (doc == NULL)
46 continue;
47
48 /* Check to see if document exists. */
49 node = doc->xmlChildrenNode;
50 if (!xml_isNode(node,DIFFICULTY_XML_ID)) {
51 ERR( _("Malformed '%s' file: missing root element '%s'"), difficulty_files[i], DIFFICULTY_XML_ID);
52 xmlFreeDoc( doc );
53 continue;
54 }
55
56 /* Initialize. */
57 memset( &d, 0, sizeof(Difficulty) );
58
59 /* Properties. */
60 xmlr_attr_strd( node, "name", d.name );
61 xmlr_attr_int_opt( node, "default", d.def );
62
63 /* Get the stats. */
64 cur = node->xmlChildrenNode;
65 do {
66 xml_onlyNodes(cur);
67
68 /* Load the description. */
69 xmlr_strd( cur, "description", d.description );
70
71 /* Rest should be ship stats. */
72 ShipStatList *ll = ss_listFromXML( cur );
73 if (ll != NULL) {
74 ll->next = d.stats;
75 d.stats = ll;
76 continue;
77 }
78 WARN(_("Difficulty '%s' has unknown node '%s'"), d.name, cur->name);
79 } while (xml_nextNode(cur));
80
81 xmlFreeDoc( doc );
82
83 array_push_back( &difficulty_stack, d );
84 }
85
86 /* Find out default. */
87 for (int i=0; i<array_size(difficulty_stack); i++) {
88 Difficulty *dd = &difficulty_stack[i];
89 if (dd->def) {
90 if (difficulty_default)
91 WARN(_("More than one difficulty with default flag set!"));
92 difficulty_default = dd;
93 }
94 }
95 if (difficulty_default==NULL) {
96 WARN(_("No default difficulty set!"));
97 difficulty_default = difficulty_stack;
98 }
99 difficulty_current = difficulty_default; /* Load default. */
100
101 /* Load the global difficulty. */
102 if (conf.difficulty != NULL)
103 difficulty_setGlobal( difficulty_get( conf.difficulty ) );
104
105 for (int i=0; i<array_size(difficulty_files); i++)
106 free( difficulty_files[i] );
107 array_free( difficulty_files );
108 return 0;
109}
110
114void difficulty_free (void)
115{
116 for (int i=0; i<array_size(difficulty_stack); i++) {
117 Difficulty *d = &difficulty_stack[i];
118 free( d->name );
119 free( d->description );
120 ss_free( d->stats );
121 }
122 array_free( difficulty_stack );
123}
124
128const Difficulty *difficulty_cur (void)
129{
130 return difficulty_current;
131}
132
136const Difficulty *difficulty_getAll (void)
137{
138 return difficulty_stack;
139}
140
141static const Difficulty *difficulty_getDefault (void)
142{
143 if (difficulty_global != NULL)
144 return difficulty_global;
145 else
146 return difficulty_default;
147}
148
152const Difficulty *difficulty_get( const char *name )
153{
154 if (name==NULL)
155 return difficulty_getDefault();
156 for (int i=0; i<array_size(difficulty_stack); i++) {
157 const Difficulty *d = &difficulty_stack[i];
158 if (strcmp(name, d->name)==0)
159 return d;
160 }
161 WARN(_("Uknown difficulty setting '%s'"), name);
162 return difficulty_default;
163}
164
165static void difficulty_update (void)
166{
167 if (difficulty_local != NULL)
168 difficulty_current = difficulty_local;
169 else if (difficulty_global != NULL)
170 difficulty_current = difficulty_global;
171 else
172 difficulty_current = difficulty_default;
173}
174
178void difficulty_setGlobal( const Difficulty *d )
179{
180 difficulty_global = d;
181 difficulty_update();
182}
183
187void difficulty_setLocal( const Difficulty *d )
188{
189 difficulty_local = d;
190 difficulty_update();
191}
192
198char *difficulty_display( const Difficulty *d )
199{
200 int l;
201 char *display = malloc( STRMAX );
202 l = scnprintf( display, STRMAX, _("Difficulty %s"), _(d->name) );
203 l += scnprintf( &display[l], STRMAX-l, "\n" );
204 if (d->description != NULL)
205 l += scnprintf( &display[l], STRMAX-l, "%s\n", _(d->description) );
206 l += scnprintf( &display[l], STRMAX-l, _("This difficulty applies the following effect to the player ships:") );
207 ss_statsListDesc( d->stats, &display[l], STRMAX-l, 1 );
208 return display;
209}
210
214int difficulty_apply( ShipStats *s )
215{
216 return ss_statsMergeFromList( s, difficulty_current->stats );
217}
Provides macros to work with dynamic arrays.
#define array_free(ptr_array)
Frees memory allocated and sets array to NULL.
Definition array.h:158
static ALWAYS_INLINE int array_size(const void *array)
Returns number of elements in the array.
Definition array.h:168
#define array_push_back(ptr_array, element)
Adds a new element at the end of the array.
Definition array.h:129
#define array_create(basic_type)
Creates a new dynamic array of ‘basic_type’.
Definition array.h:93
Header file with generic functions and naev-specifics.
char ** ndata_listRecursive(const char *path)
Lists all the visible files in a directory, at any depth.
Definition ndata.c:231
int scnprintf(char *text, size_t maxlen, const char *fmt,...)
Like snprintf(), but returns the number of characters ACTUALLY "printed" into the buffer....
Definition nstring.c:99
xmlDocPtr xml_parsePhysFS(const char *filename)
Analogous to xmlParseMemory/xmlParseFile.
Definition nxml.c:75
static const double d[]
Definition rng.c:273
int ss_statsListDesc(const ShipStatList *ll, char *buf, int len, int newline)
Writes the ship statistics description.
Definition shipstats.c:780
void ss_free(ShipStatList *ll)
Frees a list of ship stats.
Definition shipstats.c:887
int ss_statsMergeFromList(ShipStats *stats, const ShipStatList *list)
Updates a stat structure from a stat list.
Definition shipstats.c:627
ShipStatList * ss_listFromXML(xmlNodePtr node)
Creates a shipstat list element from an xml node.
Definition shipstats.c:292
ShipStatList * stats
Definition difficulty.h:11
char * difficulty
Definition conf.h:145
Represents relative ship statistics as a linked list.
Definition shipstats.h:167
struct ShipStatList_ * next
Definition shipstats.h:168
Represents ship statistics, properties ship can use.
Definition shipstats.h:198