project_files/frontlib/model/weapon.c
changeset 7230 240620f46dd7
parent 7227 1c859f572d72
child 7269 5b0aeef8ba2a
equal deleted inserted replaced
7227:1c859f572d72 7230:240620f46dd7
     1 #include "weapon.h"
     1 #include "weapon.h"
     2 
     2 
     3 #include "../util/inihelper.h"
     3 #include "../util/inihelper.h"
     4 #include "../util/logging.h"
     4 #include "../util/logging.h"
     5 #include "../util/util.h"
     5 #include "../util/util.h"
       
     6 #include "../util/refcounter.h"
     6 
     7 
     7 #include <stdlib.h>
     8 #include <stdlib.h>
     8 #include <ctype.h>
     9 #include <ctype.h>
     9 
    10 #include <string.h>
    10 int set_field(char field[WEAPONS_COUNT+1], const char *line, bool no9) {
    11 
    11 	// Validate the new string
    12 static void flib_weaponset_destroy(flib_weaponset *cfg) {
    12 	for(int i=0; i<WEAPONS_COUNT && line[i]; i++) {
       
    13 		if(line[i] < '0' || line[i] > '9' || (no9 && line[i] == '9')) {
       
    14 			flib_log_e("Invalid character in weapon config string \"%.*s\", position %i", WEAPONS_COUNT, line, i);
       
    15 			return -1;
       
    16 		}
       
    17 	}
       
    18 
       
    19 	bool lineEnded = false;
       
    20 	for(int i=0; i<WEAPONS_COUNT; i++) {
       
    21 		if(!lineEnded && !line[i]) {
       
    22 			flib_log_w("Incomplete weapon config line \"%s\", filling with zeroes.", line);
       
    23 			lineEnded = true;
       
    24 		}
       
    25 		if(lineEnded) {
       
    26 			field[i] = '0';
       
    27 		} else {
       
    28 			field[i] = line[i];
       
    29 		}
       
    30 	}
       
    31 	field[WEAPONS_COUNT] = 0;
       
    32 	return 0;
       
    33 }
       
    34 
       
    35 static flib_weaponset *flib_weaponset_create_str(const char *name, const char *loadoutStr, const char *crateProbStr, const char *crateAmmoStr, const char *delayStr) {
       
    36 	flib_weaponset *result = NULL;
       
    37 	if(!name || !loadoutStr || !crateProbStr || !crateAmmoStr || !delayStr) {
       
    38 		flib_log_e("null parameter in flib_weaponset_create_str");
       
    39 	} else {
       
    40 		flib_weaponset *newSet = flib_calloc(1, sizeof(flib_weaponset));
       
    41 		char *nameCopy = flib_strdupnull(name);
       
    42 		if(newSet && nameCopy) {
       
    43 			newSet->name = nameCopy;
       
    44 			nameCopy = NULL;
       
    45 			bool error = false;
       
    46 			error |= set_field(newSet->loadout, loadoutStr, false);
       
    47 			error |= set_field(newSet->crateprob, crateProbStr, false);
       
    48 			error |= set_field(newSet->crateammo, crateAmmoStr, false);
       
    49 			error |= set_field(newSet->delay, delayStr, false);
       
    50 			if(!error) {
       
    51 				result = newSet;
       
    52 				newSet = NULL;
       
    53 			}
       
    54 		}
       
    55 		free(nameCopy);
       
    56 		flib_weaponset_destroy(newSet);
       
    57 	}
       
    58 	return result;
       
    59 }
       
    60 
       
    61 void flib_weaponset_destroy(flib_weaponset *cfg) {
       
    62 	if(cfg) {
    13 	if(cfg) {
    63 		free(cfg->name);
    14 		free(cfg->name);
    64 		free(cfg);
    15 		free(cfg);
    65 	}
    16 	}
    66 }
    17 }
    67 
    18 
       
    19 static void setField(char field[WEAPONS_COUNT+1], const char *line, int lineLen, bool no9) {
       
    20 	if(lineLen>WEAPONS_COUNT) {
       
    21 		lineLen = WEAPONS_COUNT;
       
    22 	}
       
    23 
       
    24 	char min = '0';
       
    25 	char max = no9 ? '8' : '9';
       
    26 	for(int i=0; i<lineLen; i++) {
       
    27 		if(line[i] >= min && line[i] <= max) {
       
    28 			field[i] = line[i];
       
    29 		} else {
       
    30 			flib_log_w("Invalid character in weapon config string \"%.*s\", position %i", lineLen, line, i);
       
    31 			field[i] = '0';
       
    32 		}
       
    33 	}
       
    34 	for(int i=lineLen; i<WEAPONS_COUNT; i++) {
       
    35 		field[i] = '0';
       
    36 	}
       
    37 	field[WEAPONS_COUNT] = 0;
       
    38 }
       
    39 
    68 flib_weaponset *flib_weaponset_create(const char *name) {
    40 flib_weaponset *flib_weaponset_create(const char *name) {
    69 	return flib_weaponset_create_str(name, AMMOLINE_DEFAULT_QT, AMMOLINE_DEFAULT_PROB, AMMOLINE_DEFAULT_CRATE, AMMOLINE_DEFAULT_DELAY);
       
    70 }
       
    71 
       
    72 flib_weaponset *flib_weaponset_from_ini(const char *filename) {
       
    73 	flib_weaponset *result = NULL;
    41 	flib_weaponset *result = NULL;
       
    42 	if(!name) {
       
    43 		flib_log_e("null parameter in flib_weaponset_create_str");
       
    44 	} else {
       
    45 		flib_weaponset *newSet = flib_weaponset_retain(flib_calloc(1, sizeof(flib_weaponset)));
       
    46 		if(newSet) {
       
    47 			newSet->name = flib_strdupnull(name);
       
    48 			if(newSet->name) {
       
    49 				setField(newSet->loadout, "", 0, false);
       
    50 				setField(newSet->crateprob, "", 0, false);
       
    51 				setField(newSet->crateammo, "", 0, false);
       
    52 				setField(newSet->delay, "", 0, false);
       
    53 				result = flib_weaponset_retain(newSet);
       
    54 			}
       
    55 		}
       
    56 		flib_weaponset_release(newSet);
       
    57 	}
       
    58 	return result;
       
    59 }
       
    60 
       
    61 flib_weaponset *flib_weaponset_retain(flib_weaponset *weaponset) {
       
    62 	if(weaponset) {
       
    63 		flib_retain(&weaponset->_referenceCount, "flib_weaponset");
       
    64 	}
       
    65 	return weaponset;
       
    66 }
       
    67 
       
    68 void flib_weaponset_release(flib_weaponset *weaponset) {
       
    69 	if(weaponset && flib_release(&weaponset->_referenceCount, "flib_weaponset")) {
       
    70 		flib_weaponset_destroy(weaponset);
       
    71 	}
       
    72 }
       
    73 
       
    74 static void flib_weaponsetlist_destroy(flib_weaponsetlist *list) {
       
    75 	if(list) {
       
    76 		for(int i=0; i<list->weaponsetCount; i++) {
       
    77 			flib_weaponset_release(list->weaponsets[i]);
       
    78 		}
       
    79 		free(list);
       
    80 	}
       
    81 }
       
    82 
       
    83 static int fillWeaponsetFromIni(flib_weaponsetlist *list, flib_ini *ini, int index) {
       
    84 	int result = -1;
       
    85 	char *keyname = flib_ini_get_keyname(ini, index);
       
    86 	char *decodedKeyname = flib_urldecode(keyname);
       
    87 
       
    88 	if(decodedKeyname) {
       
    89 		flib_weaponset *set = flib_weaponset_create(decodedKeyname);
       
    90 		if(set) {
       
    91 			char *value = NULL;
       
    92 			if(!flib_ini_get_str(ini, &value, keyname)) {
       
    93 				int fieldlen = strlen(value)/4;
       
    94 				setField(set->loadout, value, fieldlen, false);
       
    95 				setField(set->crateprob, value+1*fieldlen, fieldlen, true);
       
    96 				setField(set->delay, value+2*fieldlen, fieldlen, true);
       
    97 				setField(set->crateammo, value+3*fieldlen, fieldlen, true);
       
    98 				result = flib_weaponsetlist_insert(list, set, list->weaponsetCount);
       
    99 			}
       
   100 			free(value);
       
   101 		}
       
   102 		flib_weaponset_release(set);
       
   103 	}
       
   104 
       
   105 	free(keyname);
       
   106 	free(decodedKeyname);
       
   107 	return result;
       
   108 }
       
   109 
       
   110 static int fillWeaponsetsFromIni(flib_weaponsetlist *list, flib_ini *ini) {
       
   111 	bool error = false;
       
   112 	int weaponsets = flib_ini_get_keycount(ini);
       
   113 
       
   114 	for(int i=0; i<weaponsets && !error; i++) {
       
   115 		error |= fillWeaponsetFromIni(list, ini, i);
       
   116 	}
       
   117 	return error;
       
   118 }
       
   119 
       
   120 flib_weaponsetlist *flib_weaponsetlist_from_ini(const char *filename) {
       
   121 	flib_weaponsetlist *result = NULL;
    74 	if(!filename) {
   122 	if(!filename) {
    75 		flib_log_e("null parameter in flib_weaponset_from_ini");
   123 		flib_log_e("null parameter in flib_weaponsetlist_from_ini");
    76 	} else {
   124 	} else {
    77 		flib_ini *ini = flib_ini_load(filename);
   125 		flib_ini *ini = flib_ini_load(filename);
    78 		if(!ini) {
   126 		if(!ini) {
    79 			flib_log_e("Error loading weapon scheme file %s", filename);
   127 			flib_log_e("Missing file %s.", filename);
    80 		} else if(!flib_ini_enter_section(ini, "weaponset")) {
   128 		} else if(flib_ini_enter_section(ini, "General")) {
       
   129 			flib_log_e("Missing section \"General\" in file %s.", filename);
       
   130 		} else {
       
   131 			flib_weaponsetlist *list = flib_weaponsetlist_create();
       
   132 			if(list) {
       
   133 				if(!fillWeaponsetsFromIni(list, ini)) {
       
   134 					result = flib_weaponsetlist_retain(list);
       
   135 				}
       
   136 			}
       
   137 			flib_weaponsetlist_release(list);
       
   138 		}
       
   139 		flib_ini_destroy(ini);
       
   140 	}
       
   141 	return result;
       
   142 }
       
   143 
       
   144 static bool needsEscape(char c) {
       
   145 	return !((c>='0' && c<='9') || (c>='a' && c <='z'));
       
   146 }
       
   147 
       
   148 
       
   149 static int writeWeaponsetToIni(flib_ini *ini, flib_weaponset *set) {
       
   150 	int result = -1;
       
   151 	char weaponstring[WEAPONS_COUNT*4+1];
       
   152 	strcpy(weaponstring, set->loadout);
       
   153 	strcat(weaponstring, set->crateprob);
       
   154 	strcat(weaponstring, set->delay);
       
   155 	strcat(weaponstring, set->crateammo);
       
   156 
       
   157 	char *escapedname = flib_urlencode_pred(set->name, needsEscape);
       
   158 	if(escapedname) {
       
   159 		result = flib_ini_set_str(ini, escapedname, weaponstring);
       
   160 	}
       
   161 	free(escapedname);
       
   162 	return result;
       
   163 }
       
   164 
       
   165 int flib_weaponsetlist_to_ini(const char *filename, const flib_weaponsetlist *list) {
       
   166 	int result = -1;
       
   167 	if(!filename || !list) {
       
   168 		flib_log_e("null parameter in flib_weaponsetlist_to_ini");
       
   169 	} else {
       
   170 		flib_ini *ini = flib_ini_create(NULL);
       
   171 		if(ini && !flib_ini_create_section(ini, "General")) {
    81 			bool error = false;
   172 			bool error = false;
    82 			char *name = NULL, *loadout = NULL, *crateprob = NULL, *crateammo = NULL, *delay = NULL;
   173 			for(int i=0; i<list->weaponsetCount && !error; i++) {
    83 			error |= flib_ini_get_str(ini, &name, "name");
   174 				error |= writeWeaponsetToIni(ini, list->weaponsets[i]);
    84 			error |= flib_ini_get_str(ini, &loadout, "loadout");
   175 			}
    85 			error |= flib_ini_get_str(ini, &crateprob, "crateprob");
   176 
    86 			error |= flib_ini_get_str(ini, &crateammo, "crateammo");
       
    87 			error |= flib_ini_get_str(ini, &delay, "delay");
       
    88 
       
    89 			if(error) {
       
    90 				flib_log_e("Missing key in weapon scheme file %s", filename);
       
    91 			} else {
       
    92 				result = flib_weaponset_create_str(name, loadout, crateprob, crateammo, delay);
       
    93 			}
       
    94 			free(name);
       
    95 			free(loadout);
       
    96 			free(crateprob);
       
    97 			free(crateammo);
       
    98 			free(delay);
       
    99 		}
       
   100 		flib_ini_destroy(ini);
       
   101 	}
       
   102 	return result;
       
   103 }
       
   104 
       
   105 int flib_weaponset_to_ini(const char *filename, const flib_weaponset *set) {
       
   106 	int result = -1;
       
   107 	if(!filename || !set) {
       
   108 		flib_log_e("null parameter in flib_weaponset_to_ini");
       
   109 	} else {
       
   110 		flib_ini *ini = flib_ini_create(filename);
       
   111 		if(!flib_ini_create_section(ini, "weaponset")) {
       
   112 			bool error = false;
       
   113 			error |= flib_ini_set_str(ini, "name", set->name);
       
   114 			error |= flib_ini_set_str(ini, "loadout", set->loadout);
       
   115 			error |= flib_ini_set_str(ini, "crateprob", set->crateprob);
       
   116 			error |= flib_ini_set_str(ini, "crateammo", set->crateammo);
       
   117 			error |= flib_ini_set_str(ini, "delay", set->delay);
       
   118 			if(!error) {
   177 			if(!error) {
   119 				result = flib_ini_save(ini, filename);
   178 				result = flib_ini_save(ini, filename);
   120 			}
   179 			}
   121 		}
   180 		}
   122 		flib_ini_destroy(ini);
   181 		flib_ini_destroy(ini);
   123 	}
   182 	}
   124 	return result;
   183 	return result;
   125 }
   184 }
       
   185 
       
   186 flib_weaponsetlist *flib_weaponsetlist_create() {
       
   187 	return flib_weaponsetlist_retain(flib_calloc(1, sizeof(flib_weaponsetlist)));
       
   188 }
       
   189 
       
   190 int flib_weaponsetlist_insert(flib_weaponsetlist *list, flib_weaponset *weaponset, int pos) {
       
   191 	int result = -1;
       
   192 	if(!list || !weaponset || pos < 0 || pos > list->weaponsetCount) {
       
   193 		flib_log_e("Invalid parameter in flib_weaponsetlist_insert");
       
   194 	} else {
       
   195 		flib_weaponset **newSets = flib_realloc(list->weaponsets, (list->weaponsetCount+1)*sizeof(*list->weaponsets));
       
   196 		if(newSets) {
       
   197 			list->weaponsets = newSets;
       
   198 			memmove(list->weaponsets+pos+1, list->weaponsets+pos, (list->weaponsetCount-pos)*sizeof(*list->weaponsets));
       
   199 			list->weaponsets[pos] = flib_weaponset_retain(weaponset);
       
   200 			list->weaponsetCount++;
       
   201 			result = 0;
       
   202 		}
       
   203 	}
       
   204 	return result;
       
   205 }
       
   206 
       
   207 int flib_weaponsetlist_delete(flib_weaponsetlist *list, int pos) {
       
   208 	int result = -1;
       
   209 	if(!list || pos < 0 || pos >= list->weaponsetCount) {
       
   210 		flib_log_e("Invalid parameter in flib_weaponsetlist_delete");
       
   211 	} else {
       
   212 		flib_weaponset_release(list->weaponsets[pos]);
       
   213 		memmove(list->weaponsets+pos, list->weaponsets+pos+1, (list->weaponsetCount-(pos+1))*sizeof(*list->weaponsets));
       
   214 		list->weaponsets[list->weaponsetCount-1] = NULL;
       
   215 		list->weaponsetCount--;
       
   216 
       
   217 		// If the realloc fails, just keep using the old buffer...
       
   218 		flib_weaponset **newSets = flib_realloc(list->weaponsets, list->weaponsetCount*sizeof(*list->weaponsets));
       
   219 		if(newSets || list->weaponsetCount==1) {
       
   220 			list->weaponsets = newSets;
       
   221 		}
       
   222 		result = 0;
       
   223 	}
       
   224 	return result;
       
   225 }
       
   226 
       
   227 flib_weaponsetlist *flib_weaponsetlist_retain(flib_weaponsetlist *list) {
       
   228 	if(list) {
       
   229 		flib_retain(&list->_referenceCount, "flib_weaponsetlist");
       
   230 	}
       
   231 	return list;
       
   232 }
       
   233 
       
   234 void flib_weaponsetlist_release(flib_weaponsetlist *list) {
       
   235 	if(list && flib_release(&list->_referenceCount, "flib_weaponsetlist")) {
       
   236 		flib_weaponsetlist_destroy(list);
       
   237 	}
       
   238 }