Crossfire Server, Trunk
resurrection.cpp
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
21 /* the contents of this file were create solely by peterm@soda.berkeley.edu
22  all of the above disclaimers apply. */
23 
24 #include "global.h"
25 
26 #include <errno.h>
27 #include <stdlib.h>
28 #include <string.h>
29 
30 #include "output_file.h"
31 #include "sproto.h"
32 #include "spells.h"
33 
34 static int resurrection_fails(int levelcaster, int leveldead);
35 
52 static int resurrect_player(object *op, char *playername, object *spell, char *accountname) {
53  FILE *deadplayer, *liveplayer;
54  OutputFile of;
55  char oldname[MAX_BUF];
56  char newname[MAX_BUF];
57  char path[MAX_BUF];
58  char buf[MAX_BUF];
59  char buf2[MAX_BUF];
60  const char *race = NULL;
61  int64_t exp;
62  int Con;
63 
64  /* reincarnation, which changes the race */
65  if (spell->race) {
67  treasure *t;
68  int value;
69 
70  if (!tl) {
71  LOG(llevError, "resurrect_player: race set to %s, but no treasurelist of that name!\n", spell->race);
72  return 0;
73  }
74  value = RANDOM()%tl->total_chance;
75  for (t = tl->items; t; t = t->next) {
76  value -= t->chance;
77  if (value < 0)
78  break;
79  }
80  if (!t) {
81  LOG(llevError, "resurrect_player: got null treasure from treasurelist %s!\n", spell->race);
82  return 0;
83  }
84  race = t->item->name;
85  }
86 
87  /* set up our paths/strings... */
88  snprintf(path, sizeof(path), "%s/%s/%s/%s", settings.localdir, settings.playerdir, playername, playername);
89 
90  strcpy(newname, path);
91  strcat(newname, ".pl");
92 
93  strcpy(oldname, newname);
94  strcat(oldname, ".dead");
95 
96  if (!(deadplayer = fopen(oldname, "r"))) {
98  "The soul of %s cannot be reached.",
99  playername);
100  return 0;
101  }
102 
103  if (!access(newname, 0)) {
105  "The soul of %s has already been reborn!",
106  playername);
107  fclose(deadplayer);
108  return 0;
109  }
110 
111  liveplayer = of_open(&of, newname);
112  if (liveplayer == NULL) {
114  "The soul of %s cannot be re-embodied at the moment.",
115  playername);
116  fclose(deadplayer);
117  return 0;
118  }
119 
120  while (!feof(deadplayer)) {
121  if ( fgets(buf, 255, deadplayer) == NULL ) break; /* should never fail */
122  sscanf(buf, "%s", buf2);
123  if (!(strcmp(buf2, "exp"))) {
124  sscanf(buf, "%s %" FMT64, buf2, &exp);
125  if (spell->stats.exp) {
126  exp -= exp/spell->stats.exp;
127  snprintf(buf, sizeof(buf), "exp %" FMT64 "\n", exp);
128  }
129  }
130  if (!(strcmp(buf2, "Con"))) {
131  sscanf(buf, "%s %d", buf2, &Con);
132  Con -= spell->stats.Con;
133  if (Con < 1)
134  Con = 1;
135  snprintf(buf, sizeof(buf), "Con %d\n", Con);
136  }
137  if (race && !strcmp(buf2, "race")) {
138  snprintf(buf, sizeof(buf), "race %s\n", race);
139  }
140  fputs(buf, liveplayer);
141  }
142  if (!of_close(&of)) {
144  "The soul of %s cannot be re-embodied at the moment.",
145  playername);
146  fclose(deadplayer);
147  return 0;
148  }
149  fclose(deadplayer);
150  unlink(oldname);
152  "%s lives again!",
153  playername);
154  /* Needs to go into the account file and change the player back to isDead = 0 */
155  /* I'm fairly certain the old login did not have the segfault, so just account for the new account system */
156  if (accountname)
157  unmake_perma_dead(accountname, playername);
158  return 1;
159 }
160 
181 int cast_raise_dead_spell(object *op, object *caster, object *spell, int dir, const char *arg) {
182  object *temp, *newob;
183  char name_to_resurrect[MAX_BUF];
184  char *corpse_account = NULL;
185  int leveldead = 25, mflags, clevel;
186  int16_t sx, sy;
187  mapstruct *m;
188  int spell_success = 0;
189 
190  clevel = caster_level(caster, spell);
191 
192  if (spell->last_heal) {
193  if (!arg) {
195  "Cast %s on who?",
196  spell->name);
197  return 0;
198  }
199  safe_strncpy(name_to_resurrect, arg, sizeof(name_to_resurrect));
200  temp = NULL;
201  } else {
202  sx = op->x+freearr_x[dir];
203  sy = op->y+freearr_y[dir];
204  m = op->map;
205  mflags = get_map_flags(m, &m, sx, sy, &sx, &sy);
206  if (mflags&P_OUT_OF_MAP)
207  temp = NULL;
208  else {
209  /* First we need to find a corpse, if any. */
210  /* If no object, temp will be set to NULL */
211  temp = NULL;
212  FOR_MAP_PREPARE(m, sx, sy, tmp)
213  /* If it is corpse, this must be what we want to raise */
214  if (tmp->type == CORPSE) {
215  temp = tmp;
216  break;
217  }
218  FOR_MAP_FINISH();
219  }
220 
221  if (temp == NULL) {
223  "You need a body for this spell.");
224  return 0;
225  }
226  safe_strncpy(name_to_resurrect, temp->name, sizeof(name_to_resurrect));
227  /* Only try to copy if dead body is as recent as the patch this is from. */
228  if (temp->slaying){
229  corpse_account = (char *)CALLOC(sizeof(char), MAX_BUF);
230  /* Make sure that the allocation worked. */
231  if (corpse_account) strcpy(corpse_account, temp->slaying);
232  }
233  }
234  /* no matter what, we fry the corpse. */
235  if (temp && temp->map) {
236  /* replace corpse object with a burning object */
237  archetype *arch = find_archetype("burnout");
238  if (arch != NULL) {
240  if (newob != NULL)
241  object_insert_in_map_at(newob, temp->map, op, 0, temp->x, temp->y);
242  }
243  leveldead = temp->level;
246  }
247 
248  if (resurrection_fails(clevel, leveldead)) {
249  if (spell->randomitems) {
250  treasure *t;
251 
252  for (t = spell->randomitems->items; t; t = t->next) {
253  summon_hostile_monsters(op, t->nrof, t->item->name);
254  }
255  }
256  spell_success = 1;
257  } else {
258  spell_success = resurrect_player(op, name_to_resurrect, spell, corpse_account);
259  }
260  /* Reorganized so corpse_account could be deallocated if needed */
261  free(corpse_account);
262  return spell_success;
263 }
264 
280 static int resurrection_fails(int levelcaster, int leveldead) {
281  int chance = 9;
282 
283  chance += levelcaster-leveldead;
284  if (chance < 4)
285  chance = 4;
286  if (chance > rndm(0, 19))
287  return 0; /* resurrection succeeds */
288  return 1;
289 }
290 
297 void dead_player(object *op) {
298  char filename[MAX_BUF];
299  char newname[MAX_BUF];
300  char path[MAX_BUF];
301 
302  /* set up our paths/strings... */
303  snprintf(path, sizeof(path), "%s/%s/%s/%s", settings.localdir, settings.playerdir, op->name, op->name);
304 
305  strcpy(filename, path);
306  strcat(filename, ".pl");
307  strcpy(newname, filename);
308  strcat(newname, ".dead");
309 
310  if (rename(filename, newname) != 0) {
311  LOG(llevError, "Cannot rename dead player's file %s into %s: %s\n", filename, newname, strerror(errno));
312  }
313  /* Go into the account file and change isDead for this character to 1. */
314  if (make_perma_dead(op)){
315  /* Make an error message saying that the character could not be changed in the proper account */
316  LOG(llevError, "Could not edit the account to indicate permanent death for %s!\n", op->name);
317  }
318 }
output_file.h
global.h
settings
struct Settings settings
Definition: init.cpp:139
safe_strncpy
#define safe_strncpy
Definition: compat.h:27
FOR_MAP_FINISH
#define FOR_MAP_FINISH()
Definition: define.h:730
llevError
@ llevError
Definition: logger.h:11
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.cpp:51
make_perma_dead
int make_perma_dead(object *op)
Definition: account_char.cpp:379
of_close
int of_close(OutputFile *of)
Definition: output_file.cpp:61
of_open
FILE * of_open(OutputFile *of, const char *fname)
Definition: output_file.cpp:30
archininventory.arch
arch
DIALOGCHECK MINARGS 1 MAXARGS 1
Definition: archininventory.py:16
treasurelist::items
treasure * items
Definition: treasure.h:92
treasurelist::total_chance
int16_t total_chance
Definition: treasure.h:87
sword_of_souls.Con
Con
Definition: sword_of_souls.py:58
Settings::localdir
const char * localdir
Definition: global.h:249
draw_ext_info_format
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...) PRINTF_ARGS(6
CALLOC
#define CALLOC(x, y)
Definition: compat.h:31
Ice.tmp
int tmp
Definition: Ice.py:207
find_treasurelist
treasurelist * find_treasurelist(const char *name)
Definition: assets.cpp:249
npc_dialog.filename
filename
Definition: npc_dialog.py:99
buf
StringBuffer * buf
Definition: readable.cpp:1552
dead_player
void dead_player(object *op)
Definition: resurrection.cpp:297
cast_raise_dead_spell
int cast_raise_dead_spell(object *op, object *caster, object *spell, int dir, const char *arg)
Definition: resurrection.cpp:181
draw_ext_info
vs only yadda is in because all tags get reset on the next draw_ext_info In the second since it is all in one draw_ext_info
Definition: media-tags.txt:61
MSG_TYPE_SPELL_SUCCESS
#define MSG_TYPE_SPELL_SUCCESS
Definition: newclient.h:624
m
static event_registration m
Definition: citylife.cpp:425
object_free_drop_inventory
void object_free_drop_inventory(object *ob)
Definition: object.cpp:1555
FMT64
#define FMT64
Definition: compat.h:16
freearr_y
short freearr_y[SIZEOFFREE]
Definition: object.cpp:305
treasurelist
Definition: treasure.h:85
of
a copper bar weighs and has a value of
Definition: ore.txt:3
unmake_perma_dead
int unmake_perma_dead(char *account, char *player)
Definition: account_char.cpp:421
spell
with a maximum of six This is not so if you are wearing plate you receive no benefit Armour is additive with all the supplementry forms of which means that it lasts until the next semi permanent spell effect is cast upon the character spell
Definition: tome-of-magic.txt:44
caster_level
int caster_level(const object *caster, const object *spell)
Definition: spell_util.cpp:194
archetype
Definition: object.h:474
Settings::playerdir
const char * playerdir
Definition: global.h:250
sproto.h
MSG_TYPE_SPELL
#define MSG_TYPE_SPELL
Definition: newclient.h:400
object_insert_in_map_at
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Definition: object.cpp:2095
P_OUT_OF_MAP
#define P_OUT_OF_MAP
Definition: map.h:248
MAX_BUF
#define MAX_BUF
Definition: define.h:35
path
pluglist shows those as well as a short text describing each the list will simply appear empty The keyword for the Python plugin is Python plugout< keyword > Unloads a given identified by its _keyword_ So if you want to unload the Python you need to do plugout Python plugin< libname > Loads a given whose _filename_ is libname So in the case of you d have to do a plugin cfpython so Note that all filenames are relative to the default plugin path(SHARE/plugins). Console messages. ----------------- When Crossfire starts
RANDOM
#define RANDOM()
Definition: define.h:644
FOR_MAP_PREPARE
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Definition: define.h:723
NDI_UNIQUE
#define NDI_UNIQUE
Definition: newclient.h:251
spells.h
resurrection_fails
static int resurrection_fails(int levelcaster, int leveldead)
Definition: resurrection.cpp:280
MSG_TYPE_SPELL_FAILURE
#define MSG_TYPE_SPELL_FAILURE
Definition: newclient.h:622
get_map_flags
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, int16_t x, int16_t y, int16_t *nx, int16_t *ny)
Definition: map.cpp:299
mapstruct
Definition: map.h:314
give.op
op
Definition: give.py:33
autojail.value
value
Definition: autojail.py:6
Floor.t
t
Definition: Floor.py:62
find_archetype
archetype * find_archetype(const char *name)
Definition: assets.cpp:266
summon_hostile_monsters
int summon_hostile_monsters(object *op, int n, const char *monstername)
Definition: spell_util.cpp:1005
OutputFile
Definition: output_file.h:41
arch_to_object
object * arch_to_object(archetype *at)
Definition: arch.cpp:229
CORPSE
@ CORPSE
Definition: object.h:248
object_remove
void object_remove(object *op)
Definition: object.cpp:1828
resurrect_player
static int resurrect_player(object *op, char *playername, object *spell, char *accountname)
Definition: resurrection.cpp:52
rndm
int rndm(int min, int max)
Definition: utils.cpp:162
treasure
Definition: treasure.h:63
freearr_x
short freearr_x[SIZEOFFREE]
Definition: object.cpp:299
commongive.newob
newob
Definition: commongive.py:47
guildbuy.temp
def temp
Definition: guildbuy.py:26