ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/resurrection.C
Revision: 1.25
Committed: Sun May 4 18:24:11 2008 UTC (16 years ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.24: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

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