ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/resurrection.C
Revision: 1.8
Committed: Sat Sep 16 22:24:13 2006 UTC (17 years, 9 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.7: +1 -1 lines
Log Message:
mapstruct => maptile
removed many ytypedefs in favor of structure tags

File Contents

# User Rev Content
1 elmex 1.1 /*
2     CrossFire, A Multiplayer game for X-windows
3    
4     Copyright (C) 2002 Mark Wedel & Crossfire Development Team
5     Copyright (C) 1992 Frank Tore Johansen
6    
7     This program is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11    
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     GNU General Public License for more details.
16    
17     You should have received a copy of the GNU General Public License
18     along with this program; if not, write to the Free Software
19     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20    
21 root 1.7 The authors can be reached via e-mail at <crossfire@schmorp.de>
22 elmex 1.1 */
23    
24     /* the contents of this file were create solely by peterm@soda.berkeley.edu
25     all of the above disclaimers apply. */
26    
27     #include <global.h>
28     #ifndef __CEXTRACT__
29 root 1.5 # include <sproto.h>
30 elmex 1.1 #endif
31     #include <spells.h>
32     #include <errno.h>
33     #ifdef sequent
34 root 1.5
35 elmex 1.1 /* stoopid sequent includes don't do this like they should */
36 root 1.5 extern char *sys_errlist[];
37 elmex 1.1 extern int sys_nerr;
38     #endif
39     extern char **classname;
40     extern object *objects;
41    
42    
43    
44     /* name of the person to resurrect and which spell was used
45     * to resurrect
46     */
47 root 1.5 static int
48     resurrect_player (object *op, char *playername, object *spell)
49 elmex 1.1 {
50 root 1.5 FILE *deadplayer, *liveplayer;
51    
52     char oldname[MAX_BUF];
53     char newname[MAX_BUF];
54     char path[MAX_BUF];
55     char buf[MAX_BUF];
56     char buf2[MAX_BUF];
57     const char *race = NULL;
58     sint64 exp;
59     int Con;
60    
61    
62     /* reincarnation, which changes the race */
63     if (spell->race)
64     {
65     treasurelist *tl = find_treasurelist (spell->race);
66     treasure *t;
67     int value;
68    
69     if (!tl)
70     {
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     {
77     value -= t->chance;
78     if (value < 0)
79     break;
80     }
81     if (!t)
82     {
83     LOG (llevError, "resurrect_player: got null treasure from treasurelist %s!\n", &spell->race);
84     return 0;
85     }
86     race = t->item->name;
87     }
88    
89     /* set up our paths/strings... */
90     sprintf (path, "%s/%s/%s/%s", settings.localdir, settings.playerdir, playername, playername);
91    
92     strcpy (newname, path);
93     strcat (newname, ".pl");
94    
95     strcpy (oldname, newname);
96     strcat (oldname, ".dead");
97 elmex 1.1
98 root 1.5 if (!(deadplayer = fopen (oldname, "r")))
99     {
100     new_draw_info_format (NDI_UNIQUE, 0, op, "The soul of %s cannot be reached.", playername);
101     return 0;
102     }
103    
104     if (!access (newname, 0))
105     {
106     new_draw_info_format (NDI_UNIQUE, 0, op, "The soul of %s has already been reborn!", playername);
107     fclose (deadplayer);
108     return 0;
109     }
110    
111     if (!(liveplayer = fopen (newname, "w")))
112     {
113     new_draw_info_format (NDI_UNIQUE, 0, op, "The soul of %s cannot be re-embodied at the moment.", playername);
114     LOG (llevError, "Cannot write player in resurrect_player!\n");
115     fclose (deadplayer);
116     return 0;
117     }
118    
119     while (!feof (deadplayer))
120     {
121     fgets (buf, 255, deadplayer);
122     sscanf (buf, "%s", buf2);
123     if (!(strcmp (buf2, "exp")))
124     {
125     long long exp_;
126    
127     sscanf (buf, "%s %lld", buf2, &exp_);
128     exp = exp_;
129     if (spell->stats.exp)
130     {
131     exp -= exp / spell->stats.exp;
132     sprintf (buf, "exp %lld\n", exp_);
133     exp = exp_;
134 root 1.2 }
135     }
136 root 1.5 if (!(strcmp (buf2, "Con")))
137     {
138     sscanf (buf, "%s %d", buf2, &Con);
139     Con -= spell->stats.Con;
140     if (Con < 1)
141     Con = 1;
142     sprintf (buf, "Con %d\n", Con);
143     }
144     if (race && !strcmp (buf2, "race"))
145     {
146     sprintf (buf, "race %s\n", race);
147     }
148     fputs (buf, liveplayer);
149     }
150     fclose (liveplayer);
151     fclose (deadplayer);
152     unlink (oldname);
153     new_draw_info_format (NDI_UNIQUE, 0, op, "%s lives again!", playername);
154 elmex 1.1
155 root 1.5 return 1;
156 elmex 1.1 }
157    
158    
159     /* raise_dead by peterm and mehlhaff@soda.berkeley.edu
160     * op -- who is doing the resurrecting
161     * spell - spell object
162     * dir -- direction the spell is cast
163     * corpseobj - corpse to raise - can be null, in which case this function will find it
164     */
165 root 1.5 int
166     cast_raise_dead_spell (object *op, object *caster, object *spell, int dir, const char *arg)
167 elmex 1.1 {
168 root 1.5 object *temp, *newob;
169     char name_to_resurrect[MAX_BUF];
170     int leveldead = 25, mflags, clevel;
171     sint16 sx, sy;
172 root 1.8 maptile *m;
173 root 1.5
174     clevel = caster_level (caster, spell);
175    
176     if (spell->last_heal)
177     {
178     if (!arg)
179     {
180     new_draw_info_format (NDI_UNIQUE, 0, op, "Cast %s on who?", &spell->name);
181     return 0;
182 root 1.2 }
183 root 1.5 strcpy (name_to_resurrect, arg);
184     temp = NULL;
185     }
186     else
187     {
188     sx = op->x + freearr_x[dir];
189     sy = op->y + freearr_y[dir];
190     m = op->map;
191     mflags = get_map_flags (m, &m, sx, sy, &sx, &sy);
192     if (mflags & P_OUT_OF_MAP)
193 root 1.2 temp = NULL;
194 root 1.5 else
195     {
196     /* First we need to find a corpse, if any. */
197     /* If no object, temp will be set to NULL */
198     for (temp = get_map_ob (m, sx, sy); temp != NULL; temp = temp->above)
199     /* If it is corpse, this must be what we want to raise */
200     if (temp->type == CORPSE)
201     break;
202     }
203    
204     if (temp == NULL)
205     {
206     new_draw_info (NDI_UNIQUE, 0, op, "You need a body for this spell.");
207     return 0;
208     }
209     strcpy (name_to_resurrect, temp->name);
210     }
211 elmex 1.1
212 root 1.5 /* no matter what, we fry the corpse. */
213     if (temp && temp->map)
214     {
215     /* replace corpse object with a burning object */
216 root 1.6 newob = arch_to_object (archetype::find ("burnout"));
217 root 1.5 if (newob != NULL)
218     {
219     newob->x = temp->x;
220     newob->y = temp->y;
221     insert_ob_in_map (newob, temp->map, op, 0);
222     }
223     leveldead = temp->level;
224     remove_ob (temp);
225     free_object (temp);
226     }
227    
228     if (resurrection_fails (clevel, leveldead))
229     {
230     if (spell->randomitems)
231     {
232     treasure *t;
233    
234     for (t = spell->randomitems->items; t; t = t->next)
235     {
236     summon_hostile_monsters (op, t->nrof, t->item->name);
237 root 1.2 }
238 elmex 1.1
239 root 1.2 }
240 root 1.5 return 1;
241 elmex 1.1
242 root 1.5 }
243     else
244     {
245     return resurrect_player (op, name_to_resurrect, spell);
246 elmex 1.1 }
247    
248 root 1.5 return 1;
249 elmex 1.1 }
250    
251    
252 root 1.5 int
253     resurrection_fails (int levelcaster, int leveldead)
254 elmex 1.1 {
255 root 1.5 int chance = 9;
256    
257     /* scheme: equal in level, 50% success.
258     * +5 % for each level below, -5% for each level above.
259     * minimum 20%
260     */
261     chance += levelcaster - leveldead;
262     if (chance < 4)
263     chance = 4;
264     if (chance > rndm (0, 19))
265     return 0; /* resurrection succeeds */
266     return 1;
267 elmex 1.1 }
268    
269 root 1.5 void
270     dead_player (object *op)
271 elmex 1.1 {
272 root 1.5 char filename[MAX_BUF];
273     char newname[MAX_BUF];
274     char path[MAX_BUF];
275    
276     /* set up our paths/strings... */
277     sprintf (path, "%s/%s/%s/%s", settings.localdir, settings.playerdir, &op->name, &op->name);
278    
279     strcpy (filename, path);
280     strcat (filename, ".pl");
281     strcpy (newname, filename);
282     strcat (newname, ".dead");
283    
284     if (rename (filename, newname) != 0)
285     {
286     LOG (llevError, "Cannot rename dead player's file %s into %s: %s\n", filename, newname, strerror (errno));
287 elmex 1.1 }
288     }
289    
290    
291    
292 root 1.5 void
293     dead_character (const char *name)
294     {
295     char buf[MAX_BUF];
296     char buf2[MAX_BUF];
297    
298     sprintf (buf, "%s/%s/%s/%s.pl", settings.localdir, settings.playerdir, name, name);
299     /* peterm: create a .dead filename.... ***.pl.dead */
300     strcpy (buf2, buf);
301     strcat (buf, ".dead");
302     if (rename (buf2, buf) == -1)
303     {
304     LOG (llevError, "Cannot rename dead player's file %s into %s: %s\n", buf2, buf, strerror (errno));
305 elmex 1.1 }
306     }
307    
308    
309 root 1.5 int
310     dead_player_exists (const char *name)
311     {
312     char buf[MAX_BUF];
313 elmex 1.1
314 root 1.5 sprintf (buf, "%s/%s/%s/%s", settings.localdir, settings.playerdir, name, name);
315     strcat (buf, ".pl.dead");
316     return !(access (buf, 0));
317 elmex 1.1 }