Crossfire Server, Branch 1.12
R12190
|
00001 /* 00002 * static char *rcsid_resurrection_c = 00003 * "$Id: resurrection.c 11578 2009-02-23 22:02:27Z lalo $"; 00004 */ 00005 00006 /* 00007 CrossFire, A Multiplayer game for X-windows 00008 00009 Copyright (C) 2006 Mark Wedel & Crossfire Development Team 00010 Copyright (C) 1992 Frank Tore Johansen 00011 00012 This program is free software; you can redistribute it and/or modify 00013 it under the terms of the GNU General Public License as published by 00014 the Free Software Foundation; either version 2 of the License, or 00015 (at your option) any later version. 00016 00017 This program is distributed in the hope that it will be useful, 00018 but WITHOUT ANY WARRANTY; without even the implied warranty of 00019 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00020 GNU General Public License for more details. 00021 00022 You should have received a copy of the GNU General Public License 00023 along with this program; if not, write to the Free Software 00024 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00025 00026 The authors can be reached via e-mail at crossfire-devel@real-time.com 00027 */ 00028 00036 /* the contents of this file were create solely by peterm@soda.berkeley.edu 00037 all of the above disclaimers apply. */ 00038 00039 #include <global.h> 00040 #ifndef __CEXTRACT__ 00041 #include <sproto.h> 00042 #endif 00043 #include <spells.h> 00044 #include <errno.h> 00045 00046 static int resurrection_fails(int levelcaster, int leveldead); 00047 00062 static int resurrect_player(object *op, char *playername, object *spell) { 00063 FILE *deadplayer, *liveplayer; 00064 00065 char oldname[MAX_BUF]; 00066 char newname[MAX_BUF]; 00067 char path[MAX_BUF]; 00068 char buf[MAX_BUF]; 00069 char buf2[MAX_BUF]; 00070 const char *race = NULL; 00071 sint64 exp; 00072 int Con; 00073 00074 /* reincarnation, which changes the race */ 00075 if (spell->race) { 00076 treasurelist *tl = find_treasurelist(spell->race); 00077 treasure *t; 00078 int value; 00079 00080 if (!tl) { 00081 LOG(llevError, "resurrect_player: race set to %s, but no treasurelist of that name!\n", spell->race); 00082 return 0; 00083 } 00084 value = RANDOM()%tl->total_chance; 00085 for (t = tl->items; t; t = t->next) { 00086 value -= t->chance; 00087 if (value < 0) 00088 break; 00089 } 00090 if (!t) { 00091 LOG(llevError, "resurrect_player: got null treasure from treasurelist %s!\n", spell->race); 00092 return 0; 00093 } 00094 race = t->item->name; 00095 } 00096 00097 /* set up our paths/strings... */ 00098 snprintf(path, sizeof(path), "%s/%s/%s/%s", settings.localdir, settings.playerdir, playername, playername); 00099 00100 strcpy(newname, path); 00101 strcat(newname, ".pl"); 00102 00103 strcpy(oldname, newname); 00104 strcat(oldname, ".dead"); 00105 00106 if (!(deadplayer = fopen(oldname, "r"))) { 00107 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_FAILURE, 00108 "The soul of %s cannot be reached.", 00109 "The soul of %s cannot be reached.", 00110 playername); 00111 return 0; 00112 } 00113 00114 if (!access(newname, 0)) { 00115 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_FAILURE, 00116 "The soul of %s has already been reborn!", 00117 "The soul of %s has already been reborn!", 00118 playername); 00119 fclose(deadplayer); 00120 return 0; 00121 } 00122 00123 if (!(liveplayer = fopen(newname, "w"))) { 00124 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_FAILURE, 00125 "The soul of %s cannot be re-embodied at the moment.", 00126 "The soul of %s cannot be re-embodied at the moment.", 00127 playername); 00128 LOG(llevError, "Cannot write player in resurrect_player!\n"); 00129 fclose(deadplayer); 00130 return 0; 00131 } 00132 00133 while (!feof(deadplayer)) { 00134 fgets(buf, 255, deadplayer); 00135 sscanf(buf, "%s", buf2); 00136 if (!(strcmp(buf2, "exp"))) { 00137 sscanf(buf, "%s %"FMT64, buf2, &exp); 00138 if (spell->stats.exp) { 00139 exp -= exp/spell->stats.exp; 00140 snprintf(buf, sizeof(buf), "exp %"FMT64"\n", exp); 00141 } 00142 } 00143 if (!(strcmp(buf2, "Con"))) { 00144 sscanf(buf, "%s %d", buf2, &Con); 00145 Con -= spell->stats.Con; 00146 if (Con < 1) 00147 Con = 1; 00148 snprintf(buf, sizeof(buf), "Con %d\n", Con); 00149 } 00150 if (race && !strcmp(buf2, "race")) { 00151 snprintf(buf, sizeof(buf), "race %s\n", race); 00152 } 00153 fputs(buf, liveplayer); 00154 } 00155 fclose(liveplayer); 00156 fclose(deadplayer); 00157 unlink(oldname); 00158 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_SUCCESS, 00159 "%s lives again!", 00160 "%s lives again!", 00161 playername); 00162 00163 return 1; 00164 } 00165 00186 int cast_raise_dead_spell(object *op, object *caster, object *spell, int dir, const char *arg) { 00187 object *temp, *newob; 00188 char name_to_resurrect[MAX_BUF]; 00189 int leveldead = 25, mflags, clevel; 00190 sint16 sx, sy; 00191 mapstruct *m; 00192 00193 clevel = caster_level(caster, spell); 00194 00195 if (spell->last_heal) { 00196 if (!arg) { 00197 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_FAILURE, 00198 "Cast %s on who?", 00199 "Cast %s on who?", 00200 spell->name); 00201 return 0; 00202 } 00203 strcpy(name_to_resurrect, arg); 00204 temp = NULL; 00205 } else { 00206 sx = op->x+freearr_x[dir]; 00207 sy = op->y+freearr_y[dir]; 00208 m = op->map; 00209 mflags = get_map_flags(m, &m, sx, sy, &sx, &sy); 00210 if (mflags&P_OUT_OF_MAP) 00211 temp = NULL; 00212 else { 00213 /* First we need to find a corpse, if any. */ 00214 /* If no object, temp will be set to NULL */ 00215 for (temp = GET_MAP_OB(m, sx, sy); temp != NULL; temp = temp->above) 00216 /* If it is corpse, this must be what we want to raise */ 00217 if (temp->type == CORPSE) 00218 break; 00219 } 00220 00221 if (temp == NULL) { 00222 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_SPELL, MSG_TYPE_SPELL_FAILURE, 00223 "You need a body for this spell.", NULL); 00224 return 0; 00225 } 00226 strcpy(name_to_resurrect, temp->name); 00227 } 00228 00229 /* no matter what, we fry the corpse. */ 00230 if (temp && temp->map) { 00231 /* replace corpse object with a burning object */ 00232 newob = arch_to_object(find_archetype("burnout")); 00233 if (newob != NULL) { 00234 newob->x = temp->x; 00235 newob->y = temp->y; 00236 insert_ob_in_map(newob, temp->map, op, 0); 00237 } 00238 leveldead = temp->level; 00239 remove_ob(temp); 00240 free_object(temp); 00241 } 00242 00243 if (resurrection_fails(clevel, leveldead)) { 00244 if (spell->randomitems) { 00245 treasure *t; 00246 00247 for (t = spell->randomitems->items; t; t = t->next) { 00248 summon_hostile_monsters(op, t->nrof, t->item->name); 00249 } 00250 00251 } 00252 return 1; 00253 } else { 00254 return resurrect_player(op, name_to_resurrect, spell); 00255 } 00256 /* Unreachable */ 00257 } 00258 00274 static int resurrection_fails(int levelcaster, int leveldead) { 00275 int chance = 9; 00276 00277 chance += levelcaster-leveldead; 00278 if (chance < 4) 00279 chance = 4; 00280 if (chance > rndm(0, 19)) 00281 return 0; /* resurrection succeeds */ 00282 return 1; 00283 } 00284 00291 void dead_player(object *op) { 00292 char filename[MAX_BUF]; 00293 char newname[MAX_BUF]; 00294 char path[MAX_BUF]; 00295 00296 /* set up our paths/strings... */ 00297 snprintf(path, sizeof(path), "%s/%s/%s/%s", settings.localdir, settings.playerdir, op->name, op->name); 00298 00299 strcpy(filename, path); 00300 strcat(filename, ".pl"); 00301 strcpy(newname, filename); 00302 strcat(newname, ".dead"); 00303 00304 if (rename(filename, newname) != 0) { 00305 LOG(llevError, "Cannot rename dead player's file %s into %s: %s\n", filename, newname, strerror_local(errno, path, sizeof(path))); 00306 } 00307 }