naev 0.11.5
damagetype.c
Go to the documentation of this file.
1/*
2 * See Licensing and Copyright notice in naev.h
3 */
10#include <inttypes.h>
11#include "SDL.h"
12
13#include "naev.h"
16#include "damagetype.h"
17
18#include "array.h"
19#include "log.h"
20#include "ndata.h"
21#include "nxml.h"
22#include "pause.h"
23#include "pilot.h"
24#include "rng.h"
25#include "shipstats.h"
26
27#define DTYPE_XML_ID "dtype"
34typedef struct DTYPE_ {
35 char* name;
36 char* display;
37 double sdam;
38 double adam;
39 double knock;
40 size_t soffset;
41 size_t aoffset;
42} DTYPE;
43
44static DTYPE* dtype_types = NULL;
46/*
47 * prototypes
48 */
49static int DTYPE_parse( DTYPE *temp, const char *file);
50static void DTYPE_free( DTYPE *damtype );
51static DTYPE* dtype_validType( int type );
52static int dtype_cmp( const void *p1, const void *p2 );
53
57static int dtype_cmp( const void *p1, const void *p2 )
58{
59 const DTYPE *d1 = (const DTYPE*) p1;
60 const DTYPE *d2 = (const DTYPE*) p2;
61 return strcmp( d1->name, d2->name );
62}
63
71static int DTYPE_parse( DTYPE *temp, const char *file )
72{
73 xmlNodePtr node, parent;
74 xmlDocPtr doc;
75 char *stat;
76
77 /* Load and read the data. */
78 doc = xml_parsePhysFS( file );
79 if (doc == NULL)
80 return -1;
81
82 /* Check to see if document exists. */
83 parent = doc->xmlChildrenNode;
84 if (!xml_isNode(parent,DTYPE_XML_ID)) {
85 WARN(_("Malformed '%s' file: missing root element '%s'"), file, DTYPE_XML_ID);
86 return -1;
87 }
88
89 /* Clear data. */
90 memset( temp, 0, sizeof(DTYPE) );
91
92 xmlr_attr_strd( parent, "name", temp->name );
93 xmlr_attr_strd( parent, "display", temp->display );
94
95 /* Extract the data. */
96 node = parent->xmlChildrenNode;
97 do {
98 xml_onlyNodes(node);
99
100 if (xml_isNode(node, "shield")) {
101 temp->sdam = xml_getFloat(node);
102
103 xmlr_attr_strd( node, "stat", stat );
104 if (stat != NULL) {
106 free(stat);
107 }
108
109 continue;
110 }
111 else if (xml_isNode(node, "armour")) {
112 temp->adam = xml_getFloat(node);
113
114 xmlr_attr_strd( node, "stat", stat );
115 if (stat != NULL) {
117 free(stat);
118 }
119
120 continue;
121 }
122 xmlr_float(node, "knockback", temp->knock);
123
124 WARN(_("Unknown node of type '%s' in damage node '%s'."), node->name, temp->name);
125 } while (xml_nextNode(node));
126
127#define MELEMENT(o,s) \
128 if (o) WARN(_("DTYPE '%s' invalid '"s"' element"), temp->name)
129 MELEMENT(temp->sdam<0.,"shield");
130 MELEMENT(temp->adam<0.,"armour");
131 MELEMENT(temp->knock<0.,"knockback");
132#undef MELEMENT
133
134 /* Clean up. */
135 xmlFreeDoc(doc);
136
137 return 0;
138}
139
145static void DTYPE_free( DTYPE *damtype )
146{
147 free(damtype->name);
148 damtype->name = NULL;
149 free(damtype->display);
150 damtype->display = NULL;
151}
152
159int dtype_get( const char* name )
160{
161 const DTYPE d= { .name = (char*)name };
162 const DTYPE *dout = bsearch( &d, dtype_types, array_size(dtype_types), sizeof(DTYPE), dtype_cmp );
163 if (dout==NULL) {
164 WARN(_("Damage type '%s' not found in stack."), name);
165 return -1;
166 }
167 return dout-dtype_types;
168}
169
173static DTYPE* dtype_validType( int type )
174{
175 if ((type < 0) || (type >= array_size(dtype_types))) {
176 WARN(_("Damage type '%d' is invalid."), type);
177 return NULL;
178 }
179 return &dtype_types[ type ];
180}
181
185const char* dtype_damageTypeToStr( int type )
186{
187 DTYPE *dmg = dtype_validType( type );
188 if (dmg == NULL)
189 return NULL;
190 return (dmg->display==NULL) ? dmg->name: dmg->display;
191}
192
198int dtype_load (void)
199{
200 const DTYPE dtype_raw = {
201 .name = strdup(N_("raw")),
202 .display = NULL,
203 .sdam = 1.,
204 .adam = 1.,
205 .knock = 0.,
206 .soffset = 0,
207 .aoffset = 0,
208 };
209 char **dtype_files = ndata_listRecursive( DTYPE_DATA_PATH );
210
211 /* Load up the individual damage types. */
214
215 for (int i=0; i<array_size(dtype_files); i++) {
216 DTYPE dtype;
217 int ret = DTYPE_parse( &dtype, dtype_files[i] );
218 if (ret == 0)
219 array_push_back( &dtype_types, dtype );
220 free( dtype_files[i] );
221 }
222 array_free( dtype_files );
223
224 /* Shrink back to minimum - shouldn't change ever. */
225 qsort( dtype_types, array_size(dtype_types), sizeof(DTYPE), dtype_cmp );
227
228 return 0;
229}
230
234void dtype_free (void)
235{
236 /* clear the damtypes */
237 for (int i=0; i<array_size(dtype_types); i++)
238 DTYPE_free( &dtype_types[i] );
240 dtype_types = NULL;
241}
242
252int dtype_raw( int type, double *shield, double *armour, double *knockback )
253{
254 DTYPE *dtype = dtype_validType( type );
255 if (dtype == NULL)
256 return -1;
257 if (shield != NULL)
258 *shield = dtype->sdam;
259 if (armour != NULL)
260 *armour = dtype->adam;
261 if (knockback != NULL)
262 *knockback = dtype->knock;
263 return 0;
264}
265
276void dtype_calcDamage( double *dshield, double *darmour, double absorb, double *knockback, const Damage *dmg, const ShipStats *s )
277{
278 DTYPE *dtype;
279 char *ptr;
280 double multiplier;
281
282 /* Must be valid. */
283 dtype = dtype_validType( dmg->type );
284 if (dtype == NULL)
285 return;
286
287 /* Set if non-nil. */
288 if (dshield != NULL) {
289 if ((dtype->soffset <= 0) || (s == NULL))
290 *dshield = dtype->sdam * dmg->damage * absorb;
291 else {
292 /*
293 * If an offset has been specified, look for a double at that offset
294 * in the ShipStats struct, and used it as a multiplier.
295 *
296 * The 1. - n logic serves to convert the value from absorption to
297 * damage multiplier.
298 */
299 ptr = (char*) s;
300 memcpy(&multiplier, &ptr[ dtype->soffset ], sizeof(double));
301 multiplier = MAX( 0., 1. - multiplier );
302 *dshield = dtype->sdam * dmg->damage * absorb * multiplier;
303 }
304 }
305 if (darmour != NULL) {
306 if ((dtype->aoffset) <= 0 || (s == NULL))
307 *darmour = dtype->adam * dmg->damage * absorb;
308 else {
309 ptr = (char*) s;
310 memcpy(&multiplier, &ptr[ dtype->aoffset ], sizeof(double));
311 multiplier = MAX( 0., 1. - multiplier );
312 *darmour = dtype->adam * dmg->damage * absorb * multiplier;
313 }
314 }
315
316 if (knockback != NULL)
317 *knockback = dtype->knock;
318}
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_shrink(ptr_array)
Shrinks memory to fit only ‘size’ elements.
Definition array.h:149
#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
int dtype_load(void)
Loads the dtype stack.
Definition damagetype.c:198
static void DTYPE_free(DTYPE *damtype)
Frees a DTYPE.
Definition damagetype.c:145
int dtype_raw(int type, double *shield, double *armour, double *knockback)
Gets the raw modulation stats of a damage type.
Definition damagetype.c:252
void dtype_calcDamage(double *dshield, double *darmour, double absorb, double *knockback, const Damage *dmg, const ShipStats *s)
Gives the real shield damage, armour damage and knockback modifier.
Definition damagetype.c:276
static DTYPE * dtype_types
Definition damagetype.c:44
int dtype_get(const char *name)
Gets the id of a dtype based on name.
Definition damagetype.c:159
void dtype_free(void)
Frees the dtype stack.
Definition damagetype.c:234
#define DTYPE_XML_ID
Definition damagetype.c:27
static int DTYPE_parse(DTYPE *temp, const char *file)
Parses an XML file containing a DTYPE.
Definition damagetype.c:71
static DTYPE * dtype_validType(int type)
Gets the damage type.
Definition damagetype.c:173
const char * dtype_damageTypeToStr(int type)
Gets the human readable string from damage type.
Definition damagetype.c:185
static int dtype_cmp(const void *p1, const void *p2)
For sorting and bsearching.
Definition damagetype.c:57
Header file with generic functions and naev-specifics.
#define MAX(x, y)
Definition naev.h:39
char ** ndata_listRecursive(const char *path)
Lists all the visible files in a directory, at any depth.
Definition ndata.c:231
xmlDocPtr xml_parsePhysFS(const char *filename)
Analogous to xmlParseMemory/xmlParseFile.
Definition nxml.c:75
static const double d[]
Definition rng.c:273
size_t ss_offsetFromType(ShipStatsType type)
Gets the offset from type.
Definition shipstats.c:674
ShipStatsType ss_typeFromName(const char *name)
Gets the type from the name.
Definition shipstats.c:685
A damage type.
Definition damagetype.c:34
size_t soffset
Definition damagetype.c:40
double knock
Definition damagetype.c:39
double adam
Definition damagetype.c:38
char * name
Definition damagetype.c:35
char * display
Definition damagetype.c:36
size_t aoffset
Definition damagetype.c:41
double sdam
Definition damagetype.c:37
Core damage that an outfit does.
Definition outfit.h:138
int type
Definition outfit.h:139
double damage
Definition outfit.h:141
Represents ship statistics, properties ship can use.
Definition shipstats.h:198