|
Atrinik Server 2.5
|
00001 /************************************************************************ 00002 * Atrinik, a Multiplayer Online Role Playing Game * 00003 * * 00004 * Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team * 00005 * * 00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game) * 00007 * and Crossfire (Multiplayer game for X-windows). * 00008 * * 00009 * This program is free software; you can redistribute it and/or modify * 00010 * it under the terms of the GNU General Public License as published by * 00011 * the Free Software Foundation; either version 2 of the License, or * 00012 * (at your option) any later version. * 00013 * * 00014 * This program is distributed in the hope that it will be useful, * 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00017 * GNU General Public License for more details. * 00018 * * 00019 * You should have received a copy of the GNU General Public License * 00020 * along with this program; if not, write to the Free Software * 00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 00022 * * 00023 * The author can be reached at admin@atrinik.org * 00024 ************************************************************************/ 00025 00030 #include <global.h> 00031 00035 const char *item_races[NROF_ITEM_RACES] = 00036 { 00037 "", "dwarven ", "elven ", "gnomish ", "drow ", "orcish ", "goblin ", 00038 "kobold ", "giant ", "tiny ", "demonish ", "draconish ", "ogre " 00039 }; 00040 00043 static ob_race *races = NULL; 00046 static size_t num_races = 0; 00047 00052 static void race_add_corpse(shstr *race_name, archetype *at) 00053 { 00054 ob_race *race; 00055 00056 if (!at || !race_name) 00057 { 00058 return; 00059 } 00060 00061 race = race_find(race_name); 00062 00063 if (!race) 00064 { 00065 return; 00066 } 00067 00068 race->corpse = at; 00069 } 00070 00075 static void race_add(shstr *race_name, object *ob) 00076 { 00077 ob_race *race; 00078 objectlink *ol; 00079 00080 if (!ob || !race_name) 00081 { 00082 return; 00083 } 00084 00085 race = race_find(race_name); 00086 00087 /* No such race yet? Initialize it then. */ 00088 if (!race) 00089 { 00090 size_t i, ii; 00091 00092 races = realloc(races, sizeof(ob_race) * (num_races + 1)); 00093 00094 /* Now, insert the race into the correct spot in the array. */ 00095 for (i = 0; i < num_races; i ++) 00096 { 00097 if (races[i].name > race_name) 00098 { 00099 break; 00100 } 00101 } 00102 00103 /* If this is not the special case of insertion at the last point, then shift everything. */ 00104 for (ii = num_races; ii > i; ii--) 00105 { 00106 races[ii] = races[ii - 1]; 00107 } 00108 00109 memset(&races[i], 0, sizeof(ob_race)); 00110 FREE_AND_COPY_HASH(races[i].name, race_name); 00111 race = &races[i]; 00112 num_races++; 00113 } 00114 00115 ol = get_objectlink(); 00116 ol->objlink.ob = ob; 00117 ol->id = ob->count; 00118 /* Link the new object link to the race's list. */ 00119 objectlink_link(&race->members, NULL, NULL, race->members, ol); 00120 /* Increase the number of race's members. */ 00121 race->num_members++; 00122 } 00123 00126 static int race_compare(const void *one, const void *two) 00127 { 00128 ob_race *one_race = (ob_race *) one; 00129 ob_race *two_race = (ob_race *) two; 00130 00131 if (one == NULL) 00132 { 00133 return -1; 00134 } 00135 else if (two == NULL) 00136 { 00137 return 1; 00138 } 00139 00140 if (one_race->name < two_race->name) 00141 { 00142 return -1; 00143 } 00144 else if (one_race->name > two_race->name) 00145 { 00146 return 1; 00147 } 00148 else 00149 { 00150 return 0; 00151 } 00152 } 00153 00158 ob_race *race_find(shstr *name) 00159 { 00160 ob_race key; 00161 00162 if (!races || !name) 00163 { 00164 return NULL; 00165 } 00166 00167 key.name = name; 00168 00169 return bsearch(&key, races, num_races, sizeof(ob_race), race_compare); 00170 } 00171 00175 ob_race *race_get_random() 00176 { 00177 if (!races || !num_races) 00178 { 00179 return NULL; 00180 } 00181 00182 return &races[rndm(1, num_races) - 1]; 00183 } 00184 00188 void race_init() 00189 { 00190 archetype *at, *tmp; 00191 size_t i; 00192 00193 LOG(llevDebug, "Initializing races..."); 00194 00195 for (at = first_archetype; at; at = at->next) 00196 { 00197 if (at->clone.type == MONSTER || at->clone.type == PLAYER) 00198 { 00199 race_add(at->clone.race, &at->clone); 00200 } 00201 } 00202 00203 /* Now search for corpses. */ 00204 for (at = first_archetype; at; at = at->next) 00205 { 00206 if (at->clone.type == CONTAINER && at->clone.sub_type == ST1_CONTAINER_CORPSE) 00207 { 00208 race_add_corpse(at->clone.race, at); 00209 } 00210 } 00211 00212 /* Try to find the default corpse archetype. */ 00213 tmp = find_archetype(RACE_CORPSE_DEFAULT); 00214 00215 if (!tmp) 00216 { 00217 LOG(llevError, "race_init(): Can't find required archetype: '%s'.\n", RACE_CORPSE_DEFAULT); 00218 return; 00219 } 00220 00221 /* Look through the races, and assign the default corpse archetype 00222 * to those which do not have any yet. */ 00223 for (i = 0; i < num_races; i++) 00224 { 00225 if (!races[i].corpse) 00226 { 00227 races[i].corpse = tmp; 00228 } 00229 } 00230 00231 LOG(llevDebug, " done.\n"); 00232 } 00233 00236 void race_dump() 00237 { 00238 size_t i; 00239 objectlink *ol; 00240 00241 for (i = 0; i < num_races; i++) 00242 { 00243 LOG(llevInfo, "\nRACE '%s', corpse: '%s', %d members: ", races[i].name, races[i].corpse->name, races[i].num_members); 00244 00245 for (ol = races[i].members; ol; ol = ol->next) 00246 { 00247 LOG(llevInfo, "%s, ", ol->objlink.ob->arch->name); 00248 } 00249 } 00250 00251 LOG(llevInfo, "\n"); 00252 } 00253 00256 void race_free() 00257 { 00258 size_t i; 00259 objectlink *ol, *ol_next; 00260 00261 for (i = 0; i < num_races; i++) 00262 { 00263 FREE_ONLY_HASH(races[i].name); 00264 00265 for (ol = races[i].members; ol; ol = ol_next) 00266 { 00267 ol_next = ol->next; 00268 free_objectlink_simple(ol); 00269 } 00270 } 00271 00272 free(races); 00273 LOG(-1, "Freed %"FMT64U" races.\n", (uint64) num_races); 00274 }
1.7.4