Crossfire Server, Trunk  1.75.0
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) {
239  newob = arch_to_object(arch);
240  if (newob != NULL)
241  object_insert_in_map_at(newob, temp->map, op, 0, temp->x, temp->y);
242  }
243  leveldead = temp->level;
244  object_remove(temp);
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
Global settings.
Definition: init.cpp:139
safe_strncpy
#define safe_strncpy
Definition: compat.h:27
FOR_MAP_FINISH
#define FOR_MAP_FINISH()
Finishes FOR_MAP_PREPARE().
Definition: define.h:724
llevError
@ llevError
Error, serious thing.
Definition: logger.h:11
LOG
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.cpp:58
make_perma_dead
int make_perma_dead(object *op)
This will edit the character account information so that the character that just died in permadeath w...
Definition: account_char.cpp:379
of_close
int of_close(OutputFile *of)
Closes an output file.
Definition: output_file.cpp:61
of_open
FILE * of_open(OutputFile *of, const char *fname)
Opens an output file.
Definition: output_file.cpp:30
treasurelist::items
treasure * items
Items in this list, linked.
Definition: treasure.h:92
treasurelist::total_chance
int16_t total_chance
If non-zero, only 1 item on this list should be generated.
Definition: treasure.h:87
object::x
int16_t x
Definition: object.h:335
object::map
struct mapstruct * map
Pointer to the map in which this object is present.
Definition: object.h:305
find_treasurelist
treasurelist * find_treasurelist(const char *name)
Search for the given treasurelist by name.
Definition: assets.cpp: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
rndm
int rndm(int min, int max)
Returns a number between min and max.
Definition: utils.cpp:162
object::level
int16_t level
Level of creature or object.
Definition: object.h:361
buf
StringBuffer * buf
Definition: readable.cpp:1565
dead_player
void dead_player(object *op)
Kill a player on a permanent death server with resurrection.
Definition: resurrection.cpp:297
cast_raise_dead_spell
int cast_raise_dead_spell(object *op, object *caster, object *spell, int dir, const char *arg)
This handles the raise dead / resurrection spells.
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
Spell succeeded messages.
Definition: newclient.h:639
object::y
int16_t y
Position in the map for this object.
Definition: object.h:335
m
static event_registration m
Definition: citylife.cpp:424
object_free_drop_inventory
void object_free_drop_inventory(object *ob)
Frees everything allocated by an object, removes it from the list of used objects,...
Definition: object.cpp:1545
FMT64
#define FMT64
Definition: compat.h:16
freearr_y
short freearr_y[SIZEOFFREE]
Y offset when searching around a spot.
Definition: object.cpp:305
treasurelist
treasurelist represents one logical group of items to be generated together.
Definition: treasure.h:85
unmake_perma_dead
int unmake_perma_dead(char *account, char *player)
This will edit the character account information so that the character that was just resurrected in p...
Definition: account_char.cpp:421
t
in that case they will be relative to whatever the PWD of the crossfire server process is You probably shouldn t
Definition: server-directories.txt:28
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)
This function returns the effective level the spell is being cast at.
Definition: spell_util.cpp:194
archetype
The archetype structure is a set of rules on how to generate and manipulate objects which point to ar...
Definition: object.h:483
sproto.h
MSG_TYPE_SPELL
#define MSG_TYPE_SPELL
Spell related info.
Definition: newclient.h:415
object_insert_in_map_at
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Same as object_insert_in_map() except it handle separate coordinates and do a clean job preparing mul...
Definition: object.cpp:2085
P_OUT_OF_MAP
#define P_OUT_OF_MAP
This space is outside the map.
Definition: map.h:249
MAX_BUF
#define MAX_BUF
Used for all kinds of things.
Definition: define.h:35
Settings::playerdir
const char * playerdir
Where the player files are.
Definition: global.h:251
RANDOM
#define RANDOM()
Definition: define.h:638
FOR_MAP_PREPARE
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Constructs a loop iterating over all objects of a map tile.
Definition: define.h:717
NDI_UNIQUE
#define NDI_UNIQUE
Print immediately, don't buffer.
Definition: newclient.h:266
object::slaying
sstring slaying
Which race to do double damage to.
Definition: object.h:327
spells.h
resurrection_fails
static int resurrection_fails(int levelcaster, int leveldead)
Will the resurrection succeed?
Definition: resurrection.cpp:280
object::name
sstring name
The name of the object, obviously...
Definition: object.h:319
MSG_TYPE_SPELL_FAILURE
#define MSG_TYPE_SPELL_FAILURE
Spell failure messages.
Definition: newclient.h:637
get_map_flags
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, int16_t x, int16_t y, int16_t *nx, int16_t *ny)
This rolls up wall, blocks_magic, blocks_view, etc, all into one function that just returns a P_.
Definition: map.cpp:300
mapstruct
This is a game-map.
Definition: map.h:315
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)
Summons hostile monsters and places them in nearby squares.
Definition: spell_util.cpp:1005
arch_to_object
object * arch_to_object(archetype *at)
Creates and returns a new object which is a copy of the given archetype.
Definition: arch.cpp:227
CORPSE
@ CORPSE
Definition: object.h:248
object_remove
void object_remove(object *op)
This function removes the object op from the linked list of objects which it is currently tied to.
Definition: object.cpp:1818
resurrect_player
static int resurrect_player(object *op, char *playername, object *spell, char *accountname)
Resurrect a player.
Definition: resurrection.cpp:52
chance
bool chance(int a, int b)
Return true with a probability of a/b.
Definition: treasure.cpp:890
treasure
treasure is one element in a linked list, which together consist of a complete treasure-list.
Definition: treasure.h:63
freearr_x
short freearr_x[SIZEOFFREE]
X offset when searching around a spot.
Definition: object.cpp:299
OutputFile
Definition: output_file.h:41
Settings::localdir
const char * localdir
Read/write data files.
Definition: global.h:250