ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/player.C
Revision: 1.152
Committed: Sun Jul 1 05:00:20 2007 UTC (16 years, 11 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.151: +10 -11 lines
Log Message:
- upgrade crossfire trt to the GPL version 3 (hopefully correctly).
- add a single file covered by the GNU Affero General Public License
  (which is not yet released, so I used the current draft, which is
  legally a bit wavy, but its likely better than nothing as it expresses
  direct intent by the authors, and we can upgrade as soon as it has been
  released).
  * this should ensure availability of source code for the server at least
    and hopefully also archetypes and maps even when modified versions
    are not being distributed, in accordance of section 13 of the agplv3.

File Contents

# User Rev Content
1 elmex 1.1 /*
2 root 1.145 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
3     *
4     * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team
5     * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team
6     * Copyright (©) 1992,2007 Frank Tore Johansen
7     *
8 root 1.152 * Crossfire TRT is free software: you can redistribute it and/or modify
9     * 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 root 1.145 *
13 root 1.152 * 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 root 1.145 *
18 root 1.152 * 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.145 *
21     * The authors can be reached via e-mail to <crossfire@schmorp.de>
22 root 1.89 */
23 elmex 1.1
24     #include <global.h>
25 root 1.38 #include <sproto.h>
26 elmex 1.1 #include <sounds.h>
27     #include <living.h>
28     #include <object.h>
29     #include <spells.h>
30     #include <skills.h>
31    
32 root 1.54 #include <algorithm>
33     #include <functional>
34 elmex 1.1
35 root 1.89 playervec players;
36 elmex 1.1
37 root 1.18 void
38     display_motd (const object *op)
39     {
40     char buf[MAX_BUF];
41     char motd[HUGE_BUF];
42     FILE *fp;
43     int comp;
44     int size;
45 elmex 1.1
46 root 1.18 sprintf (buf, "%s/%s", settings.confdir, settings.motd);
47     if ((fp = open_and_uncompress (buf, 0, &comp)) == NULL)
48 root 1.44 return;
49    
50 root 1.18 motd[0] = '\0';
51     size = 0;
52 root 1.44
53 root 1.53 while (fgets (buf, MAX_BUF, fp))
54 root 1.18 {
55     if (*buf == '#')
56     continue;
57 root 1.44
58 root 1.18 strncat (motd + size, buf, HUGE_BUF - size);
59     size += strlen (buf);
60 elmex 1.1 }
61 root 1.44
62 root 1.18 draw_ext_info (NDI_UNIQUE | NDI_GREEN, 0, op, MSG_TYPE_MOTD, MSG_SUBTYPE_NONE, motd, NULL);
63     close_and_delete (fp, comp);
64 elmex 1.1 }
65    
66 root 1.18 void
67     send_rules (const object *op)
68     {
69     char buf[MAX_BUF];
70     char rules[HUGE_BUF];
71     FILE *fp;
72     int comp;
73     int size;
74    
75     sprintf (buf, "%s/%s", settings.confdir, settings.rules);
76     if ((fp = open_and_uncompress (buf, 0, &comp)) == NULL)
77 root 1.44 return;
78    
79 root 1.18 rules[0] = '\0';
80     size = 0;
81 root 1.44
82 root 1.53 while (fgets (buf, MAX_BUF, fp))
83 root 1.18 {
84     if (*buf == '#')
85 elmex 1.1 continue;
86 root 1.44
87 root 1.18 if (size + strlen (buf) >= HUGE_BUF)
88     {
89     LOG (llevDebug, "Warning, rules size is > %d bytes.\n", HUGE_BUF);
90 elmex 1.1 break;
91 root 1.18 }
92 root 1.44
93 root 1.18 strncat (rules + size, buf, HUGE_BUF - size);
94     size += strlen (buf);
95 elmex 1.1 }
96 root 1.44
97 root 1.18 draw_ext_info (NDI_UNIQUE | NDI_GREEN, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_RULES, rules, NULL);
98     close_and_delete (fp, comp);
99 elmex 1.1 }
100    
101 root 1.18 void
102     send_news (const object *op)
103     {
104     char buf[MAX_BUF];
105     char news[HUGE_BUF];
106     char subject[MAX_BUF];
107     FILE *fp;
108     int comp;
109     int size;
110    
111     sprintf (buf, "%s/%s", settings.confdir, settings.news);
112     if ((fp = open_and_uncompress (buf, 0, &comp)) == NULL)
113     return;
114 root 1.44
115 root 1.18 news[0] = '\0';
116     subject[0] = '\0';
117     size = 0;
118 root 1.44
119 root 1.104 while (fgets (buf, MAX_BUF, fp))
120 root 1.18 {
121     if (*buf == '#')
122     continue;
123 root 1.44
124 root 1.18 if (*buf == '%')
125     { /* send one news */
126     if (size > 0)
127 root 1.109 draw_ext_info_format (NDI_UNIQUE | NDI_GREEN, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_NEWS, "INFORMATION: %s\n%s", (char *)"%s\n%s", subject, news); /*send previously read news */
128 root 1.89
129 root 1.18 strcpy (subject, buf + 1);
130     strip_endline (subject);
131     size = 0;
132     news[0] = '\0';
133     }
134     else
135     {
136     if (size + strlen (buf) >= HUGE_BUF)
137     {
138     LOG (llevDebug, "Warning, one news item has size > %d bytes.\n", HUGE_BUF);
139 elmex 1.1 break;
140 root 1.18 }
141     strncat (news + size, buf, HUGE_BUF - size);
142     size += strlen (buf);
143     }
144 elmex 1.1 }
145 root 1.18
146     draw_ext_info_format (NDI_UNIQUE | NDI_GREEN, 0, op,
147 root 1.109 MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_NEWS, "INFORMATION: %s\n%s\n", (char *)"%s\n%s", subject, news);
148 root 1.18 close_and_delete (fp, comp);
149 elmex 1.1 }
150    
151 root 1.54 /* This loads the first map an puts the player on it. */
152     static void
153     set_first_map (object *op)
154     {
155 root 1.77 op->contr->maplevel = first_map_path;
156 root 1.54 op->x = -1;
157     op->y = -1;
158 root 1.75 }
159    
160     void
161 root 1.89 player::activate ()
162     {
163     if (active)
164     return;
165    
166     players.insert (this);
167     ob->remove ();
168     ob->map = 0;
169     ob->activate_recursive ();
170 root 1.92 CLEAR_FLAG (ob, FLAG_FRIENDLY);
171     add_friendly_object (ob);
172 root 1.89 }
173    
174     void
175     player::deactivate ()
176     {
177     if (!active)
178     return;
179    
180     terminate_all_pets (ob);
181 root 1.92 remove_friendly_object (ob);
182 root 1.89 ob->deactivate_recursive ();
183 root 1.111
184     if (ob->map)
185     maplevel = ob->map->path;
186    
187 root 1.89 ob->remove ();
188     ob->map = 0;
189 root 1.104 party = 0;
190 root 1.89
191 root 1.119 combat_ob = ranged_ob = 0; //TODO, should be special marker, non-refcounted, not this
192 root 1.92
193 root 1.89 players.erase (this);
194     }
195    
196 root 1.56 // connect the player with a specific client
197 root 1.122 // also changes, rationalises, and fixes some incorrect settings
198 root 1.54 void
199     player::connect (client *ns)
200 root 1.18 {
201 root 1.54 this->ns = ns;
202     ns->pl = this;
203    
204 root 1.95 run_on = 0;
205     fire_on = 0;
206 root 1.103 ob->close_container (); //TODO: client-specific
207 root 1.95
208 root 1.54 ns->update_look = 0;
209     ns->look_position = 0;
210    
211 root 1.147 clear_los (this);
212 root 1.54
213 root 1.95 ns->reset_stats ();
214 root 1.93
215 root 1.57 /* make sure he's a player -- needed because of class change. */
216 root 1.54 ob->type = PLAYER; // we are paranoid
217 root 1.149 ob->race = ob->arch->race;
218 elmex 1.1
219 root 1.54 ob->carrying = sum_weight (ob);
220     link_player_skills (ob);
221 elmex 1.1
222 root 1.56 CLEAR_FLAG (ob, FLAG_NO_FIX_PLAYER);
223 elmex 1.1
224 root 1.149 assign (title, ob->arch->object::name);
225 root 1.15
226 root 1.54 /* if it's a dragon player, set the correct title here */
227     if (is_dragon_pl (ob))
228     {
229     object *tmp, *abil = 0, *skin = 0;
230    
231     shstr_cmp dragon_ability_force ("dragon_ability_force");
232     shstr_cmp dragon_skin_force ("dragon_skin_force");
233    
234     for (tmp = ob->inv; tmp; tmp = tmp->below)
235     if (tmp->type == FORCE)
236 root 1.148 if (tmp->arch->archname == dragon_ability_force)
237 root 1.54 abil = tmp;
238 root 1.148 else if (tmp->arch->archname == dragon_skin_force)
239 root 1.54 skin = tmp;
240    
241     set_dragon_name (ob, abil, skin);
242     }
243    
244     new_draw_info (NDI_UNIQUE, 0, ob, "Welcome Back!");
245    
246 root 1.60 esrv_new_player (this, ob->weight + ob->carrying);
247    
248 root 1.139 ob->flag [FLAG_READY_WEAPON] = false;
249     ob->flag [FLAG_READY_SKILL] = false;
250     ob->flag [FLAG_READY_BOW] = false;
251    
252 root 1.122 for (object *op = ob->inv; op; op = op->below)
253     if (op->flag [FLAG_APPLIED])
254     switch (op->type)
255     {
256 root 1.140 case SKILL:
257     ob->flag [FLAG_APPLIED] = false;
258     break;
259    
260 root 1.122 case WAND:
261     case ROD:
262     case HORN:
263     case BOW:
264 root 1.140 ranged_ob = op;
265 root 1.122 break;
266 root 1.139
267 root 1.140 case WEAPON:
268     combat_ob = op;
269 root 1.139 break;
270 root 1.122 }
271    
272 root 1.139 ob->change_weapon (combat_ob ? combat_ob : ranged_ob);
273 root 1.60 ob->update_stats ();
274 root 1.139
275 root 1.54 ns->floorbox_update ();
276     esrv_send_inventory (ob, ob);
277     esrv_add_spells (this, 0);
278    
279 root 1.89 activate ();
280 root 1.54
281 root 1.59 send_rules (ob);
282     send_news (ob);
283     display_motd (ob);
284 root 1.78
285     INVOKE_PLAYER (CONNECT, this);
286 root 1.54 INVOKE_PLAYER (LOGIN, this);
287     }
288 elmex 1.1
289 root 1.62 void
290     player::disconnect ()
291     {
292 root 1.63 if (ns)
293 root 1.72 {
294 root 1.89 if (active)
295     INVOKE_PLAYER (LOGOUT, this, ARG_INT (0));
296 root 1.78
297     INVOKE_PLAYER (DISCONNECT, this);
298 root 1.72
299 root 1.97 ns->reset_stats ();
300 root 1.72 ns->pl = 0;
301 root 1.115 ns = 0;
302 root 1.89 }
303 root 1.72
304 root 1.105 if (ob)
305     ob->close_container (); //TODO: client-specific
306    
307 root 1.150 observe = ob;
308    
309 root 1.89 deactivate ();
310 root 1.62 }
311    
312 root 1.54 // the need for this function can be explained
313     // by load_object not returning the object
314     void
315     player::set_object (object *op)
316     {
317 root 1.146 ob = observe = op;
318 root 1.104 ob->contr = this; /* this aren't yet in archetype */
319 root 1.15
320 root 1.142 ob->speed = 1.0f;
321     ob->speed_left = 0.5f;
322    
323     ob->direction = 5; /* So player faces south */
324 root 1.54 }
325 root 1.15
326 root 1.146 void
327     player::set_observe (object *op)
328     {
329     observe = op ? op : ob;
330 root 1.147 do_los = 1;
331 root 1.146 }
332    
333 root 1.54 player::player ()
334     {
335 pippijn 1.81 /* There are some elements we want initialised to non zero value -
336 root 1.54 * we deal with that below this point.
337     */
338 root 1.114 outputs_sync = 4;
339     outputs_count = 4;
340 root 1.54 unapply = unapply_nochoice;
341    
342 root 1.77 savebed_map = first_map_path; /* Init. respawn position */
343 root 1.54
344     gen_sp_armour = 10;
345     bowtype = bow_normal;
346     petmode = pet_normal;
347     listening = 10;
348     usekeys = containers;
349     peaceful = 1; /* default peaceful */
350     do_los = 1;
351 root 1.142
352     weapon_sp = 1.0f;
353     weapon_sp_left = 0.5f;
354 root 1.54 }
355    
356 root 1.62 void
357     player::do_destroy ()
358 root 1.54 {
359 root 1.72 disconnect ();
360 root 1.62
361 root 1.72 attachable::do_destroy ();
362 root 1.62
363 root 1.54 if (ob)
364 root 1.69 {
365     ob->destroy_inv (false);
366     ob->destroy ();
367     }
368 root 1.151
369     ob = observe = 0;
370 root 1.62 }
371    
372     player::~player ()
373     {
374 root 1.54 /* Clear item stack */
375     free (stack_items);
376 elmex 1.1 }
377    
378 root 1.54 /* Tries to add player on the connection passed in ns.
379 elmex 1.1 * All we can really get in this is some settings like host and display
380     * mode.
381     */
382 root 1.54 player *
383     player::create ()
384 root 1.18 {
385 root 1.54 player *pl = new player;
386 root 1.38
387 root 1.54 pl->set_object (arch_to_object (get_player_archetype (0)));
388 root 1.104
389     pl->ob->roll_stats ();
390     pl->ob->stats.wc = 2;
391     pl->ob->run_away = 25; /* Then we panick... */
392    
393 root 1.76 set_first_map (pl->ob);
394 root 1.26
395 root 1.54 return pl;
396 elmex 1.1 }
397    
398     /*
399     * get_player_archetype() return next player archetype from archetype
400     * list. Not very efficient routine, but used only creating new players.
401     * Note: there MUST be at least one player archetype!
402     */
403 root 1.18 archetype *
404     get_player_archetype (archetype *at)
405 elmex 1.1 {
406 root 1.149 archvec::iterator i = at ? archetypes.find (at) : archetypes.begin ();
407 root 1.18
408     for (;;)
409     {
410 root 1.149 if (++i == archetypes.end ())
411     i = archetypes.begin ();
412     else if (*i == at)
413     cleanup ("not a single player archetype found");
414 root 1.46
415 root 1.149 if ((*i)->type == PLAYER)
416     return *i;
417 elmex 1.1 }
418     }
419    
420 root 1.18 object *
421     get_nearest_player (object *mon)
422     {
423     object *op = NULL;
424     objectlink *ol;
425     unsigned lastdist;
426     rv_vector rv;
427    
428 root 1.92 for (ol = first_friendly_object, lastdist = 1000; ol; ol = ol->next)
429 root 1.18 {
430     /* We should not find free objects on this friendly list, but it
431     * does periodically happen. Given that, lets deal with it.
432     * While unlikely, it is possible the next object on the friendly
433     * list is also free, so encapsulate this in a while loop.
434     */
435     while (QUERY_FLAG (ol->ob, FLAG_FREED) || !QUERY_FLAG (ol->ob, FLAG_FRIENDLY))
436     {
437     object *tmp = ol->ob;
438    
439     /* Can't do much more other than log the fact, because the object
440     * itself will have been cleared.
441     */
442 root 1.92 LOG (llevDebug, "get_nearest_player: Found free/non friendly object '%s' on friendly list\n",
443     tmp->debug_desc ());
444 root 1.18 ol = ol->next;
445     remove_friendly_object (tmp);
446     if (!ol)
447     return op;
448     }
449 root 1.11
450 root 1.18 /* Remove special check for player from this. First, it looks to cause
451     * some crashes (ol->ob->contr not set properly?), but secondly, a more
452     * complicated method of state checking would be needed in any case -
453     * as it was, a clever player could type quit, and the function would
454     * skip them over while waiting for confirmation. Remove
455     * on_same_map check, as can_detect_enemy also does this
456     */
457     if (!can_detect_enemy (mon, ol->ob, &rv))
458     continue;
459 root 1.11
460 root 1.18 if (lastdist > rv.distance)
461     {
462     op = ol->ob;
463     lastdist = rv.distance;
464 root 1.11 }
465 elmex 1.1 }
466 root 1.61
467     for_all_players (pl)
468     if (can_detect_enemy (mon, pl->ob, &rv))
469     if (lastdist > rv.distance)
470 root 1.18 {
471 root 1.61 op = pl->ob;
472     lastdist = rv.distance;
473     }
474 elmex 1.1
475     #if 0
476 root 1.18 LOG (llevDebug, "get_nearest_player() finds player: %s\n", op ? &op->name : "(null)");
477 elmex 1.1 #endif
478 root 1.18 return op;
479 elmex 1.1 }
480    
481     /* I believe this can safely go to 2, 3 is questionable, 4 will likely
482     * result in a monster paths backtracking. It basically determines how large a
483     * detour a monster will take from the direction path when looking
484     * for a path to the player. The values are in the amount of direction
485     * the deviation is
486     */
487     #define DETOUR_AMOUNT 2
488    
489     /* This is used to prevent infinite loops. Consider a case where the
490     * player is in a chamber (with gate closed), and monsters are outside.
491     * with DETOUR_AMOUNT==2, the function will turn each corner, trying to
492     * find a path into the chamber. This is a good thing, but since there
493     * is no real path, it will just keep circling the chamber for
494     * ever (this could be a nice effect for monsters, but not for the function
495     * to get stuck in. I think for the monsters, if max is reached and
496     * we return the first direction the creature could move would result in the
497     * circling behaviour. Unfortunately, this function is also used to determined
498     * if the creature should cast a spell, so returning a direction in that case
499     * is probably not a good thing.
500     */
501     #define MAX_SPACES 50
502    
503     /*
504     * Returns the direction to the player, if valid. Returns 0 otherwise.
505     * modified to verify there is a path to the player. Does this by stepping towards
506     * player and if path is blocked then see if blockage is close enough to player that
507     * direction to player is changed (ie zig or zag). Continue zig zag until either
508     * reach player or path is blocked. Thus, will only return true if there is a free
509     * path to player. Though path may not be a straight line. Note that it will find
510     * player hiding along a corridor at right angles to the corridor with the monster.
511     *
512     * Modified by MSW 2001-08-06 to handle tiled maps. Various notes:
513     * 1) With DETOUR_AMOUNT being 2, it should still go and find players hiding
514     * down corriders.
515     * 2) I think the old code was broken if the first direction the monster
516     * should move was blocked - the code would store the first direction without
517     * verifying that the player can actually move in that direction. The new
518     * code does not store anything in firstdir until we have verified that the
519     * monster can in fact move one space in that direction.
520     * 3) I'm not sure how good this code will be for moving multipart monsters,
521     * since only simple checks to blocked are being called, which could mean the monster
522     * is blocking itself.
523     */
524 root 1.18 int
525     path_to_player (object *mon, object *pl, unsigned mindiff)
526     {
527     rv_vector rv;
528     sint16 x, y;
529     int lastx, lasty, dir, i, diff, firstdir = 0, lastdir, max = MAX_SPACES, mflags, blocked;
530 root 1.25 maptile *m, *lastmap;
531 root 1.18
532     get_rangevector (mon, pl, &rv, 0);
533    
534     if (rv.distance < mindiff)
535     return 0;
536    
537     x = mon->x;
538     y = mon->y;
539     m = mon->map;
540     dir = rv.direction;
541     lastdir = firstdir = rv.direction; /* perhaps we stand next to pl, init firstdir too */
542 root 1.100 diff = ::max (abs (rv.distance_x), abs (rv.distance_y));
543    
544 root 1.18 /* If we can't solve it within the search distance, return now. */
545     if (diff > max)
546     return 0;
547 root 1.100
548 root 1.18 while (diff > 1 && max > 0)
549     {
550     lastx = x;
551     lasty = y;
552     lastmap = m;
553     x = lastx + freearr_x[dir];
554     y = lasty + freearr_y[dir];
555    
556     mflags = get_map_flags (m, &m, x, y, &x, &y);
557     blocked = (mflags & P_OUT_OF_MAP) ? MOVE_ALL : GET_MAP_MOVE_BLOCK (m, x, y);
558    
559     /* Space is blocked - try changing direction a little */
560     if ((mflags & P_OUT_OF_MAP) || ((OB_TYPE_MOVE_BLOCK (mon, blocked) || (mflags & P_BLOCKSVIEW))
561     && (m == mon->map && blocked_link (mon, m, x, y))))
562     {
563     /* recalculate direction from last good location. Possible
564     * we were not traversing ideal location before.
565     */
566     get_rangevector_from_mapcoord (lastmap, lastx, lasty, pl, &rv, 0);
567     if (rv.direction != dir)
568     {
569     /* OK - says direction should be different - lets reset the
570     * the values so it will try again.
571     */
572     x = lastx;
573     y = lasty;
574     m = lastmap;
575     dir = firstdir = rv.direction;
576     }
577     else
578     {
579     /* direct path is blocked - try taking a side step to
580     * either the left or right.
581     * Note increase the values in the loop below to be
582     * more than -1/1 respectively will mean the monster takes
583     * bigger detour. Have to be careful about these values getting
584     * too big (3 or maybe 4 or higher) as the monster may just try
585     * stepping back and forth
586     */
587     for (i = -DETOUR_AMOUNT; i <= DETOUR_AMOUNT; i++)
588     {
589     if (i == 0)
590     continue; /* already did this, so skip it */
591     /* Use lastdir here - otherwise,
592     * since the direction that the creature should move in
593     * may change, you could get infinite loops.
594     * ie, player is northwest, but monster can only
595     * move west, so it does that. It goes some distance,
596     * gets blocked, finds that it should move north,
597     * can't do that, but now finds it can move east, and
598     * gets back to its original point. lastdir contains
599     * the last direction the creature has successfully
600     * moved.
601     */
602    
603     x = lastx + freearr_x[absdir (lastdir + i)];
604     y = lasty + freearr_y[absdir (lastdir + i)];
605     m = lastmap;
606     mflags = get_map_flags (m, &m, x, y, &x, &y);
607     if (mflags & P_OUT_OF_MAP)
608     continue;
609     blocked = GET_MAP_MOVE_BLOCK (m, x, y);
610     if (OB_TYPE_MOVE_BLOCK (mon, blocked))
611     continue;
612     if (mflags & P_BLOCKSVIEW)
613     continue;
614    
615     if (m == mon->map && blocked_link (mon, m, x, y))
616     break;
617     }
618     /* go through entire loop without finding a valid
619     * sidestep to take - thus, no valid path.
620     */
621     if (i == (DETOUR_AMOUNT + 1))
622     return 0;
623     diff--;
624     lastdir = dir;
625     max--;
626     if (!firstdir)
627     firstdir = dir + i;
628     } /* else check alternate directions */
629     } /* if blocked */
630     else
631     {
632     /* we moved towards creature, so diff is less */
633     diff--;
634     max--;
635     lastdir = dir;
636     if (!firstdir)
637     firstdir = dir;
638     }
639 root 1.100
640 root 1.18 if (diff <= 1)
641     {
642     /* Recalculate diff (distance) because we may not have actually
643     * headed toward player for entire distance.
644     */
645     get_rangevector_from_mapcoord (m, x, y, pl, &rv, 0);
646 root 1.100 diff = ::max (abs (rv.distance_x), abs (rv.distance_y));
647 root 1.18 }
648 root 1.100
649 root 1.18 if (diff > max)
650     return 0;
651     }
652 root 1.100
653 root 1.18 /* If we reached the max, didn't find a direction in time */
654     if (!max)
655     return 0;
656    
657     return firstdir;
658     }
659    
660     void
661     give_initial_items (object *pl, treasurelist * items)
662     {
663     object *op, *next = NULL;
664    
665     if (pl->randomitems != NULL)
666     create_treasure (items, pl, GT_STARTEQUIP | GT_ONLY_GOOD, 1, 0);
667    
668     for (op = pl->inv; op; op = next)
669     {
670     next = op->below;
671    
672     /* Forces get applied per default, unless they have the
673     * flag "neutral" set. Sorry but I can't think of a better way
674     */
675     if (op->type == FORCE && !QUERY_FLAG (op, FLAG_NEUTRAL))
676     SET_FLAG (op, FLAG_APPLIED);
677    
678     /* we never give weapons/armour if these cannot be used
679     * by this player due to race restrictions
680     */
681     if (pl->type == PLAYER)
682     {
683     if ((!QUERY_FLAG (pl, FLAG_USE_ARMOUR) &&
684     (op->type == ARMOUR || op->type == BOOTS ||
685     op->type == CLOAK || op->type == HELMET ||
686     op->type == SHIELD || op->type == GLOVES ||
687     op->type == BRACERS || op->type == GIRDLE)) || (!QUERY_FLAG (pl, FLAG_USE_WEAPON) && op->type == WEAPON))
688     {
689 root 1.33 op->destroy ();
690 root 1.18 continue;
691     }
692 root 1.11 }
693    
694 root 1.18 /* This really needs to be better - we should really give
695     * a substitute spellbook. The problem is that we don't really
696     * have a good idea what to replace it with (need something like
697     * a first level treasurelist for each skill.)
698     * remove duplicate skills also
699     */
700     if (op->type == SPELLBOOK || op->type == SKILL)
701     {
702     object *tmp;
703 elmex 1.1
704 root 1.18 for (tmp = op->below; tmp; tmp = tmp->below)
705     if (tmp->type == op->type && tmp->name == op->name)
706     break;
707 root 1.11
708 root 1.18 if (tmp)
709     {
710 root 1.33 op->destroy ();
711 root 1.18 LOG (llevError, "give_initial_items: Removing duplicate object %s\n", &tmp->name);
712     continue;
713 root 1.11 }
714 root 1.33
715 root 1.18 if (op->nrof > 1)
716     op->nrof = 1;
717 root 1.11 }
718 elmex 1.1
719 root 1.18 if (op->type == SPELLBOOK && op->inv)
720     {
721     CLEAR_FLAG (op->inv, FLAG_STARTEQUIP);
722 root 1.11 }
723    
724 root 1.18 /* Give starting characters identified, uncursed, and undamned
725     * items. Just don't identify gold or silver, or it won't be
726     * merged properly.
727     */
728     if (need_identify (op))
729     {
730     SET_FLAG (op, FLAG_IDENTIFIED);
731     CLEAR_FLAG (op, FLAG_CURSED);
732     CLEAR_FLAG (op, FLAG_DAMNED);
733     }
734     if (op->type == SPELL)
735     {
736 root 1.33 op->destroy ();
737 root 1.18 continue;
738     }
739     else if (op->type == SKILL)
740     {
741     SET_FLAG (op, FLAG_CAN_USE_SKILL);
742     op->stats.exp = 0;
743     op->level = 1;
744 root 1.11 }
745 root 1.18 /* lock all 'normal items by default */
746     else
747     SET_FLAG (op, FLAG_INV_LOCKED);
748     } /* for loop of objects in player inv */
749    
750     /* Need to set up the skill pointers */
751     link_player_skills (pl);
752     }
753    
754     void
755     get_party_password (object *op, partylist *party)
756     {
757     if (party == NULL)
758     {
759     LOG (llevError, "get_party_password(): tried to make player %s join a NULL party", &op->name);
760     return;
761 elmex 1.1 }
762 root 1.54
763 root 1.18 op->contr->write_buf[0] = '\0';
764 root 1.52 op->contr->ns->state = ST_GET_PARTY_PASSWORD;
765 root 1.18 op->contr->party_to_join = party;
766 root 1.52 send_query (op->contr->ns, CS_QUERY_HIDEINPUT, "What is the password?\n:");
767 elmex 1.1 }
768    
769     /* This rolls four 1-6 rolls and sums the best 3 of the 4. */
770 root 1.54 static int
771 root 1.18 roll_stat (void)
772     {
773     int a[4], i, j, k;
774    
775     for (i = 0; i < 4; i++)
776 root 1.99 a[i] = (int) rndm (6) + 1;
777 root 1.18
778     for (i = 0, j = 0, k = 7; i < 4; i++)
779     if (a[i] < k)
780     k = a[i], j = i;
781    
782     for (i = 0, k = 0; i < 4; i++)
783 root 1.54 if (i != j)
784     k += a[i];
785    
786 root 1.18 return k;
787     }
788    
789     void
790 root 1.54 object::roll_stats ()
791 root 1.18 {
792 root 1.128 int statsort [NUM_STATS];
793 root 1.18
794 root 1.54 for (;;)
795 root 1.18 {
796 root 1.54 int sum = 0;
797 root 1.128 for (int i = NUM_STATS; i--; )
798 root 1.54 sum += statsort [i] = roll_stat ();
799    
800     if (sum >= 82 && sum <= 116)
801     break;
802 root 1.18 }
803    
804 root 1.54 // Sort the stats so that rerolling is easier...
805 root 1.128 std::sort (statsort, statsort + NUM_STATS, std::greater<int>());
806 root 1.18
807 root 1.128 for (int i = 0; i < NUM_STATS; ++i)
808     stats.stat (i) = statsort [i];
809 root 1.18
810 root 1.54 stats.exp = 0;
811     stats.ac = 0;
812 root 1.18
813 root 1.54 stats.hp = stats.maxhp;
814     stats.sp = stats.maxsp;
815     stats.grace = stats.maxgrace;
816 root 1.18
817 root 1.54 if (contr)
818     {
819     contr->levhp[1] = 9;
820     contr->levsp[1] = 6;
821     contr->levgrace[1] = 3;
822 root 1.18
823 root 1.54 contr->orig_stats = stats;
824     }
825 root 1.18 }
826    
827     void
828 root 1.54 object::swap_stats (int a, int b)
829 root 1.18 {
830 root 1.127 swap (contr->orig_stats.stat (a), contr->orig_stats.stat (b));
831    
832     for (int i = 0; i < NUM_STATS; ++i)
833     stats.stat (i) = contr->orig_stats.stat (i);
834 elmex 1.1
835 root 1.54 //TODO: the following code looks so borked and should, at the very least,
836     // be merged with the similar code in roll_stats
837     stats.ac = 0;
838 elmex 1.1
839 root 1.54 level = 1;
840     stats.exp = 0;
841     stats.ac = 0;
842 elmex 1.1
843 root 1.54 stats.hp = stats.maxhp;
844     stats.sp = stats.maxsp;
845     stats.grace = stats.maxgrace;
846 elmex 1.1
847 root 1.54 if (contr)
848 root 1.18 {
849 root 1.54 contr->levhp[1] = 9;
850     contr->levsp[1] = 6;
851     contr->levgrace[1] = 3;
852 root 1.18
853 root 1.54 contr->orig_stats = stats;
854 elmex 1.1 }
855     }
856    
857 root 1.73 static void
858     start_info (object *op)
859     {
860     char buf[MAX_BUF];
861    
862     sprintf (buf, "Welcome to Crossfire v%s!", VERSION);
863     new_draw_info (NDI_UNIQUE, 0, op, buf);
864     //new_draw_info (NDI_UNIQUE, 0, op, "Press `?' for help");
865     //new_draw_info (NDI_UNIQUE, 0, op, " ");
866     }
867    
868 elmex 1.1 /* This function takes the key that is passed, and does the
869     * appropriate action with it (change race, or other things).
870     * The function name is for historical reasons - now we have
871     * separate race and class; this actually changes the RACE,
872     * not the class.
873     */
874 root 1.112 void
875     player::chargen_race_done ()
876 elmex 1.1 {
877 root 1.112 /* this must before then initial items are given */
878     esrv_new_player (ob->contr, ob->weight + ob->carrying);
879 elmex 1.1
880 root 1.112 treasurelist *tl = treasurelist::find ("starting_wealth");
881     if (tl)
882     create_treasure (tl, ob, 0, 0, 0);
883 elmex 1.1
884 root 1.112 INVOKE_PLAYER (BIRTH, ob->contr);
885     INVOKE_PLAYER (LOGIN, ob->contr);
886 elmex 1.36
887 root 1.112 ob->contr->ns->state = ST_PLAYING;
888 elmex 1.1
889 root 1.112 if (ob->msg)
890     ob->msg = 0;
891 elmex 1.1
892 root 1.112 /* We create this now because some of the unique maps will need it
893     * to save here.
894     */
895     {
896     char buf[MAX_BUF];
897     sprintf (buf, "%s/%s/%s", settings.localdir, settings.playerdir, &ob->name);
898     make_path_to_file (buf);
899     }
900    
901     start_info (ob);
902     CLEAR_FLAG (ob, FLAG_WIZ);
903     give_initial_items (ob, ob->randomitems);
904     link_player_skills (ob);
905     esrv_send_inventory (ob, ob);
906     ob->update_stats ();
907 root 1.11
908 root 1.112 /* This moves the player to a different start map, if there
909     * is one for this race
910     */
911     if (*first_map_ext_path)
912     {
913     object *tmp;
914     char mapname[MAX_BUF];
915 elmex 1.1
916 root 1.148 snprintf (mapname, MAX_BUF - 1, "%s/%s", &first_map_ext_path, &ob->arch->archname);
917 root 1.112 tmp = object::create ();
918     EXIT_PATH (tmp) = mapname;
919     EXIT_X (tmp) = ob->x;
920     EXIT_Y (tmp) = ob->y;
921     ob->enter_exit (tmp); /* we don't really care if it succeeded;
922     * if the map isn't there, then stay on the
923     * default initial map */
924     tmp->destroy ();
925 elmex 1.1 }
926 root 1.112 else
927     LOG (llevDebug, "first_map_ext_path not set\n");
928     }
929 elmex 1.1
930 root 1.112 void
931     player::chargen_race_next ()
932     {
933 root 1.18 /* Following actually changes the race - this is the default command
934     * if we don't match with one of the options above.
935     */
936    
937 root 1.112 do
938 root 1.18 {
939 root 1.112 shstr name = ob->name;
940     int x = ob->x, y = ob->y;
941 root 1.21
942 root 1.112 ob->remove_statbonus ();
943     ob->remove ();
944     ob->arch = get_player_archetype (ob->arch);
945 root 1.149 ob->arch->copy_to (ob);
946 root 1.112 ob->instantiate ();
947     ob->stats = ob->contr->orig_stats;
948     ob->name = ob->name_pl = name;
949     ob->x = x;
950     ob->y = y;
951     SET_ANIMATION (ob, 2); /* So player faces south */
952     insert_ob_in_map (ob, ob->map, ob, 0);
953 root 1.149 assign (ob->contr->title, ob->arch->object::name);
954 root 1.112 ob->add_statbonus ();
955     }
956     while (!allowed_class (ob));
957    
958     update_object (ob, UP_OBJ_FACE);
959     esrv_update_item (UPD_FACE, ob, ob);
960     ob->update_stats ();
961     ob->stats.hp = ob->stats.maxhp;
962     ob->stats.sp = ob->stats.maxsp;
963     ob->stats.grace = 0;
964 elmex 1.1 }
965    
966 root 1.18 void
967     flee_player (object *op)
968     {
969     int dir, diff;
970     rv_vector rv;
971    
972     if (op->stats.hp < 0)
973     {
974     LOG (llevDebug, "Fleeing player is dead.\n");
975     CLEAR_FLAG (op, FLAG_SCARED);
976     return;
977 elmex 1.1 }
978    
979 root 1.18 if (op->enemy == NULL)
980     {
981     LOG (llevDebug, "Fleeing player had no enemy.\n");
982     CLEAR_FLAG (op, FLAG_SCARED);
983     return;
984 elmex 1.1 }
985    
986 root 1.18 /* Seen some crashes here. Since we don't store an
987     * op->enemy_count, it is possible that something destroys the
988     * actual enemy, and the object is recycled.
989     */
990     if (op->enemy->map == NULL)
991     {
992     CLEAR_FLAG (op, FLAG_SCARED);
993     op->enemy = NULL;
994     return;
995 elmex 1.1 }
996    
997 root 1.18 if (!(random_roll (0, 4, op, PREFER_LOW)) && did_make_save (op, op->level, 0))
998     {
999     op->enemy = NULL;
1000     CLEAR_FLAG (op, FLAG_SCARED);
1001     return;
1002 elmex 1.1 }
1003 root 1.49
1004 root 1.18 get_rangevector (op, op->enemy, &rv, 0);
1005    
1006     dir = absdir (4 + rv.direction);
1007     for (diff = 0; diff < 3; diff++)
1008     {
1009     int m = 1 - (RANDOM () & 2);
1010 elmex 1.1
1011 root 1.18 if (move_ob (op, absdir (dir + diff * m), op) || (diff == 0 && move_ob (op, absdir (dir - diff * m), op)))
1012 root 1.49 return;
1013 elmex 1.1 }
1014 root 1.49
1015 root 1.18 /* Cornered, get rid of scared */
1016     CLEAR_FLAG (op, FLAG_SCARED);
1017     op->enemy = NULL;
1018 elmex 1.1 }
1019    
1020     /* check_pick sees if there is stuff to be picked up/picks up stuff.
1021 root 1.122 * It returns 1 if the player should keep on moving, 0 if he should
1022 elmex 1.1 * stop.
1023     */
1024 root 1.18 int
1025     check_pick (object *op)
1026     {
1027 elmex 1.1 object *tmp, *next;
1028     int stop = 0;
1029 pippijn 1.106 int wvratio;
1030     char putstring[128];
1031 elmex 1.1
1032     /* if you're flying, you cna't pick up anything */
1033     if (op->move_type & MOVE_FLYING)
1034     return 1;
1035    
1036     next = op->below;
1037    
1038     /* loop while there are items on the floor that are not marked as
1039     * destroyed */
1040 root 1.24 while (next && !next->destroyed ())
1041 root 1.18 {
1042     tmp = next;
1043     next = tmp->below;
1044 elmex 1.1
1045 root 1.24 if (op->destroyed ())
1046 elmex 1.1 return 0;
1047    
1048 root 1.18 if (!can_pick (op, tmp))
1049     continue;
1050 elmex 1.1
1051 root 1.18 if (op->contr->search_str[0] != '\0' && settings.search_items == TRUE)
1052     {
1053     if (item_matched_string (op, tmp, op->contr->search_str))
1054     pick_up (op, tmp);
1055     continue;
1056 root 1.11 }
1057    
1058 root 1.18 /* high not bit set? We're using the old autopickup model */
1059     if (!(op->contr->mode & PU_NEWMODE))
1060 root 1.11 {
1061 root 1.18 switch (op->contr->mode)
1062 root 1.11 {
1063 root 1.20 case 0:
1064     return 1; /* don't pick up */
1065     case 1:
1066     pick_up (op, tmp);
1067     return 1;
1068     case 2:
1069     pick_up (op, tmp);
1070     return 0;
1071     case 3:
1072     return 0; /* stop before pickup */
1073     case 4:
1074     pick_up (op, tmp);
1075     break;
1076     case 5:
1077     pick_up (op, tmp);
1078     stop = 1;
1079     break;
1080     case 6:
1081     if (QUERY_FLAG (tmp, FLAG_KNOWN_MAGICAL) && !QUERY_FLAG (tmp, FLAG_KNOWN_CURSED))
1082 root 1.18 pick_up (op, tmp);
1083 root 1.20 break;
1084    
1085     case 7:
1086     if (tmp->type == MONEY || tmp->type == GEM)
1087 root 1.18 pick_up (op, tmp);
1088 root 1.20 break;
1089    
1090     default:
1091     /* use value density */
1092     if (!QUERY_FLAG (tmp, FLAG_UNPAID)
1093     && (query_cost (tmp, op, F_TRUE) * 100 / (tmp->weight * MAX (tmp->nrof, 1))) >= op->contr->mode)
1094 root 1.18 pick_up (op, tmp);
1095 root 1.11 }
1096     }
1097 root 1.18 else
1098     { /* old model */
1099     /* NEW pickup handling */
1100     if (op->contr->mode & PU_DEBUG)
1101     {
1102     /* some debugging code to figure out item information */
1103     if (tmp->name != NULL)
1104     sprintf (putstring, "item name: %s item type: %d weight/value: %d",
1105     &tmp->name, tmp->type, (int) (query_cost (tmp, op, F_TRUE) * 100 / (tmp->weight * MAX (tmp->nrof, 1))));
1106     else
1107     sprintf (putstring, "item name: %s item type: %d weight/value: %d",
1108 root 1.148 &tmp->arch->archname, tmp->type, (int) (query_cost (tmp, op, F_TRUE) * 100 / (tmp->weight * MAX (tmp->nrof, 1))));
1109 root 1.18
1110     new_draw_info (NDI_UNIQUE, 0, op, putstring);
1111 root 1.58 }
1112 elmex 1.1
1113 root 1.18 /* philosophy:
1114     * It's easy to grab an item type from a pile, as long as it's
1115     * generic. This takes no game-time. For more detailed pickups
1116 root 1.58 * and selections, select-items should be used. This is a
1117 root 1.18 * grab-as-you-run type mode that's really useful for arrows for
1118     * example.
1119     * The drawback: right now it has no frontend, so you need to
1120     * stick the bits you want into a calculator in hex mode and then
1121     * convert to decimal and then 'pickup <#>
1122     */
1123    
1124     /* the first two modes are exclusive: if NOTHING we return, if
1125     * STOP then we stop. All the rest are applied sequentially,
1126     * meaning if any test passes, the item gets picked up. */
1127    
1128     /* if mode is set to pick nothing up, return */
1129    
1130     if (op->contr->mode & PU_NOTHING)
1131     return 1;
1132    
1133     /* if mode is set to stop when encountering objects, return */
1134     /* take STOP before INHIBIT since it doesn't actually pick
1135     * anything up */
1136    
1137     if (op->contr->mode & PU_STOP)
1138     return 0;
1139    
1140     /* useful for going into stores and not losing your settings... */
1141     /* and for battles wher you don't want to get loaded down while
1142     * fighting */
1143     if (op->contr->mode & PU_INHIBIT)
1144     return 1;
1145    
1146     /* prevent us from turning into auto-thieves :) */
1147     if (QUERY_FLAG (tmp, FLAG_UNPAID))
1148     continue;
1149    
1150     /* ignore known cursed objects */
1151     if (QUERY_FLAG (tmp, FLAG_KNOWN_CURSED) && op->contr->mode & PU_NOT_CURSED)
1152     continue;
1153    
1154     /* all food and drink if desired */
1155     /* question: don't pick up known-poisonous stuff? */
1156     if (op->contr->mode & PU_FOOD)
1157     if (tmp->type == FOOD)
1158     {
1159     pick_up (op, tmp);
1160     continue;
1161     }
1162 root 1.29
1163 root 1.18 if (op->contr->mode & PU_DRINK)
1164     if (tmp->type == DRINK || (tmp->type == POISON && !QUERY_FLAG (tmp, FLAG_KNOWN_CURSED)))
1165     {
1166     pick_up (op, tmp);
1167     continue;
1168     }
1169    
1170     if (op->contr->mode & PU_POTION)
1171     if (tmp->type == POTION)
1172     {
1173     pick_up (op, tmp);
1174     continue;
1175     }
1176    
1177     /* spellbooks, skillscrolls and normal books/scrolls */
1178     if (op->contr->mode & PU_SPELLBOOK)
1179     if (tmp->type == SPELLBOOK)
1180     {
1181     pick_up (op, tmp);
1182     continue;
1183     }
1184 root 1.29
1185 root 1.18 if (op->contr->mode & PU_SKILLSCROLL)
1186     if (tmp->type == SKILLSCROLL)
1187     {
1188     pick_up (op, tmp);
1189     continue;
1190     }
1191 root 1.29
1192 root 1.18 if (op->contr->mode & PU_READABLES)
1193     if (tmp->type == BOOK || tmp->type == SCROLL)
1194     {
1195     pick_up (op, tmp);
1196     continue;
1197     }
1198    
1199     /* wands/staves/rods/horns */
1200     if (op->contr->mode & PU_MAGIC_DEVICE)
1201     if (tmp->type == WAND || tmp->type == ROD || tmp->type == HORN)
1202     {
1203     pick_up (op, tmp);
1204     continue;
1205     }
1206    
1207     /* pick up all magical items */
1208     if (op->contr->mode & PU_MAGICAL)
1209     if (QUERY_FLAG (tmp, FLAG_KNOWN_MAGICAL) && !QUERY_FLAG (tmp, FLAG_KNOWN_CURSED))
1210     {
1211     pick_up (op, tmp);
1212     continue;
1213     }
1214    
1215     if (op->contr->mode & PU_VALUABLES)
1216     {
1217     if (tmp->type == MONEY || tmp->type == GEM)
1218     {
1219     pick_up (op, tmp);
1220     continue;
1221     }
1222     }
1223    
1224     /* rings & amulets - talismans seems to be typed AMULET */
1225     if (op->contr->mode & PU_JEWELS)
1226     if (tmp->type == RING || tmp->type == AMULET)
1227     {
1228     pick_up (op, tmp);
1229 root 1.29 continue;
1230     }
1231    
1232     /* we don't forget dragon food */
1233     if (op->contr->mode & PU_FLESH)
1234     if (tmp->type == FLESH)
1235     {
1236     pick_up (op, tmp);
1237 root 1.18 continue;
1238     }
1239    
1240     /* bows and arrows. Bows are good for selling! */
1241     if (op->contr->mode & PU_BOW)
1242     if (tmp->type == BOW)
1243     {
1244     pick_up (op, tmp);
1245     continue;
1246     }
1247 root 1.29
1248 root 1.18 if (op->contr->mode & PU_ARROW)
1249     if (tmp->type == ARROW)
1250     {
1251     pick_up (op, tmp);
1252     continue;
1253     }
1254    
1255     /* all kinds of armor etc. */
1256     if (op->contr->mode & PU_ARMOUR)
1257     if (tmp->type == ARMOUR)
1258     {
1259     pick_up (op, tmp);
1260     continue;
1261     }
1262 root 1.29
1263 root 1.18 if (op->contr->mode & PU_HELMET)
1264     if (tmp->type == HELMET)
1265     {
1266     pick_up (op, tmp);
1267     continue;
1268     }
1269 root 1.29
1270 root 1.18 if (op->contr->mode & PU_SHIELD)
1271     if (tmp->type == SHIELD)
1272     {
1273     pick_up (op, tmp);
1274     continue;
1275     }
1276 root 1.29
1277 root 1.18 if (op->contr->mode & PU_BOOTS)
1278     if (tmp->type == BOOTS)
1279     {
1280     pick_up (op, tmp);
1281     continue;
1282     }
1283 root 1.29
1284 root 1.18 if (op->contr->mode & PU_GLOVES)
1285     if (tmp->type == GLOVES)
1286     {
1287     pick_up (op, tmp);
1288     continue;
1289     }
1290 root 1.29
1291 root 1.18 if (op->contr->mode & PU_CLOAK)
1292     if (tmp->type == CLOAK)
1293     {
1294     pick_up (op, tmp);
1295     continue;
1296     }
1297 elmex 1.1
1298 root 1.18 /* hoping to catch throwing daggers here */
1299     if (op->contr->mode & PU_MISSILEWEAPON)
1300     if (tmp->type == WEAPON && QUERY_FLAG (tmp, FLAG_IS_THROWN))
1301     {
1302     pick_up (op, tmp);
1303     continue;
1304     }
1305 elmex 1.1
1306 root 1.18 /* careful: chairs and tables are weapons! */
1307     if (op->contr->mode & PU_ALLWEAPON)
1308     {
1309     if (tmp->type == WEAPON && tmp->name != NULL)
1310     {
1311 root 1.148 if (strstr (tmp->name, "table") == NULL && strstr (tmp->arch->archname, "table") == NULL &&
1312     strstr (tmp->name, "chair") && strstr (tmp->arch->archname, "chair") == NULL)
1313 root 1.18 {
1314     pick_up (op, tmp);
1315     continue;
1316     }
1317     }
1318 root 1.29
1319 root 1.18 if (tmp->type == WEAPON && tmp->name == NULL)
1320     {
1321 root 1.148 if (strstr (tmp->arch->archname, "table") == NULL && strstr (tmp->arch->archname, "chair") == NULL)
1322 root 1.18 {
1323     pick_up (op, tmp);
1324     continue;
1325     }
1326     }
1327     }
1328 elmex 1.1
1329 root 1.18 /* misc stuff that's useful */
1330     if (op->contr->mode & PU_KEY)
1331     if (tmp->type == KEY || tmp->type == SPECIAL_KEY)
1332     {
1333     pick_up (op, tmp);
1334     continue;
1335     }
1336 elmex 1.1
1337 root 1.18 /* any of the last 4 bits set means we use the ratio for value
1338     * pickups */
1339     if (op->contr->mode & PU_RATIO)
1340     {
1341     /* use value density to decide what else to grab */
1342     /* >=7 was >= op->contr->mode */
1343     /* >=7 is the old standard setting. Now we take the last 4 bits
1344     * and multiply them by 5, giving 0..15*5== 5..75 */
1345     wvratio = (op->contr->mode & PU_RATIO) * 5;
1346     if ((query_cost (tmp, op, F_TRUE) * 100 / (tmp->weight * MAX (tmp->nrof, 1))) >= (unsigned int) wvratio)
1347     {
1348     pick_up (op, tmp);
1349 elmex 1.1 #if 0
1350 root 1.18 fprintf (stderr, "HIGH WEIGHT/VALUE [");
1351     if (tmp->name != NULL)
1352     {
1353     fprintf (stderr, "%s", tmp->name);
1354     }
1355     else
1356 root 1.148 fprintf (stderr, "%s", tmp->arch->archname);
1357 root 1.18 fprintf (stderr, ",%d] = ", tmp->type);
1358     fprintf (stderr, "%d\n", (int) (query_cost (tmp, op, F_TRUE) * 100 / (tmp->weight * MAX (tmp->nrof, 1))));
1359 elmex 1.1 #endif
1360 root 1.18 continue;
1361     }
1362     }
1363     } /* the new pickup model */
1364     }
1365 root 1.29
1366 root 1.18 return !stop;
1367 elmex 1.1 }
1368    
1369     /*
1370     * Find an arrow in the inventory and after that
1371     * in the right type container (quiver). Pointer to the
1372     * found object is returned.
1373     */
1374 root 1.18 object *
1375     find_arrow (object *op, const char *type)
1376 elmex 1.1 {
1377 root 1.103 object *tmp = 0;
1378 elmex 1.1
1379 root 1.18 for (op = op->inv; op; op = op->below)
1380     if (!tmp && op->type == CONTAINER && op->race == type && QUERY_FLAG (op, FLAG_APPLIED))
1381     tmp = find_arrow (op, type);
1382     else if (op->type == ARROW && op->race == type)
1383     return op;
1384 root 1.103
1385 root 1.18 return tmp;
1386 elmex 1.1 }
1387    
1388     /*
1389     * Similar to find_arrow, but looks for (roughly) the best arrow to use
1390     * against the target. A full test is not performed, simply a basic test
1391     * of resistances. The archer is making a quick guess at what he sees down
1392     * the hall. Failing that it does it's best to pick the highest plus arrow.
1393     */
1394 root 1.18 object *
1395     find_better_arrow (object *op, object *target, const char *type, int *better)
1396 elmex 1.1 {
1397 root 1.18 object *tmp = NULL, *arrow, *ntmp;
1398     int attacknum, attacktype, betterby = 0, i;
1399 elmex 1.1
1400 root 1.18 if (!type)
1401     return NULL;
1402 elmex 1.1
1403 root 1.18 for (arrow = op->inv; arrow; arrow = arrow->below)
1404     {
1405     if (arrow->type == CONTAINER && arrow->race == type && QUERY_FLAG (arrow, FLAG_APPLIED))
1406     {
1407     i = 0;
1408     ntmp = find_better_arrow (arrow, target, type, &i);
1409     if (i > betterby)
1410     {
1411     tmp = ntmp;
1412     betterby = i;
1413     }
1414     }
1415     else if (arrow->type == ARROW && arrow->race == type)
1416     {
1417     /* allways prefer assasination/slaying */
1418     if (target->race != NULL && arrow->slaying != NULL && strstr (arrow->slaying, target->race))
1419     {
1420     if (arrow->attacktype & AT_DEATH)
1421     {
1422     *better = 100;
1423     return arrow;
1424     }
1425     else
1426     {
1427     tmp = arrow;
1428     betterby = (arrow->magic + arrow->stats.dam) * 2;
1429     }
1430     }
1431     else
1432     {
1433     for (attacknum = 0; attacknum < NROFATTACKS; attacknum++)
1434     {
1435     attacktype = 1 << attacknum;
1436 root 1.149 if ((arrow->attacktype & attacktype) && (target->arch->resist[attacknum]) < 0)
1437     if (((arrow->magic + arrow->stats.dam) * (100 - target->arch->resist[attacknum]) / 100) > betterby)
1438 root 1.18 {
1439     tmp = arrow;
1440 root 1.149 betterby = (arrow->magic + arrow->stats.dam) * (100 - target->arch->resist[attacknum]) / 100;
1441 root 1.18 }
1442 root 1.11 }
1443 root 1.18 if ((2 + arrow->magic + arrow->stats.dam) > betterby)
1444     {
1445     tmp = arrow;
1446     betterby = 2 + arrow->magic + arrow->stats.dam;
1447 root 1.11 }
1448 root 1.18 if (arrow->title && (1 + arrow->magic + arrow->stats.dam) > betterby)
1449     {
1450     tmp = arrow;
1451     betterby = 1 + arrow->magic + arrow->stats.dam;
1452 root 1.11 }
1453     }
1454     }
1455 elmex 1.1 }
1456 root 1.18 if (tmp == NULL && arrow == NULL)
1457     return find_arrow (op, type);
1458 elmex 1.1
1459 root 1.18 *better = betterby;
1460     return tmp;
1461 elmex 1.1 }
1462    
1463     /* looks in a given direction, finds the first valid target, and calls
1464     * find_better_arrow to find a decent arrow to use.
1465     * op = the shooter
1466     * type = bow->race
1467     * dir = fire direction
1468     */
1469 root 1.18 object *
1470     pick_arrow_target (object *op, const char *type, int dir)
1471 elmex 1.1 {
1472 root 1.18 object *tmp = NULL;
1473 root 1.25 maptile *m;
1474 root 1.18 int i, mflags, found, number;
1475     sint16 x, y;
1476    
1477     if (op->map == NULL)
1478     return find_arrow (op, type);
1479    
1480     /* do a dex check */
1481     number = (die_roll (2, 40, op, PREFER_LOW) - 2) / 2;
1482     if (number > (op->stats.Dex + (op->chosen_skill ? op->chosen_skill->level : op->level)))
1483     return find_arrow (op, type);
1484    
1485     m = op->map;
1486     x = op->x;
1487     y = op->y;
1488    
1489     /* find the first target */
1490     for (i = 0, found = 0; i < 20; i++)
1491     {
1492     x += freearr_x[dir];
1493     y += freearr_y[dir];
1494     mflags = get_map_flags (m, &m, x, y, &x, &y);
1495     if (mflags & P_OUT_OF_MAP || mflags & P_BLOCKSVIEW)
1496     {
1497     tmp = NULL;
1498     break;
1499     }
1500     else if (GET_MAP_MOVE_BLOCK (m, x, y) == MOVE_FLY_LOW)
1501     {
1502     /* This block presumes arrows and the like are MOVE_FLY_SLOW -
1503     * perhaps a bad assumption.
1504     */
1505     tmp = NULL;
1506     break;
1507 root 1.11 }
1508 root 1.18 if (mflags & P_IS_ALIVE)
1509     {
1510     for (tmp = GET_MAP_OB (m, x, y); tmp; tmp = tmp->above)
1511     if (QUERY_FLAG (tmp, FLAG_ALIVE))
1512     {
1513     found++;
1514 root 1.11 break;
1515 root 1.18 }
1516     if (found)
1517     break;
1518 root 1.11 }
1519 elmex 1.1 }
1520 root 1.18 if (tmp == NULL)
1521     return find_arrow (op, type);
1522 elmex 1.1
1523 root 1.18 if (tmp->head)
1524     tmp = tmp->head;
1525 elmex 1.1
1526 root 1.18 return find_better_arrow (op, tmp, type, &i);
1527 elmex 1.1 }
1528    
1529     /*
1530     * Creature fires a bow - op can be monster or player. Returns
1531     * 1 if bow was actually fired, 0 otherwise.
1532     * op is the object firing the bow.
1533     * part is for multipart creatures - the part firing the bow.
1534     * dir is the direction of fire.
1535     * wc_mod is any special modifier to give (used in special player fire modes)
1536     * sx, sy are coordinates to fire arrow from - also used in some of the special
1537     * player fire modes.
1538     */
1539 root 1.18 int
1540     fire_bow (object *op, object *part, object *arrow, int dir, int wc_mod, sint16 sx, sint16 sy)
1541 elmex 1.1 {
1542 root 1.18 object *left, *bow;
1543 root 1.132 int mflags;
1544 root 1.25 maptile *m;
1545 elmex 1.1
1546 root 1.18 if (!dir)
1547     {
1548     new_draw_info (NDI_UNIQUE, 0, op, "You can't shoot yourself!");
1549     return 0;
1550 elmex 1.1 }
1551 root 1.48
1552 root 1.136 if (op->contr)
1553     bow = op->current_weapon;
1554 root 1.18 else
1555     {
1556     for (bow = op->inv; bow; bow = bow->below)
1557     /* Don't check for applied - monsters don't apply bows - in that way, they
1558     * don't need to switch back and forth between bows and weapons.
1559     */
1560     if (bow->type == BOW)
1561     break;
1562 root 1.11
1563 root 1.18 if (!bow)
1564     {
1565     LOG (llevError, "Range: bow without activated bow (%s).\n", &op->name);
1566     return 0;
1567 root 1.11 }
1568 root 1.118
1569     // optimisation: move object to top so we will find it quickly again
1570     if (bow->below)
1571     {
1572     bow->remove ();
1573     op->insert (bow);
1574     }
1575    
1576 elmex 1.1 }
1577 root 1.48
1578 root 1.18 if (!bow->race || !bow->skill)
1579     {
1580     new_draw_info_format (NDI_UNIQUE, 0, op, "Your %s is broken.", &bow->name);
1581     return 0;
1582 elmex 1.1 }
1583    
1584 root 1.18 if (arrow == NULL)
1585     {
1586     if ((arrow = find_arrow (op, bow->race)) == NULL)
1587     {
1588     if (op->type == PLAYER)
1589     new_draw_info_format (NDI_UNIQUE, 0, op, "You have no %s left.", &bow->race);
1590     /* FLAG_READY_BOW will get reset if the monsters picks up some arrows */
1591     else
1592     CLEAR_FLAG (op, FLAG_READY_BOW);
1593 root 1.116
1594 root 1.18 return 0;
1595 root 1.11 }
1596 elmex 1.1 }
1597 root 1.48
1598 root 1.18 mflags = get_map_flags (op->map, &m, sx, sy, &sx, &sy);
1599     if (mflags & P_OUT_OF_MAP)
1600 root 1.48 return 0;
1601    
1602 root 1.18 if (GET_MAP_MOVE_BLOCK (m, sx, sy) == MOVE_FLY_LOW)
1603     {
1604     new_draw_info (NDI_UNIQUE, 0, op, "Something is in the way.");
1605     return 0;
1606     }
1607    
1608     /* this should not happen, but sometimes does */
1609     if (arrow->nrof == 0)
1610     {
1611 root 1.33 arrow->destroy ();
1612 root 1.18 return 0;
1613     }
1614    
1615     left = arrow; /* these are arrows left to the player */
1616     arrow = get_split_ob (arrow, 1);
1617 root 1.48 if (!arrow)
1618 root 1.18 {
1619     new_draw_info_format (NDI_UNIQUE, 0, op, "You have no %s left.", &bow->race);
1620     return 0;
1621 elmex 1.1 }
1622 root 1.48
1623 root 1.34 arrow->set_owner (op);
1624 root 1.18 arrow->skill = bow->skill;
1625     arrow->direction = dir;
1626    
1627 root 1.124 arrow->stats.sp = arrow->stats.wc; /* save original wc, dam, attacktype and slaying */
1628     arrow->stats.hp = arrow->stats.dam;
1629     arrow->stats.grace = arrow->attacktype;
1630    
1631     if (arrow->slaying)
1632     arrow->spellarg = strdup (arrow->slaying);
1633    
1634 root 1.142 #if 0
1635 root 1.131 if (player *pl = op->contr)
1636 root 1.18 {
1637 root 1.142 float speed = pl->weapon_sp;
1638 root 1.132
1639 root 1.142 /* penalize ROF for bestarrow */
1640     if (pl->bowtype == bow_bestarrow)
1641     speed *= .9f;
1642     else
1643     speed *= 1.f + dex_bonus[op->stats.Dex] * .2f;
1644 root 1.131
1645 root 1.142 op->speed_left += speed - op->speed;
1646     }
1647 root 1.132 #endif
1648 elmex 1.1
1649 root 1.18 SET_ANIMATION (arrow, arrow->direction);
1650 root 1.116
1651 root 1.18 /* update the speed */
1652 root 1.142 arrow->speed = ((bow->flag [FLAG_NO_STRENGTH] ? 0 : dam_bonus[op->stats.Str]) + bow->magic + arrow->magic) / 5.f
1653     + bow->stats.dam / 7.f;
1654 root 1.18
1655 root 1.142 arrow->set_speed (max (arrow->speed, 2.f));
1656 root 1.18 arrow->speed_left = 0;
1657    
1658 root 1.129 int wc = op->stats.wc + wc_mod - arrow->magic - arrow->stats.wc;
1659 root 1.116
1660 root 1.18 if (op->type == PLAYER)
1661     {
1662 root 1.116 arrow->level = op->chosen_skill ? op->chosen_skill->level : op->level;
1663 root 1.129 wc -= dex_bonus[op->stats.Dex];
1664 root 1.18
1665 root 1.116 if (!arrow->slaying)
1666     arrow->slaying = op->slaying;
1667 root 1.124
1668     arrow->attacktype |= op->attacktype;
1669 elmex 1.1 }
1670 root 1.18 else
1671     {
1672     arrow->level = op->level;
1673 root 1.116 arrow->stats.wc -= bow->magic;
1674    
1675     if (!arrow->slaying)
1676     arrow->slaying = bow->slaying;
1677 root 1.124
1678     arrow->attacktype |= bow->attacktype;
1679 elmex 1.1 }
1680 root 1.24
1681 root 1.129 wc -= arrow->level;
1682     arrow->stats.dam = clamp (arrow->stats.dam + op->stats.dam + arrow->magic, MIN_DAM, MAX_DAM);
1683 root 1.24
1684 root 1.129 arrow->stats.wc = clamp (wc, MIN_WC, MAX_WC);
1685 root 1.18 arrow->move_type = MOVE_FLY_LOW;
1686     arrow->move_on = MOVE_FLY_LOW | MOVE_WALK;
1687    
1688     play_sound_map (op->map, op->x, op->y, SOUND_FIRE_ARROW);
1689 root 1.70 m->insert (arrow, sx, sy, op);
1690 root 1.18
1691 root 1.24 if (!arrow->destroyed ())
1692 root 1.18 move_arrow (arrow);
1693 elmex 1.1
1694 root 1.18 if (op->type == PLAYER)
1695     {
1696 root 1.24 if (left->destroyed ())
1697     esrv_del_item (op->contr, left->count);
1698 root 1.18 else
1699     esrv_send_item (op, left);
1700 elmex 1.1 }
1701 root 1.24
1702 root 1.18 return 1;
1703 elmex 1.1 }
1704    
1705     /* Special fire code for players - this takes into
1706     * account the special fire modes players can have
1707     * but monsters can't. Putting that code here
1708     * makes the fire_bow code much cleaner.
1709     * this function should only be called if 'op' is a player,
1710     * hence the function name.
1711     */
1712 root 1.18 int
1713     player_fire_bow (object *op, int dir)
1714 elmex 1.1 {
1715 root 1.18 int ret = 0, wcmod = 0;
1716    
1717     if (op->contr->bowtype == bow_bestarrow)
1718     {
1719 root 1.118 ret = fire_bow (op, op, pick_arrow_target (op, op->contr->ranged_ob->race, dir), dir, 0, op->x, op->y);
1720 root 1.18 }
1721     else if (op->contr->bowtype >= bow_n && op->contr->bowtype <= bow_nw)
1722     {
1723     if (!similar_direction (dir, op->contr->bowtype - bow_n + 1))
1724     wcmod = -1;
1725 root 1.74
1726 root 1.18 ret = fire_bow (op, op, NULL, op->contr->bowtype - bow_n + 1, wcmod, op->x, op->y);
1727     }
1728     else if (op->contr->bowtype == bow_threewide)
1729     {
1730     ret = fire_bow (op, op, NULL, dir, 0, op->x, op->y);
1731     ret |= fire_bow (op, op, NULL, dir, -5, op->x + freearr_x[absdir (dir + 2)], op->y + freearr_y[absdir (dir + 2)]);
1732     ret |= fire_bow (op, op, NULL, dir, -5, op->x + freearr_x[absdir (dir - 2)], op->y + freearr_y[absdir (dir - 2)]);
1733     }
1734     else if (op->contr->bowtype == bow_spreadshot)
1735     {
1736     ret |= fire_bow (op, op, NULL, dir, 0, op->x, op->y);
1737     ret |= fire_bow (op, op, NULL, absdir (dir - 1), -5, op->x, op->y);
1738     ret |= fire_bow (op, op, NULL, absdir (dir + 1), -5, op->x, op->y);
1739 elmex 1.1 }
1740 root 1.18 else
1741     {
1742     /* Simple case */
1743     ret = fire_bow (op, op, NULL, dir, 0, op->x, op->y);
1744     }
1745 root 1.121
1746 root 1.18 return ret;
1747 elmex 1.1 }
1748    
1749     /* Fires a misc (wand/rod/horn) object in 'dir'.
1750     * Broken apart from 'fire' to keep it more readable.
1751     */
1752 root 1.18 void
1753     fire_misc_object (object *op, int dir)
1754 elmex 1.1 {
1755 root 1.118 object *item = op->contr->ranged_ob;
1756 elmex 1.1
1757 root 1.118 if (!item)
1758 root 1.18 {
1759     new_draw_info (NDI_UNIQUE, 0, op, "You have range item readied.");
1760     return;
1761 elmex 1.1 }
1762    
1763 root 1.18 if (!item->inv)
1764     {
1765     LOG (llevError, "Object %s lacks a spell\n", &item->name);
1766     return;
1767 elmex 1.1 }
1768 root 1.118
1769 root 1.126 if (!op->change_weapon (item))
1770     return;
1771 root 1.121
1772 root 1.18 if (item->type == WAND)
1773     {
1774     if (item->stats.food <= 0)
1775     {
1776     play_sound_player_only (op->contr, SOUND_WAND_POOF, 0, 0);
1777     new_draw_info_format (NDI_UNIQUE, 0, op, "The %s goes poof.", query_base_name (item, 0));
1778 root 1.121
1779 root 1.18 return;
1780 root 1.11 }
1781 root 1.18 }
1782     else if (item->type == ROD || item->type == HORN)
1783     {
1784     if (item->stats.hp < MAX (item->inv->stats.sp, item->inv->stats.grace))
1785     {
1786     play_sound_player_only (op->contr, SOUND_WAND_POOF, 0, 0);
1787 root 1.121
1788 root 1.18 if (item->type == ROD)
1789     new_draw_info_format (NDI_UNIQUE, 0, op, "The %s whines for a while, but nothing happens.", query_base_name (item, 0));
1790     else
1791     new_draw_info_format (NDI_UNIQUE, 0, op, "The %s needs more time to charge.", query_base_name (item, 0));
1792 root 1.121
1793 root 1.18 return;
1794 root 1.11 }
1795 elmex 1.1 }
1796    
1797 root 1.18 if (cast_spell (op, item, dir, item->inv, NULL))
1798     {
1799     SET_FLAG (op, FLAG_BEEN_APPLIED); /* You now know something about it */
1800     if (item->type == WAND)
1801     {
1802     if (!(--item->stats.food))
1803     {
1804     object *tmp;
1805    
1806     if (item->arch)
1807     {
1808     CLEAR_FLAG (item, FLAG_ANIMATE);
1809 root 1.149 item->face = item->arch->face;
1810 root 1.67 item->set_speed (0);
1811 root 1.11 }
1812 root 1.67
1813 root 1.49 if ((tmp = item->in_player ()))
1814 root 1.18 esrv_update_item (UPD_ANIM, tmp, item);
1815 root 1.11 }
1816     }
1817 root 1.18 else if (item->type == ROD || item->type == HORN)
1818 root 1.67 drain_rod_charge (item);
1819 elmex 1.1 }
1820     }
1821    
1822     /* Received a fire command for the player - go and do it.
1823     */
1824 root 1.142 bool
1825 root 1.18 fire (object *op, int dir)
1826     {
1827     int spellcost = 0;
1828 elmex 1.1
1829 root 1.18 /* check for loss of invisiblity/hide */
1830     if (action_makes_visible (op))
1831     make_visible (op);
1832 elmex 1.1
1833 root 1.118 player *pl = op->contr;
1834 elmex 1.1
1835 root 1.119 if (pl->golem)
1836     {
1837     control_golem (op->contr->golem, dir);
1838 root 1.142 return false;
1839 root 1.119 }
1840    
1841     object *ob = pl->ranged_ob;
1842 elmex 1.1
1843 root 1.119 if (!ob)
1844 root 1.142 return false;
1845 elmex 1.1
1846 root 1.136 if (!op->change_weapon (ob))
1847 root 1.142 return false;
1848    
1849     if (op->speed_left > 0.f)
1850     --op->speed_left;
1851     else
1852     return false;
1853 root 1.136
1854 root 1.119 switch (ob->type)
1855 root 1.118 {
1856 root 1.119 case BOW:
1857 root 1.118 player_fire_bow (op, dir);
1858 root 1.119 break;
1859    
1860     case SPELL:
1861     spellcost = cast_spell (op, op, dir, ob, pl->spellparam[0] ? pl->spellparam : 0);
1862     break;
1863 root 1.113
1864 root 1.119 case BUILDER:
1865 root 1.20 apply_map_builder (op, dir);
1866 root 1.119 break;
1867    
1868     case SKILL:
1869     do_skill (op, op, ob, dir, 0);
1870     break;
1871    
1872     default:
1873     fire_misc_object (op, dir);
1874     break;
1875 elmex 1.1 }
1876 root 1.142
1877     return true;
1878 elmex 1.1 }
1879    
1880     /* find_key
1881     * We try to find a key for the door as passed. If we find a key
1882     * and successfully use it, we return the key, otherwise NULL
1883     * This function merges both normal and locked door, since the logic
1884     * for both is the same - just the specific key is different.
1885     * pl is the player,
1886     * inv is the objects inventory to searched
1887     * door is the door we are trying to match against.
1888     * This function can be called recursively to search containers.
1889     */
1890 root 1.18 object *
1891     find_key (object *pl, object *container, object *door)
1892 elmex 1.1 {
1893 root 1.18 object *tmp, *key;
1894 elmex 1.1
1895 root 1.18 /* Should not happen, but sanity checking is never bad */
1896 root 1.103 if (!container->inv)
1897     return 0;
1898 elmex 1.1
1899 root 1.18 /* First, lets try to find a key in the top level inventory */
1900 root 1.103 for (tmp = container->inv; tmp; tmp = tmp->below)
1901 root 1.18 {
1902     if (door->type == DOOR && tmp->type == KEY)
1903     break;
1904     /* For sanity, we should really check door type, but other stuff
1905     * (like containers) can be locked with special keys
1906     */
1907     if (tmp->slaying && tmp->type == SPECIAL_KEY && tmp->slaying == door->slaying)
1908     break;
1909     }
1910 root 1.103
1911 root 1.18 /* No key found - lets search inventories now */
1912     /* If we find and use a key in an inventory, return at that time.
1913     * otherwise, if we search all the inventories and still don't find
1914     * a key, return
1915     */
1916     if (!tmp)
1917     {
1918 root 1.103 for (tmp = container->inv; tmp; tmp = tmp->below)
1919 root 1.18 {
1920     /* No reason to search empty containers */
1921     if (tmp->type == CONTAINER && tmp->inv)
1922     {
1923 root 1.103 if ((key = find_key (pl, tmp, door)))
1924 root 1.18 return key;
1925     }
1926     }
1927 root 1.103
1928 root 1.18 if (!tmp)
1929     return NULL;
1930 elmex 1.1 }
1931 root 1.103
1932 root 1.18 /* We get down here if we have found a key. Now if its in a container,
1933     * see if we actually want to use it
1934     */
1935     if (pl != container)
1936     {
1937     /* Only let players use keys in containers */
1938     if (!pl->contr)
1939     return NULL;
1940     /* cases where this fails:
1941     * If we only search the player inventory, return now since we
1942     * are not in the players inventory.
1943     * If the container is not active, return now since only active
1944     * containers can be used.
1945     * If we only search keyrings and the container does not have
1946     * a race/isn't a keyring.
1947     * No checking for all containers - to fall through past here,
1948     * inv must have been an container and must have been active.
1949     *
1950     * Change the color so that the message doesn't disappear with
1951     * all the others.
1952     */
1953     if (pl->contr->usekeys == key_inventory ||
1954     !QUERY_FLAG (container, FLAG_APPLIED) ||
1955     (pl->contr->usekeys == keyrings && (!container->race || strcmp (container->race, "keys"))))
1956     {
1957     new_draw_info_format (NDI_UNIQUE | NDI_BROWN, 0, pl,
1958     "The %s in your %s vibrates as you approach the door", query_name (tmp), query_name (container));
1959     return NULL;
1960 root 1.11 }
1961 elmex 1.1 }
1962 root 1.103
1963 root 1.18 return tmp;
1964 elmex 1.1 }
1965    
1966     /* moved door processing out of move_player_attack.
1967     * returns 1 if player has opened the door with a key
1968     * such that the caller should not do anything more,
1969     * 0 otherwise
1970     */
1971 root 1.18 static int
1972     player_attack_door (object *op, object *door)
1973 elmex 1.1 {
1974 root 1.142 /* If its a door, try to find a key. If we do destroy the door,
1975 root 1.18 * might as well return immediately as there is nothing more to do -
1976     * otherwise, we fall through to the rest of the code.
1977     */
1978     object *key = find_key (op, op, door);
1979    
1980 root 1.142 /* If we found a key, do some extra work */
1981 root 1.18 if (key)
1982     {
1983     object *container = key->env;
1984    
1985     play_sound_map (op->map, op->x, op->y, SOUND_OPEN_DOOR);
1986 root 1.117
1987 root 1.18 if (action_makes_visible (op))
1988     make_visible (op);
1989 root 1.117
1990 root 1.18 if (door->inv && (door->inv->type == RUNE || door->inv->type == TRAP))
1991     spring_trap (door->inv, op);
1992 root 1.103
1993 root 1.18 if (door->type == DOOR)
1994 root 1.103 hit_player (door, 9998, op, AT_PHYSICAL, 1); /* Break through the door */
1995 root 1.18 else if (door->type == LOCKED_DOOR)
1996     {
1997     new_draw_info_format (NDI_UNIQUE, NDI_BROWN, op, "You open the door with the %s", query_short_name (key));
1998     remove_door2 (door); /* remove door without violence ;-) */
1999     }
2000 root 1.103
2001 root 1.18 /* Do this after we print the message */
2002     decrease_ob (key); /* Use up one of the keys */
2003     /* Need to update the weight the container the key was in */
2004     if (container != op)
2005     esrv_update_item (UPD_WEIGHT, op, container);
2006 root 1.103
2007 root 1.18 return 1; /* Nothing more to do below */
2008     }
2009     else if (door->type == LOCKED_DOOR)
2010     {
2011     /* Might as well return now - no other way to open this */
2012     new_draw_info (NDI_UNIQUE | NDI_NAVY, 0, op, door->msg);
2013     return 1;
2014 elmex 1.1 }
2015 root 1.103
2016 root 1.18 return 0;
2017 elmex 1.1 }
2018    
2019     /* This function is just part of a breakup from move_player.
2020     * It should keep the code cleaner.
2021     * When this is called, the players direction has been updated
2022     * (taking into account confusion.) The player is also actually
2023     * going to try and move (not fire weapons).
2024     */
2025 root 1.142 bool
2026 root 1.18 move_player_attack (object *op, int dir)
2027 elmex 1.1 {
2028 root 1.18 int on_battleground;
2029    
2030 root 1.117 sint16 nx = freearr_x[dir] + op->x;
2031     sint16 ny = freearr_y[dir] + op->y;
2032 root 1.18
2033 root 1.49 on_battleground = op_on_battleground (op, 0, 0);
2034 root 1.18
2035 root 1.142 if (out_of_map (op->map, nx, ny))
2036     return false;
2037    
2038     if (!op->contr->braced && op->speed_left > 0.f && move_ob (op, dir, op))
2039     {
2040     --op->speed_left;
2041     return true;
2042     }
2043    
2044 root 1.18 /* If braced, or can't move to the square, and it is not out of the
2045     * map, attack it. Note order of if statement is important - don't
2046     * want to be calling move_ob if braced, because move_ob will move the
2047     * player. This is a pretty nasty hack, because if we could
2048     * move to some space, it then means that if we are braced, we should
2049     * do nothing at all. As it is, if we are braced, we go through
2050     * quite a bit of processing. However, it probably is less than what
2051     * move_ob uses.
2052     */
2053 root 1.142 maptile *m = op->map->xy_find (nx, ny);
2054    
2055     /* Go through all the objects, and find ones of interest. Only stop if
2056     * we find a monster - that is something we know we want to attack.
2057     * if its a door or barrel (can roll) see if there may be monsters
2058     * on the space
2059     */
2060     object *mon;
2061     for (mon = m->at (nx, ny).bot; mon; mon = mon->above)
2062 root 1.18 {
2063 root 1.142 if ((mon->flag [FLAG_ALIVE]
2064     || mon->type == LOCKED_DOOR
2065     || mon->flag [FLAG_CAN_ROLL])
2066     && mon != op)
2067     break;
2068     }
2069    
2070     if (!mon) /* This happens anytime the player tries to move */
2071     return false; /* into a wall */
2072 root 1.18
2073 root 1.142 mon = mon->head_ ();
2074 root 1.11
2075 root 1.142 if ((mon->type == DOOR && mon->stats.hp >= 0) || (mon->type == LOCKED_DOOR))
2076     if (op->contr->weapon_sp_left > 0.f)
2077     if (player_attack_door (op, mon))
2078 root 1.18 {
2079 root 1.142 --op->contr->weapon_sp_left;
2080     return true;
2081 root 1.18 }
2082    
2083 root 1.142 /* The following deals with possibly attacking peaceful
2084     * or friendly creatures. Basically, all players are considered
2085     * unaggressive. If the moving player has peaceful set, then the
2086     * object should be pushed instead of attacked. It is assumed that
2087     * if you are braced, you will not attack friends accidently,
2088     * and thus will not push them.
2089     */
2090 root 1.18
2091 root 1.142 /* If the creature is a pet, push it even if the player is not
2092     * peaceful. Our assumption is the creature is a pet if the
2093     * player owns it and it is either friendly or unagressive.
2094     */
2095     if (op->type == PLAYER
2096     && ((mon->owner && mon->owner->contr
2097     && same_party (mon->owner->contr->party, op->contr->party))
2098     || mon->owner == op)
2099     && (QUERY_FLAG (mon, FLAG_UNAGGRESSIVE) || QUERY_FLAG (mon, FLAG_FRIENDLY)))
2100     {
2101     /* If we're braced, we don't want to switch places with it */
2102     if (op->contr->braced)
2103     return false;
2104 root 1.18
2105 root 1.142 if (op->speed_left > 0.f)
2106     {
2107     --op->speed_left;
2108 root 1.85
2109 root 1.18 play_sound_map (op->map, op->x, op->y, SOUND_PUSH_PLAYER);
2110 root 1.117 push_ob (mon, dir, op);
2111 root 1.142
2112 root 1.18 if (op->contr->tmp_invis || op->hide)
2113     make_visible (op);
2114 root 1.85
2115 root 1.142 return true;
2116 root 1.11 }
2117 root 1.142 else
2118     return false;
2119     }
2120 root 1.11
2121 root 1.142 /* in certain circumstances, you shouldn't attack friendly
2122     * creatures. Note that if you are braced, you can't push
2123     * someone, but put it inside this loop so that you won't
2124     * attack them either.
2125     */
2126     if ((mon->type == PLAYER || mon->enemy != op)
2127     && (mon->type == PLAYER || QUERY_FLAG (mon, FLAG_UNAGGRESSIVE) || QUERY_FLAG (mon, FLAG_FRIENDLY))
2128     && ((op->contr->peaceful
2129     || (mon->type == PLAYER && mon->contr->peaceful))
2130     && !on_battleground))
2131     {
2132     if (op->speed_left > 0.f)
2133 root 1.18 {
2134 root 1.142 --op->speed_left;
2135    
2136 root 1.18 if (!op->contr->braced)
2137     {
2138     play_sound_map (op->map, op->x, op->y, SOUND_PUSH_PLAYER);
2139 root 1.85 push_ob (mon, dir, op);
2140 root 1.18 }
2141     else
2142 root 1.49 new_draw_info (0, 0, op, "You withhold your attack");
2143    
2144 root 1.18 if (op->contr->tmp_invis || op->hide)
2145     make_visible (op);
2146 root 1.142
2147     return true;
2148 root 1.11 }
2149 root 1.142 }
2150     /* If the object is a boulder or other rollable object, then
2151     * roll it if not braced. You can't roll it if you are braced.
2152     */
2153     else if (QUERY_FLAG (mon, FLAG_CAN_ROLL) && (!op->contr->braced))
2154     {
2155     if (op->speed_left > 0.f)
2156     {
2157     --op->speed_left;
2158 elmex 1.1
2159 root 1.18 recursive_roll (mon, dir, op);
2160     if (action_makes_visible (op))
2161     make_visible (op);
2162 root 1.142
2163     return true;
2164 root 1.11 }
2165 root 1.142 }
2166     /* Any generic living creature. Including things like doors.
2167     * Way it works is like this: First, it must have some hit points
2168     * and be living. Then, it must be one of the following:
2169     * 1) Not a player, 2) A player, but of a different party. Note
2170     * that party_number -1 is no party, so attacks can still happen.
2171     */
2172     else if ((mon->stats.hp >= 0) && QUERY_FLAG (mon, FLAG_ALIVE) &&
2173     ((mon->type != PLAYER || op->contr->party == NULL || op->contr->party != mon->contr->party)))
2174     {
2175 root 1.143 if (op->contr->weapon_sp_left > 0.f && !op->flag [FLAG_WIZPASS])
2176 root 1.18 {
2177 root 1.142 --op->contr->weapon_sp_left;
2178 root 1.11
2179 root 1.49 skill_attack (mon, op, 0, 0, 0);
2180 root 1.11
2181 root 1.18 if (action_makes_visible (op))
2182     make_visible (op);
2183 root 1.142
2184     return true;
2185 root 1.11 }
2186 root 1.142 }
2187    
2188     return false;
2189 elmex 1.1 }
2190    
2191 root 1.142 bool
2192 root 1.18 move_player (object *op, int dir)
2193     {
2194     int pick;
2195 elmex 1.1
2196 root 1.84 if (!op->map || op->map->in_memory != MAP_IN_MEMORY)
2197 root 1.18 return 0;
2198 elmex 1.1
2199 root 1.18 /* Sanity check: make sure dir is valid */
2200     if ((dir < 0) || (dir >= 9))
2201     {
2202     LOG (llevError, "move_player: invalid direction %d\n", dir);
2203     return 0;
2204 elmex 1.1 }
2205    
2206 root 1.84 /* peterm: added following line */
2207 root 1.18 if (QUERY_FLAG (op, FLAG_CONFUSED) && dir)
2208 root 1.99 dir = absdir (dir + rndm (3) + rndm (3) - 2);
2209 root 1.18
2210     op->facing = dir;
2211    
2212     if (op->hide)
2213     do_hidden_move (op);
2214    
2215 root 1.142 bool retval;
2216    
2217 root 1.18 if (INVOKE_PLAYER (MOVE, op->contr, ARG_INT (dir)))
2218 root 1.142 retval = RESULT_INT (0);
2219 root 1.18 else if (op->contr->fire_on)
2220 root 1.142 retval = fire (op, dir);
2221 root 1.18 else
2222     {
2223 root 1.142 retval = move_player_attack (op, dir);
2224 root 1.18 pick = check_pick (op);
2225     }
2226 elmex 1.1
2227 root 1.18 /* Add special check for newcs players and fire on - this way, the
2228     * server can handle repeat firing.
2229     */
2230     if (op->contr->fire_on || (op->contr->run_on && pick != 0))
2231 root 1.49 op->direction = dir;
2232 root 1.18 else
2233 root 1.49 op->direction = 0;
2234    
2235 root 1.18 /* Update how the player looks. Use the facing, so direction may
2236     * get reset to zero. This allows for full animation capabilities
2237     * for players.
2238     */
2239     animate_object (op, op->facing);
2240 root 1.142
2241     return retval;
2242 elmex 1.1 }
2243    
2244     /* This is similar to handle_player, below, but is only used by the
2245     * new client/server stuff.
2246     * This is sort of special, in that the new client/server actually uses
2247     * the new speed values for commands.
2248     *
2249 root 1.142 * Returns true if there are more actions we can do. Should not do
2250     * many actions in a row, as that would be too unfair to other
2251     * players.
2252 elmex 1.1 */
2253 root 1.142 bool
2254 root 1.18 handle_newcs_player (object *op)
2255 elmex 1.1 {
2256 root 1.18 if (QUERY_FLAG (op, FLAG_SCARED))
2257     {
2258 root 1.142 if (op->speed_left > 0.f)
2259 root 1.18 {
2260 root 1.132 --op->speed_left;
2261 root 1.142 flee_player (op);
2262    
2263     return true;
2264 root 1.11 }
2265 root 1.142 else
2266     return false;
2267 elmex 1.1 }
2268    
2269 root 1.18 /* call this here - we also will call this in do_ericserver, but
2270     * the players time has been increased when doericserver has been
2271     * called, so we recheck it here.
2272     */
2273 root 1.83 if (op->contr->ns->handle_command ())
2274 root 1.142 return true;
2275 root 1.47
2276 root 1.142 if (op->direction && (op->contr->run_on || op->contr->fire_on))
2277     return move_player (op, op->direction);
2278 elmex 1.1
2279 root 1.142 return false;
2280 root 1.18 }
2281    
2282     int
2283     save_life (object *op)
2284     {
2285     if (!QUERY_FLAG (op, FLAG_LIFESAVE))
2286 elmex 1.1 return 0;
2287 root 1.18
2288 root 1.41 for (object *tmp = op->inv; tmp; tmp = tmp->below)
2289 root 1.18 if (QUERY_FLAG (tmp, FLAG_APPLIED) && QUERY_FLAG (tmp, FLAG_LIFESAVE))
2290     {
2291     play_sound_map (op->map, op->x, op->y, SOUND_OB_EVAPORATE);
2292     new_draw_info_format (NDI_UNIQUE, 0, op, "Your %s vibrates violently, then evaporates.", query_name (tmp));
2293 root 1.33
2294 root 1.18 if (op->contr)
2295     esrv_del_item (op->contr, tmp->count);
2296 root 1.33
2297     tmp->destroy ();
2298 root 1.18 CLEAR_FLAG (op, FLAG_LIFESAVE);
2299 root 1.33
2300 root 1.18 if (op->stats.hp < 0)
2301     op->stats.hp = op->stats.maxhp;
2302 root 1.33
2303 root 1.18 if (op->stats.food < 0)
2304     op->stats.food = 999;
2305 root 1.33
2306 root 1.54 op->update_stats ();
2307 root 1.18 return 1;
2308     }
2309 root 1.41
2310 root 1.18 LOG (llevError, "Error: LIFESAVE set without applied object.\n");
2311     CLEAR_FLAG (op, FLAG_LIFESAVE);
2312     enter_player_savebed (op); /* bring him home. */
2313     return 0;
2314 elmex 1.1 }
2315    
2316     /* This goes throws the inventory and removes unpaid objects, and puts them
2317     * back in the map (location and map determined by values of env). This
2318     * function will descend into containers. op is the object to start the search
2319     * from.
2320     */
2321 root 1.18 void
2322     remove_unpaid_objects (object *op, object *env)
2323 elmex 1.1 {
2324 root 1.18 while (op)
2325     {
2326 root 1.70 object *next = op->below; /* Make sure we have a good value, in case we remove object 'op' */
2327    
2328 root 1.18 if (QUERY_FLAG (op, FLAG_UNPAID))
2329     {
2330     if (env->type == PLAYER)
2331     esrv_del_item (env->contr, op->count);
2332 root 1.70
2333     op->insert_at (env);
2334 root 1.18 }
2335     else if (op->inv)
2336     remove_unpaid_objects (op->inv, env);
2337 root 1.41
2338 root 1.18 op = next;
2339 elmex 1.1 }
2340     }
2341    
2342     /*
2343     * Returns pointer a static string containing gravestone text
2344     * Moved from apply.c to player.c - player.c is what
2345     * actually uses this function. player.c may not be quite the
2346     * best, a misc file for object actions is probably better,
2347     * but there isn't one in the server directory.
2348     */
2349 root 1.18 char *
2350     gravestone_text (object *op)
2351 elmex 1.1 {
2352 root 1.18 static char buf2[MAX_BUF];
2353     char buf[MAX_BUF];
2354     time_t now = time (NULL);
2355    
2356     strcpy (buf2, " R.I.P.\n\n");
2357     if (op->type == PLAYER)
2358     sprintf (buf, "%s the %s\n", &op->name, op->contr->title);
2359     else
2360     sprintf (buf, "%s\n", &op->name);
2361 root 1.41
2362 root 1.18 strncat (buf2, " ", 20 - strlen (buf) / 2);
2363     strcat (buf2, buf);
2364     if (op->type == PLAYER)
2365     sprintf (buf, "who was in level %d when killed\n", op->level);
2366     else
2367     sprintf (buf, "who was in level %d when died.\n\n", op->level);
2368 root 1.41
2369 root 1.18 strncat (buf2, " ", 20 - strlen (buf) / 2);
2370     strcat (buf2, buf);
2371     if (op->type == PLAYER)
2372     {
2373     sprintf (buf, "by %s.\n\n", op->contr->killer);
2374     strncat (buf2, " ", 21 - strlen (buf) / 2);
2375     strcat (buf2, buf);
2376     }
2377 root 1.41
2378 root 1.18 strftime (buf, MAX_BUF, "%b %d %Y\n", localtime (&now));
2379     strncat (buf2, " ", 20 - strlen (buf) / 2);
2380     strcat (buf2, buf);
2381 root 1.41
2382 root 1.18 return buf2;
2383 elmex 1.1 }
2384    
2385 root 1.18 void
2386     do_some_living (object *op)
2387     {
2388     int last_food = op->stats.food;
2389 elmex 1.1 int gen_hp, gen_sp, gen_grace;
2390     int over_hp, over_sp, over_grace;
2391     int i;
2392     int rate_hp = 1200;
2393     int rate_sp = 2500;
2394     int rate_grace = 2000;
2395     const int max_hp = 1;
2396     const int max_sp = 1;
2397     const int max_grace = 1;
2398    
2399 root 1.107 if (op->contr->hidden)
2400     {
2401     op->invisible = 1000;
2402     /* the socket code flashes the player visible/invisible
2403     * depending on the value of invisible, so we need to
2404     * alternate it here for it to work correctly.
2405     */
2406     if (pticks & 2)
2407     op->invisible--;
2408     }
2409     else if (op->invisible && !(QUERY_FLAG (op, FLAG_MAKE_INVIS)))
2410     {
2411     if (!op->invisible--)
2412     {
2413     make_visible (op);
2414     new_draw_info (NDI_UNIQUE, 0, op, "Your invisibility spell runs out.");
2415     }
2416     }
2417    
2418 root 1.52 if (op->contr->ns->state == ST_PLAYING)
2419 root 1.18 {
2420     /* these next three if clauses make it possible to SLOW DOWN
2421     hp/grace/spellpoint regeneration. */
2422     if (op->contr->gen_hp >= 0)
2423     gen_hp = (op->contr->gen_hp + 1) * op->stats.maxhp;
2424     else
2425     {
2426     gen_hp = op->stats.maxhp;
2427     rate_hp -= rate_hp / 2 * op->contr->gen_hp;
2428     }
2429 root 1.55
2430 root 1.18 if (op->contr->gen_sp >= 0)
2431     gen_sp = (op->contr->gen_sp + 1) * op->stats.maxsp;
2432     else
2433     {
2434     gen_sp = op->stats.maxsp;
2435     rate_sp -= rate_sp / 2 * op->contr->gen_sp;
2436     }
2437 root 1.55
2438 root 1.18 if (op->contr->gen_grace >= 0)
2439     gen_grace = (op->contr->gen_grace + 1) * op->stats.maxgrace;
2440     else
2441     {
2442     gen_grace = op->stats.maxgrace;
2443     rate_grace -= rate_grace / 2 * op->contr->gen_grace;
2444     }
2445    
2446     /* Regenerate Spell Points */
2447 root 1.118 if (!op->contr->golem && --op->last_sp < 0)
2448 root 1.18 {
2449     gen_sp = gen_sp * 10 / (op->contr->gen_sp_armour < 10 ? 10 : op->contr->gen_sp_armour);
2450     if (op->stats.sp < op->stats.maxsp)
2451     {
2452     op->stats.sp++;
2453     /* dms do not consume food */
2454     if (!QUERY_FLAG (op, FLAG_WIZ))
2455     {
2456     op->stats.food--;
2457     if (op->contr->digestion < 0)
2458     op->stats.food += op->contr->digestion;
2459     else if (op->contr->digestion > 0 && random_roll (0, op->contr->digestion, op, PREFER_HIGH))
2460     op->stats.food = last_food;
2461     }
2462     }
2463 root 1.55
2464 root 1.18 if (max_sp > 1)
2465     {
2466     over_sp = (gen_sp + 10) / rate_sp;
2467     if (over_sp > 0)
2468     {
2469     if (op->stats.sp < op->stats.maxsp)
2470     {
2471     op->stats.sp += over_sp > max_sp ? max_sp : over_sp;
2472 root 1.55
2473 root 1.18 if (random_roll (0, rate_sp - 1, op, PREFER_LOW) > ((gen_sp + 10) % rate_sp))
2474     op->stats.sp--;
2475 root 1.55
2476 root 1.18 if (op->stats.sp > op->stats.maxsp)
2477     op->stats.sp = op->stats.maxsp;
2478     }
2479     op->last_sp = 0;
2480     }
2481     else
2482 root 1.55 op->last_sp = rate_sp / (gen_sp < 20 ? 30 : gen_sp + 10);
2483 root 1.18 }
2484     else
2485 root 1.55 op->last_sp = rate_sp / (gen_sp < 20 ? 30 : gen_sp + 10);
2486 root 1.18 }
2487    
2488     /* Regenerate Grace */
2489     /* I altered this a little - maximum grace is ony achieved through prayer -b.t. */
2490     if (--op->last_grace < 0)
2491     {
2492     if (op->stats.grace < op->stats.maxgrace / 2)
2493     op->stats.grace++; /* no penalty in food for regaining grace */
2494 root 1.55
2495 root 1.18 if (max_grace > 1)
2496     {
2497     over_grace = (gen_grace < 20 ? 30 : gen_grace + 10) / rate_grace;
2498     if (over_grace > 0)
2499     {
2500     op->stats.sp += over_grace
2501     + (random_roll (0, rate_grace - 1, op, PREFER_HIGH) > ((gen_grace < 20 ? 30 : gen_grace + 10) % rate_grace)) ? -1 : 0;
2502     op->last_grace = 0;
2503     }
2504     else
2505     {
2506     op->last_grace = rate_grace / (gen_grace < 20 ? 30 : gen_grace + 10);
2507     }
2508     }
2509     else
2510     {
2511     op->last_grace = rate_grace / (gen_grace < 20 ? 30 : gen_grace + 10);
2512     }
2513     /* wearing stuff doesn't detract from grace generation. */
2514     }
2515    
2516     /* Regenerate Hit Points */
2517     if (--op->last_heal < 0)
2518     {
2519     if (op->stats.hp < op->stats.maxhp)
2520     {
2521     op->stats.hp++;
2522     /* dms do not consume food */
2523     if (!QUERY_FLAG (op, FLAG_WIZ))
2524     {
2525     op->stats.food--;
2526     if (op->contr->digestion < 0)
2527     op->stats.food += op->contr->digestion;
2528     else if (op->contr->digestion > 0 && random_roll (0, op->contr->digestion, op, PREFER_HIGH))
2529     op->stats.food = last_food;
2530     }
2531     }
2532 root 1.55
2533 root 1.18 if (max_hp > 1)
2534     {
2535     over_hp = (gen_hp < 20 ? 30 : gen_hp + 10) / rate_hp;
2536     if (over_hp > 0)
2537     {
2538     op->stats.sp += over_hp + (RANDOM () % rate_hp > ((gen_hp < 20 ? 30 : gen_hp + 10) % rate_hp)) ? -1 : 0;
2539     op->last_heal = 0;
2540     }
2541     else
2542     {
2543     op->last_heal = rate_hp / (gen_hp < 20 ? 30 : gen_hp + 10);
2544     }
2545     }
2546     else
2547     {
2548     op->last_heal = rate_hp / (gen_hp < 20 ? 30 : gen_hp + 10);
2549     }
2550 root 1.11 }
2551 elmex 1.1
2552 root 1.18 /* Digestion */
2553     if (--op->last_eat < 0)
2554     {
2555     int bonus = op->contr->digestion > 0 ? op->contr->digestion : 0, penalty = op->contr->digestion < 0 ? -op->contr->digestion : 0;
2556    
2557     if (op->contr->gen_hp > 0)
2558     op->last_eat = 25 * (1 + bonus) / (op->contr->gen_hp + penalty + 1);
2559     else
2560     op->last_eat = 25 * (1 + bonus) / (penalty + 1);
2561 root 1.55
2562 root 1.18 /* dms do not consume food */
2563     if (!QUERY_FLAG (op, FLAG_WIZ))
2564     op->stats.food--;
2565 root 1.11 }
2566 elmex 1.1
2567 root 1.55 if (op->stats.food < 0 && op->stats.hp >= 0)
2568     {
2569     object *tmp, *flesh = 0;
2570 root 1.18
2571 root 1.55 for (tmp = op->inv; tmp; tmp = tmp->below)
2572 root 1.18 {
2573 root 1.55 if (!QUERY_FLAG (tmp, FLAG_UNPAID))
2574 root 1.18 {
2575 root 1.55 if (tmp->type == FOOD || tmp->type == DRINK || tmp->type == POISON)
2576     {
2577     new_draw_info (NDI_UNIQUE, 0, op, "You blindly grab for a bite of food.");
2578     manual_apply (op, tmp, 0);
2579     if (op->stats.food >= 0 || op->stats.hp < 0)
2580     break;
2581     }
2582     else if (tmp->type == FLESH)
2583     flesh = tmp;
2584     } /* End if paid for object */
2585     } /* end of for loop */
2586    
2587     /* If player is still starving, it means they don't have any food, so
2588     * eat flesh instead.
2589     */
2590     if (op->stats.food < 0 && op->stats.hp >= 0 && flesh)
2591     {
2592     new_draw_info (NDI_UNIQUE, 0, op, "You blindly grab for a bite of food.");
2593     manual_apply (op, flesh, 0);
2594     }
2595 root 1.11 }
2596 elmex 1.1
2597 root 1.55 while (op->stats.food < 0 && op->stats.hp >= 0)
2598     op->stats.food++, op->stats.hp--;
2599 elmex 1.1
2600 root 1.55 if (op->stats.hp < 0 && !QUERY_FLAG (op, FLAG_WIZ))
2601     kill_player (op);
2602     }
2603 elmex 1.1 }
2604    
2605     /* If the player should die (lack of hp, food, etc), we call this.
2606     * op is the player in jeopardy. If the player can not be saved (not
2607     * permadeath, no lifesave), this will take care of removing the player
2608     * file.
2609     */
2610 root 1.18 void
2611     kill_player (object *op)
2612 elmex 1.1 {
2613 root 1.18 char buf[MAX_BUF];
2614     int x, y;
2615    
2616     //int i;
2617 root 1.25 maptile *map; /* this is for resurrection */
2618 root 1.18
2619     /* int z;
2620     int num_stats_lose;
2621     int lost_a_stat;
2622     int lose_this_stat;
2623     int this_stat; */
2624     int will_kill_again;
2625     archetype *at;
2626     object *tmp;
2627    
2628     if (save_life (op))
2629     return;
2630    
2631    
2632     /* If player dies on BATTLEGROUND, no stat/exp loss! For Combat-Arenas
2633     * in cities ONLY!!! It is very important that this doesn't get abused.
2634     * Look at op_on_battleground() for more info --AndreasV
2635     */
2636     if (op_on_battleground (op, &x, &y))
2637     {
2638     new_draw_info (NDI_UNIQUE | NDI_NAVY, 0, op, "You have been defeated in combat!");
2639     new_draw_info (NDI_UNIQUE | NDI_NAVY, 0, op, "Local medics have saved your life...");
2640    
2641     /* restore player */
2642 root 1.22 at = archetype::find ("poisoning");
2643 root 1.70 if (object *tmp = present_arch_in_ob (at, op))
2644 root 1.18 {
2645 root 1.33 tmp->destroy ();
2646 root 1.18 new_draw_info (NDI_UNIQUE, 0, op, "Your body feels cleansed");
2647     }
2648 elmex 1.1
2649 root 1.22 at = archetype::find ("confusion");
2650 root 1.70 if (object *tmp = present_arch_in_ob (at, op))
2651 root 1.18 {
2652 root 1.33 tmp->destroy ();
2653 root 1.18 new_draw_info (NDI_UNIQUE, 0, tmp, "Your mind feels clearer");
2654     }
2655    
2656     cure_disease (op, 0); /* remove any disease */
2657     op->stats.hp = op->stats.maxhp;
2658     if (op->stats.food <= 0)
2659     op->stats.food = 999;
2660 elmex 1.1
2661 root 1.18 /* create a bodypart-trophy to make the winner happy */
2662 root 1.70 if (object *tmp = arch_to_object (archetype::find ("finger")))
2663 root 1.18 {
2664     sprintf (buf, "%s's finger", &op->name);
2665     tmp->name = buf;
2666     sprintf (buf, " This finger has been cut off %s\n"
2667     " the %s, when he was defeated at\n level %d by %s.\n",
2668     &op->name, op->contr->title, (int) (op->level), op->contr->killer);
2669     tmp->msg = buf;
2670 root 1.102 tmp->value = 0, tmp->type = 0;
2671     tmp->materialname = "organics";
2672 elmex 1.87 tmp->insert_at (op, tmp);
2673 root 1.18 }
2674 elmex 1.1
2675 root 1.18 /* teleport defeated player to new destination */
2676     transfer_ob (op, x, y, 0, NULL);
2677     op->contr->braced = 0;
2678     return;
2679 elmex 1.1 }
2680    
2681 root 1.18 INVOKE_PLAYER (DEATH, op->contr);
2682 root 1.3
2683 root 1.18 command_kill_pets (op, 0);
2684 elmex 1.1
2685 root 1.18 if (op->stats.food < 0)
2686     {
2687     sprintf (buf, "%s starved to death.", &op->name);
2688     strcpy (op->contr->killer, "starvation");
2689 elmex 1.1 }
2690 root 1.18 else
2691 root 1.89 sprintf (buf, "%s died.", &op->name);
2692 root 1.70
2693 root 1.18 play_sound_player_only (op->contr, SOUND_PLAYER_DIES, 0, 0);
2694 elmex 1.1
2695 root 1.18 /* save the map location for corpse, gravestone */
2696 root 1.70 x = op->x;
2697     y = op->y;
2698 root 1.18 map = op->map;
2699 elmex 1.1
2700 root 1.54 /* NOT_PERMADEATH code. This basically brings the character back to
2701     * life if they are dead - it takes some exp and a random stat.
2702     * See the config.h file for a little more in depth detail about this.
2703     */
2704    
2705     /* Basically two ways to go - remove a stat permanently, or just
2706     * make it depletion. This bunch of code deals with that aspect
2707     * of death.
2708     */
2709     #ifndef COZY_SERVER
2710     if (settings.balanced_stat_loss)
2711 root 1.18 {
2712 root 1.54 /* If stat loss is permanent, lose one stat only. */
2713     /* Lower level chars don't lose as many stats because they suffer
2714     more if they do. */
2715     /* Higher level characters can afford things such as potions of
2716     restoration, or better, stat potions. So we slug them that
2717     little bit harder. */
2718     /* GD */
2719     if (settings.stat_loss_on_death)
2720     num_stats_lose = 1;
2721     else
2722     num_stats_lose = 1 + op->level / BALSL_NUMBER_LOSSES_RATIO;
2723     }
2724     else
2725 root 1.70 num_stats_lose = 1;
2726    
2727 root 1.54 lost_a_stat = 0;
2728    
2729     for (z = 0; z < num_stats_lose; z++)
2730     {
2731     i = RANDOM () % NUM_STATS;
2732 root 1.11
2733 root 1.54 if (settings.stat_loss_on_death)
2734 root 1.18 {
2735 root 1.54 /* Pick a random stat and take a point off it. Tell the player
2736     * what he lost.
2737     */
2738     change_attr_value (&(op->stats), i, -1);
2739     check_stat_bounds (&(op->stats));
2740     change_attr_value (&(op->contr->orig_stats), i, -1);
2741     check_stat_bounds (&(op->contr->orig_stats));
2742     new_draw_info (NDI_UNIQUE, 0, op, lose_msg[i]);
2743     lost_a_stat = 1;
2744 root 1.18 }
2745     else
2746     {
2747 root 1.54 /* deplete a stat */
2748     archetype *deparch = archetype::find ("depletion");
2749     object *dep;
2750 root 1.11
2751 root 1.54 dep = present_arch_in_ob (deparch, op);
2752     if (!dep)
2753 root 1.18 {
2754 root 1.54 dep = arch_to_object (deparch);
2755     insert_ob_in_ob (dep, op);
2756 root 1.18 }
2757 root 1.54 lose_this_stat = 1;
2758     if (settings.balanced_stat_loss)
2759 root 1.18 {
2760 root 1.54 /* GD */
2761     /* Get the stat that we're about to deplete. */
2762     this_stat = get_attr_value (&(dep->stats), i);
2763     if (this_stat < 0)
2764     {
2765     int loss_chance = 1 + op->level / BALSL_LOSS_CHANCE_RATIO;
2766     int keep_chance = this_stat * this_stat;
2767 root 1.18
2768 root 1.54 /* Yes, I am paranoid. Sue me. */
2769     if (keep_chance < 1)
2770     keep_chance = 1;
2771 root 1.18
2772 root 1.54 /* There is a maximum depletion total per level. */
2773     if (this_stat < -1 - op->level / BALSL_MAX_LOSS_RATIO)
2774     {
2775     lose_this_stat = 0;
2776     /* Take loss chance vs keep chance to see if we
2777     retain the stat. */
2778     }
2779     else
2780     {
2781     if (random_roll (0, loss_chance + keep_chance - 1, op, PREFER_LOW) < keep_chance)
2782     lose_this_stat = 0;
2783     /* LOG(llevDebug, "Determining stat loss. Stat: %d Keep: %d Lose: %d Result: %s.\n",
2784     this_stat, keep_chance, loss_chance,
2785     lose_this_stat?"LOSE":"KEEP"); */
2786 root 1.11 }
2787     }
2788 root 1.54 }
2789 root 1.18
2790 root 1.54 if (lose_this_stat)
2791     {
2792     this_stat = get_attr_value (&(dep->stats), i);
2793     /* We could try to do something clever like find another
2794     * stat to reduce if this fails. But chances are, if
2795     * stats have been depleted to -50, all are pretty low
2796     * and should be roughly the same, so it shouldn't make a
2797     * difference.
2798     */
2799     if (this_stat >= -50)
2800 root 1.18 {
2801 root 1.54 change_attr_value (&(dep->stats), i, -1);
2802     SET_FLAG (dep, FLAG_APPLIED);
2803     new_draw_info (NDI_UNIQUE, 0, op, lose_msg[i]);
2804     op->update_stats ();
2805     lost_a_stat = 1;
2806 root 1.11 }
2807     }
2808     }
2809 root 1.54 }
2810     /* If no stat lost, tell the player. */
2811     if (!lost_a_stat)
2812     {
2813     /* determine_god() seems to not work sometimes... why is this?
2814     Should I be using something else? GD */
2815     const char *god = determine_god (op);
2816 root 1.18
2817 root 1.54 if (god && (strcmp (god, "none")))
2818     new_draw_info_format (NDI_UNIQUE, 0, op, "For a brief moment you feel the holy presence of %s protecting" " you.", god);
2819     else
2820     new_draw_info (NDI_UNIQUE, 0, op, "For a brief moment you feel a holy presence protecting you.");
2821     }
2822 root 1.28 #else
2823 root 1.54 new_draw_info (NDI_UNIQUE, 0, op, "For a brief moment you" " feel a holy presence protecting you from losing yourself completely.");
2824 elmex 1.1 #endif
2825    
2826 root 1.54 /* Put a gravestone up where the character 'almost' died. List the
2827     * exp loss on the stone.
2828     */
2829     tmp = arch_to_object (archetype::find ("gravestone"));
2830     sprintf (buf, "%s's gravestone", &op->name);
2831     tmp->name = buf;
2832     sprintf (buf, "%s's gravestones", &op->name);
2833     tmp->name_pl = buf;
2834     sprintf (buf, "RIP\nHere rests the hero %s the %s,\n" "who was killed\n" "by %s.\n", &op->name, op->contr->title, op->contr->killer);
2835     tmp->msg = buf;
2836     tmp->x = op->x, tmp->y = op->y;
2837     insert_ob_in_map (tmp, op->map, NULL, 0);
2838    
2839     /**************************************/
2840     /* */
2841     /* Subtract the experience points, */
2842     /* if we died cause of food, give us */
2843     /* food, and reset HP's... */
2844     /* */
2845     /**************************************/
2846    
2847     /* remove any poisoning and confusion the character may be suffering. */
2848     /* restore player */
2849     at = archetype::find ("poisoning");
2850     tmp = present_arch_in_ob (at, op);
2851    
2852     if (tmp)
2853     {
2854     tmp->destroy ();
2855     new_draw_info (NDI_UNIQUE, 0, op, "Your body feels cleansed");
2856     }
2857    
2858     at = archetype::find ("confusion");
2859     tmp = present_arch_in_ob (at, op);
2860     if (tmp)
2861     {
2862     tmp->destroy ();
2863     new_draw_info (NDI_UNIQUE, 0, tmp, "Your mind feels clearer");
2864     }
2865    
2866     cure_disease (op, 0); /* remove any disease */
2867    
2868     /*add_exp(op, (op->stats.exp * -0.20)); */
2869     apply_death_exp_penalty (op);
2870     if (op->stats.food < 100)
2871     op->stats.food = 900;
2872     op->stats.hp = op->stats.maxhp;
2873     op->stats.sp = MAX (op->stats.sp, op->stats.maxsp);
2874     op->stats.grace = MAX (op->stats.grace, op->stats.maxgrace);
2875 root 1.11
2876 root 1.54 /*
2877 root 1.108 * Check to see if the player has any unpaid items. If so, remove them
2878     * and put them back in the map.
2879 root 1.54 */
2880 root 1.108 remove_unpaid_objects (op->inv, op);
2881 root 1.18
2882 root 1.54 /****************************************/
2883     /* */
2884     /* Move player to his current respawn- */
2885     /* position (usually last savebed) */
2886     /* */
2887     /****************************************/
2888 root 1.18
2889 root 1.54 enter_player_savebed (op);
2890 root 1.18
2891 root 1.54 op->contr->braced = 0;
2892 root 1.11
2893 root 1.54 /* it is possible that the player has blown something up
2894     * at his savebed location, and that can have long lasting
2895     * spell effects. So first see if there is a spell effect
2896     * on the space that might harm the player.
2897     */
2898     will_kill_again = 0;
2899     for (tmp = GET_MAP_OB (op->map, op->x, op->y); tmp; tmp = tmp->above)
2900     if (tmp->type == SPELL_EFFECT)
2901     will_kill_again |= tmp->attacktype;
2902 elmex 1.1
2903 root 1.54 if (will_kill_again)
2904 root 1.18 {
2905 root 1.54 object *force;
2906     int at;
2907 root 1.18
2908 root 1.54 force = get_archetype (FORCE_NAME);
2909     /* 50 ticks should be enough time for the spell to abate */
2910 root 1.133 force->speed = 0.1f;
2911     force->speed_left = -5.f;
2912 root 1.54 SET_FLAG (force, FLAG_APPLIED);
2913     for (at = 0; at < NROFATTACKS; at++)
2914     if (will_kill_again & (1 << at))
2915     force->resist[at] = 100;
2916 root 1.30
2917 root 1.54 insert_ob_in_ob (force, op);
2918     op->update_stats ();
2919 root 1.30
2920 root 1.54 }
2921 root 1.18
2922 root 1.54 new_draw_info (NDI_UNIQUE, 0, op, "YOU HAVE DIED.");
2923 elmex 1.1 }
2924    
2925 root 1.18 void
2926     loot_object (object *op)
2927     { /* Grab and destroy some treasure */
2928     object *tmp, *tmp2, *next;
2929 elmex 1.1
2930 root 1.103 op->close_container (); /* close open sack first */
2931 elmex 1.1
2932 root 1.54 for (tmp = op->inv; tmp; tmp = next)
2933 root 1.18 {
2934     next = tmp->below;
2935 root 1.54
2936 elmex 1.50 if (tmp->invisible)
2937 root 1.18 continue;
2938 root 1.54
2939 root 1.32 tmp->remove ();
2940 root 1.18 tmp->x = op->x, tmp->y = op->y;
2941 root 1.103
2942 root 1.18 if (tmp->type == CONTAINER)
2943 root 1.103 loot_object (tmp); /* empty container to ground */
2944    
2945 root 1.99 if (!QUERY_FLAG (tmp, FLAG_UNIQUE) && (QUERY_FLAG (tmp, FLAG_STARTEQUIP) || QUERY_FLAG (tmp, FLAG_NO_DROP) || !(rndm (3))))
2946 root 1.18 {
2947     if (tmp->nrof > 1)
2948     {
2949     tmp2 = get_split_ob (tmp, 1 + RANDOM () % (tmp->nrof - 1));
2950 root 1.33 tmp2->destroy ();
2951 root 1.18 insert_ob_in_map (tmp, op->map, NULL, 0);
2952     }
2953     else
2954 root 1.33 tmp->destroy ();
2955 root 1.18 }
2956     else
2957     insert_ob_in_map (tmp, op->map, NULL, 0);
2958     }
2959 elmex 1.1 }
2960    
2961     /*
2962     * fix_weight(): Check recursively the weight of all players, and fix
2963     * what needs to be fixed. Refresh windows and fix speed if anything
2964     * was changed.
2965     */
2966 root 1.18 void
2967     fix_weight (void)
2968     {
2969 root 1.61 for_all_players (pl)
2970 root 1.18 {
2971     int old = pl->ob->carrying, sum = sum_weight (pl->ob);
2972    
2973     if (old == sum)
2974     continue;
2975 root 1.54 pl->ob->update_stats ();
2976 root 1.18 LOG (llevDebug, "Fixed inventory in %s (%d -> %d)\n", &pl->ob->name, old, sum);
2977     }
2978 elmex 1.1 }
2979    
2980 root 1.18 void
2981     fix_luck (void)
2982     {
2983 root 1.61 for_all_players (pl)
2984 root 1.52 if (!pl->ob->contr->ns->state)
2985 root 1.54 pl->ob->change_luck (0);
2986 elmex 1.1 }
2987    
2988     /* cast_dust() - handles op throwing objects of type 'DUST'.
2989     * This is much simpler in the new spell code - we basically
2990     * just treat this as any other spell casting object.
2991     */
2992 elmex 1.2 void
2993 root 1.18 cast_dust (object *op, object *throw_ob, int dir)
2994 elmex 1.2 {
2995     object *skop, *spob;
2996    
2997     skop = find_skill_by_name (op, throw_ob->skill);
2998    
2999     /* casting POTION 'dusts' is really a use_magic_item skill */
3000     if (op->type == PLAYER && throw_ob->type == POTION && !skop)
3001     {
3002 root 1.18 LOG (llevError, "Player %s lacks critical skill use_magic_item!\n", &op->name);
3003 elmex 1.2 return;
3004     }
3005    
3006     spob = throw_ob->inv;
3007    
3008     // elmex Tue Aug 15 17:19:46 CEST 2006: Added this check to
3009     // not pass NULL to cast_spell (which did indeed check itself, but
3010     // errors should be reported as early as possible IMHO)
3011     if (!spob)
3012     {
3013 root 1.18 LOG (llevError, "cast_dust: thrown object %s (by %s) had no spell in it!", &throw_ob->name, &op->name);
3014 elmex 1.2 return;
3015 elmex 1.1 }
3016    
3017 elmex 1.2 if (op->type == PLAYER)
3018 root 1.14 new_draw_info_format (NDI_UNIQUE, 0, op, "You cast %s.", &spob->name);
3019 elmex 1.2
3020     cast_spell (op, throw_ob, dir, spob, NULL);
3021    
3022 root 1.33 throw_ob->destroy ();
3023 elmex 1.1 }
3024    
3025 root 1.18 void
3026     make_visible (object *op)
3027     {
3028     op->hide = 0;
3029     op->invisible = 0;
3030     if (op->type == PLAYER)
3031     {
3032     op->contr->tmp_invis = 0;
3033     op->contr->invis_race = 0;
3034     }
3035 root 1.107
3036     update_object (op, UP_OBJ_CHANGE);
3037 root 1.18 }
3038    
3039     int
3040     is_true_undead (object *op)
3041     {
3042 root 1.149 if (QUERY_FLAG (op->arch, FLAG_UNDEAD))
3043 root 1.18 return 1;
3044    
3045 elmex 1.1 return 0;
3046     }
3047    
3048     /* look at the surrounding terrain to determine
3049     * the hideability of this object. Positive levels
3050     * indicate greater hideability.
3051     */
3052    
3053 root 1.18 int
3054     hideability (object *ob)
3055     {
3056     int i, level = 0, mflag;
3057     sint16 x, y;
3058    
3059     if (!ob || !ob->map)
3060     return 0;
3061    
3062     /* so, on normal lighted maps, its hard to hide */
3063     level = ob->map->darkness - 2;
3064    
3065     /* this also picks up whether the object is glowing.
3066     * If you carry a light on a non-dark map, its not
3067     * as bad as carrying a light on a pitch dark map */
3068     if (has_carried_lights (ob))
3069     level = -(10 + (2 * ob->map->darkness));
3070    
3071     /* scan through all nearby squares for terrain to hide in */
3072     for (i = 0, x = ob->x, y = ob->y; i < 9; i++, x = ob->x + freearr_x[i], y = ob->y + freearr_y[i])
3073     {
3074     mflag = get_map_flags (ob->map, NULL, x, y, NULL, NULL);
3075     if (mflag & P_OUT_OF_MAP)
3076     {
3077     continue;
3078     }
3079     if (mflag & P_BLOCKSVIEW) /* something to hide near! */
3080     level += 2;
3081     else /* open terrain! */
3082     level -= 1;
3083 elmex 1.1 }
3084 root 1.18
3085 elmex 1.1 #if 0
3086 root 1.18 LOG (llevDebug, "hideability of %s is %d\n", ob->name, level);
3087 elmex 1.1 #endif
3088 root 1.18 return level;
3089 elmex 1.1 }
3090    
3091     /* For Hidden creatures - a chance of becoming 'unhidden'
3092     * every time they move - as we subtract off 'invisibility'
3093     * AND, for players, if they move into a ridiculously unhideable
3094     * spot (surrounded by clear terrain in broad daylight). -b.t.
3095     */
3096 root 1.18 void
3097     do_hidden_move (object *op)
3098     {
3099     int hide = 0, num = random_roll (0, 19, op, PREFER_LOW);
3100     object *skop;
3101    
3102     if (!op || !op->map)
3103     return;
3104    
3105     skop = find_obj_by_type_subtype (op, SKILL, SK_HIDING);
3106    
3107     /* its *extremely* hard to run and sneak/hide at the same time! */
3108     if (op->type == PLAYER && op->contr->run_on)
3109 root 1.85 if (!skop || num >= skop->level)
3110     {
3111     new_draw_info (NDI_UNIQUE, 0, op, "You ran too much! You are no longer hidden!");
3112     make_visible (op);
3113     return;
3114     }
3115     else
3116     num += 20;
3117    
3118 root 1.18 num += op->map->difficulty;
3119     hide = hideability (op); /* modify by terrain hidden level */
3120     num -= hide;
3121 root 1.85
3122 root 1.18 if ((op->type == PLAYER && hide < -10) || ((op->invisible -= num) <= 0))
3123     {
3124     make_visible (op);
3125     if (op->type == PLAYER)
3126     new_draw_info (NDI_UNIQUE, 0, op, "You moved out of hiding! You are visible!");
3127 elmex 1.1 }
3128 root 1.18 else if (op->type == PLAYER && skop)
3129 root 1.85 change_exp (op, calc_skill_exp (op, NULL, skop), skop->skill, 0);
3130 elmex 1.1 }
3131    
3132     /* determine if who is standing near a hostile creature. */
3133    
3134 root 1.18 int
3135     stand_near_hostile (object *who)
3136     {
3137     object *tmp = NULL;
3138     int i, friendly = 0, player = 0, mflags;
3139 root 1.25 maptile *m;
3140 root 1.18 sint16 x, y;
3141    
3142     if (!who)
3143     return 0;
3144    
3145     if (who->type == PLAYER)
3146     player = 1;
3147    
3148     else
3149     friendly = QUERY_FLAG (who, FLAG_FRIENDLY);
3150    
3151     /* search adjacent squares */
3152     for (i = 1; i < 9; i++)
3153     {
3154     x = who->x + freearr_x[i];
3155     y = who->y + freearr_y[i];
3156     m = who->map;
3157     mflags = get_map_flags (m, &m, x, y, &x, &y);
3158     /* space must be blocked if there is a monster. If not
3159     * blocked, don't need to check this space.
3160     */
3161     if (mflags & P_OUT_OF_MAP)
3162     continue;
3163     if (OB_TYPE_MOVE_BLOCK (who, GET_MAP_MOVE_BLOCK (m, x, y)))
3164     continue;
3165    
3166 root 1.49 for (tmp = GET_MAP_OB (m, x, y); tmp; tmp = tmp->above)
3167 root 1.18 {
3168     if ((player ||friendly) &&QUERY_FLAG (tmp, FLAG_MONSTER) && !QUERY_FLAG (tmp, FLAG_UNAGGRESSIVE))
3169     return 1;
3170     else if (tmp->type == PLAYER)
3171     {
3172     /*don't let a hidden DM prevent you from hiding */
3173     if (!QUERY_FLAG (tmp, FLAG_WIZ) || tmp->contr->hidden == 0)
3174 root 1.11 return 1;
3175 root 1.18 }
3176 root 1.11 }
3177 elmex 1.1 }
3178 root 1.18 return 0;
3179 elmex 1.1 }
3180    
3181     /* check the player los field for viewability of the
3182     * object op. This function works fine for monsters,
3183     * but we dont worry if the object isnt the top one in
3184     * a pile (say a coin under a table would return "viewable"
3185     * by this routine). Another question, should we be
3186     * concerned with the direction the player is looking
3187     * in? Realistically, most of use cant see stuff behind
3188     * our backs...on the other hand, does the "facing" direction
3189     * imply the way your head, or body is facing? Its possible
3190     * for them to differ. Sigh, this fctn could get a bit more complex.
3191     * -b.t.
3192     * This function is now map tiling safe.
3193     */
3194    
3195 root 1.18 int
3196     player_can_view (object *pl, object *op)
3197     {
3198     rv_vector rv;
3199     int dx, dy;
3200    
3201     if (pl->type != PLAYER)
3202     {
3203     LOG (llevError, "player_can_view() called for non-player object\n");
3204     return -1;
3205 elmex 1.1 }
3206 root 1.74
3207 root 1.18 if (!pl || !op)
3208 elmex 1.1 return 0;
3209 root 1.18
3210 root 1.74 op = op->head_ ();
3211    
3212 root 1.18 get_rangevector (pl, op, &rv, 0x1);
3213    
3214     /* starting with the 'head' part, lets loop
3215     * through the object and find if it has any
3216     * part that is in the los array but isnt on
3217     * a blocked los square.
3218     * we use the archetype to figure out offsets.
3219     */
3220     while (op)
3221     {
3222 root 1.149 dx = rv.distance_x + op->arch->x;
3223     dy = rv.distance_y + op->arch->y;
3224 root 1.18
3225     /* only the viewable area the player sees is updated by LOS
3226     * code, so we need to restrict ourselves to that range of values
3227     * for any meaningful values.
3228     */
3229 root 1.52 if (FABS (dx) <= (pl->contr->ns->mapx / 2) &&
3230     FABS (dy) <= (pl->contr->ns->mapy / 2) &&
3231     !pl->contr->blocked_los[dx + (pl->contr->ns->mapx / 2)][dy + (pl->contr->ns->mapy / 2)])
3232 root 1.18 return 1;
3233     op = op->more;
3234     }
3235     return 0;
3236 elmex 1.1 }
3237    
3238     /* routine for both players and monsters. We call this when
3239     * there is a possibility for our action distrubing our hiding
3240     * place or invisiblity spell. Artefact invisiblity is not
3241     * effected by this. If we arent invisible to begin with, we
3242     * return 0.
3243     */
3244 root 1.18 int
3245     action_makes_visible (object *op)
3246     {
3247    
3248     if (op->invisible && QUERY_FLAG (op, FLAG_ALIVE))
3249     {
3250     if (QUERY_FLAG (op, FLAG_MAKE_INVIS))
3251     return 0;
3252    
3253     if (op->contr && op->contr->tmp_invis == 0)
3254     return 0;
3255 elmex 1.1
3256 root 1.18 /* If monsters, they should become visible */
3257     if (op->hide || !op->contr || (op->contr && op->contr->tmp_invis))
3258     {
3259     new_draw_info_format (NDI_UNIQUE, 0, op, "You become %s!", op->hide ? "unhidden" : "visible");
3260     return 1;
3261 root 1.11 }
3262 elmex 1.1 }
3263 root 1.18 return 0;
3264 elmex 1.1 }
3265    
3266     /* op_on_battleground - checks if the given object op (usually
3267     * a player) is standing on a valid battleground-tile,
3268     * function returns TRUE/FALSE. If true x, y returns the battleground
3269     * -exit-coord. (and if x, y not NULL)
3270     * 19 March 2005 - josh@woosworld.net modifed to check if the battleground also has slaying, maxhp, and maxsp set
3271     * and if those are all set and the player has a marker that matches the slaying send them to a different x, y
3272     * Default is to do the same as before, so only people wanting to have different points need worry about this
3273     */
3274 root 1.18 int
3275     op_on_battleground (object *op, int *x, int *y)
3276     {
3277 elmex 1.1 object *tmp;
3278 root 1.18
3279 elmex 1.1 /* A battleground-tile needs the following attributes to be valid:
3280     * is_floor 1 (has to be the FIRST floor beneath the player's feet),
3281     * name="battleground", no_pick 1, type=58 (type BATTLEGROUND)
3282     * and the exit-coordinates sp/hp must both be > 0.
3283     * => The intention here is to prevent abuse of the battleground-
3284     * feature (like pickable or hidden battleground tiles). */
3285 root 1.18 for (tmp = op->below; tmp != NULL; tmp = tmp->below)
3286     {
3287     if (QUERY_FLAG (tmp, FLAG_IS_FLOOR))
3288     {
3289     if (QUERY_FLAG (tmp, FLAG_NO_PICK) &&
3290     strcmp (tmp->name, "battleground") == 0 && tmp->type == BATTLEGROUND && EXIT_X (tmp) && EXIT_Y (tmp))
3291     {
3292     /*before we assign the exit, check if this is a teambattle */
3293     if (EXIT_ALT_X (tmp) && EXIT_ALT_Y (tmp) && EXIT_PATH (tmp))
3294     {
3295     object *invtmp;
3296    
3297     for (invtmp = op->inv; invtmp != NULL; invtmp = invtmp->below)
3298     {
3299     if (invtmp->type == FORCE && invtmp->slaying && !strcmp (EXIT_PATH (tmp), invtmp->slaying))
3300     {
3301     if (x != NULL && y != NULL)
3302     *x = EXIT_ALT_X (tmp), *y = EXIT_ALT_Y (tmp);
3303     return 1;
3304     }
3305     }
3306     }
3307     if (x != NULL && y != NULL)
3308     *x = EXIT_X (tmp), *y = EXIT_Y (tmp);
3309     return 1;
3310     }
3311     }
3312 elmex 1.1 }
3313     /* If we got here, did not find a battleground */
3314     return 0;
3315     }
3316    
3317     /*
3318     * When a dragon-player gains a new stage of evolution,
3319     * he gets some treasure
3320     *
3321     * attributes:
3322     * object *who the dragon player
3323     * int atnr the attack-number of the ability focus
3324     * int level ability level
3325     */
3326 root 1.18 void
3327     dragon_ability_gain (object *who, int atnr, int level)
3328     {
3329     treasurelist *trlist = NULL; /* treasurelist */
3330     treasure *tr; /* treasure */
3331     object *tmp, *skop; /* tmp. object */
3332     object *item; /* treasure object */
3333     char buf[MAX_BUF]; /* tmp. string buffer */
3334     int i = 0, j = 0;
3335    
3336     /* get the appropriate treasurelist */
3337     if (atnr == ATNR_FIRE)
3338 root 1.110 trlist = treasurelist::find ("dragon_ability_fire");
3339 root 1.18 else if (atnr == ATNR_COLD)
3340 root 1.110 trlist = treasurelist::find ("dragon_ability_cold");
3341 root 1.18 else if (atnr == ATNR_ELECTRICITY)
3342 root 1.110 trlist = treasurelist::find ("dragon_ability_elec");
3343 root 1.18 else if (atnr == ATNR_POISON)
3344 root 1.110 trlist = treasurelist::find ("dragon_ability_poison");
3345 root 1.18
3346     if (trlist == NULL || who->type != PLAYER)
3347     return;
3348    
3349     for (i = 0, tr = trlist->items; tr != NULL && i < level - 1; tr = tr->next, i++);
3350    
3351 elmex 1.82 if (!tr || !tr->item)
3352 root 1.18 {
3353     /* LOG(llevDebug, "-> no more treasure for %s\n", change_resist_msg[atnr]); */
3354     return;
3355 elmex 1.1 }
3356    
3357 root 1.18 /* everything seems okay - now bring on the gift: */
3358 root 1.149 item = tr->item;
3359 elmex 1.1
3360 root 1.18 if (item->type == SPELL)
3361     {
3362     if (check_spell_known (who, item->name))
3363 root 1.11 return;
3364 root 1.18
3365     new_draw_info_format (NDI_UNIQUE | NDI_BLUE, 0, who, "You gained the ability of %s", &item->name);
3366     do_learn_spell (who, item, 0);
3367     return;
3368 elmex 1.1 }
3369    
3370 root 1.18 /* grant direct spell */
3371     if (item->type == SPELLBOOK)
3372     {
3373     if (!item->inv)
3374     {
3375     LOG (llevDebug, "dragon_ability_gain: Broken spellbook %s\n", &item->name);
3376     return;
3377     }
3378     if (check_spell_known (who, item->inv->name))
3379     return;
3380     if (item->invisible)
3381     {
3382     new_draw_info_format (NDI_UNIQUE | NDI_BLUE, 0, who, "You gained the ability of %s", &item->inv->name);
3383     do_learn_spell (who, item->inv, 0);
3384     return;
3385 root 1.11 }
3386 root 1.18 }
3387     else if (item->type == SKILL_TOOL && item->invisible)
3388     {
3389     if (item->subtype == SK_CLAWING && (skop = find_skill_by_name (who, item->skill)) != NULL)
3390     {
3391    
3392     /* should this perhaps be (skop->attackyp & item->attacktype)!=item->attacktype ...
3393     * in this way, if the player is missing any of the attacktypes, he gets
3394     * them. As it is now, if the player has any that match the granted skill,
3395     * but not all of them, he gets nothing.
3396     */
3397     if (!(skop->attacktype & item->attacktype))
3398     {
3399     /* Give new attacktype */
3400     skop->attacktype |= item->attacktype;
3401    
3402     /* always add physical if there's none */
3403     skop->attacktype |= AT_PHYSICAL;
3404    
3405     if (item->msg != NULL)
3406     new_draw_info (NDI_UNIQUE | NDI_BLUE, 0, who, item->msg);
3407    
3408     /* Give player new face */
3409     if (item->animation_id)
3410     {
3411     who->face = skop->face;
3412     who->animation_id = item->animation_id;
3413     who->anim_speed = item->anim_speed;
3414     who->last_anim = 0;
3415     who->state = 0;
3416     animate_object (who, who->direction);
3417     }
3418     }
3419 root 1.11 }
3420 elmex 1.1 }
3421 root 1.18 else if (item->type == FORCE)
3422     {
3423     /* forces in the treasurelist can alter the player's stats */
3424     object *skin;
3425 elmex 1.1
3426 root 1.18 /* first get the dragon skin force */
3427 root 1.52 shstr_cmp dragon_skin_force ("dragon_skin_force");
3428 root 1.148 for (skin = who->inv; skin && !(skin->arch->archname == dragon_skin_force); skin = skin->below)
3429 root 1.52 ;
3430    
3431     if (!skin)
3432 root 1.18 return;
3433    
3434     /* adding new spellpath attunements */
3435     if (item->path_attuned > 0 && !(skin->path_attuned & item->path_attuned))
3436     {
3437     skin->path_attuned |= item->path_attuned; /* add attunement to skin */
3438    
3439     /* print message */
3440     sprintf (buf, "You feel attuned to ");
3441     for (i = 0, j = 0; i < NRSPELLPATHS; i++)
3442     {
3443     if (item->path_attuned & (1 << i))
3444     {
3445     if (j)
3446     strcat (buf, " and ");
3447     else
3448     j = 1;
3449     strcat (buf, spellpathnames[i]);
3450     }
3451     }
3452     strcat (buf, ".");
3453     new_draw_info (NDI_UNIQUE | NDI_BLUE, 0, who, buf);
3454     }
3455    
3456     /* evtl. adding flags: */
3457     if (QUERY_FLAG (item, FLAG_XRAYS))
3458     SET_FLAG (skin, FLAG_XRAYS);
3459     if (QUERY_FLAG (item, FLAG_STEALTH))
3460     SET_FLAG (skin, FLAG_STEALTH);
3461     if (QUERY_FLAG (item, FLAG_SEE_IN_DARK))
3462     SET_FLAG (skin, FLAG_SEE_IN_DARK);
3463    
3464     /* print message if there is one */
3465     if (item->msg != NULL)
3466     new_draw_info (NDI_UNIQUE | NDI_BLUE, 0, who, item->msg);
3467     }
3468     else
3469     {
3470     /* generate misc. treasure */
3471     tmp = arch_to_object (tr->item);
3472     new_draw_info_format (NDI_UNIQUE | NDI_BLUE, 0, who, "You gained %s", query_short_name (tmp));
3473     tmp = insert_ob_in_ob (tmp, who);
3474     if (who->type == PLAYER)
3475     esrv_send_item (who, tmp);
3476 elmex 1.1 }
3477     }
3478    
3479     /**
3480     * Unready an object for a player. This function does nothing if the object was
3481     * not readied.
3482     */
3483 root 1.18 void
3484     player_unready_range_ob (player *pl, object *ob)
3485     {
3486 root 1.119 if (pl->ob->current_weapon == ob)
3487     pl->ob->current_weapon = 0;
3488    
3489 root 1.118 if (pl->combat_ob == ob)
3490 root 1.119 pl->combat_ob = 0;
3491 root 1.118
3492     if (pl->ranged_ob == ob)
3493 root 1.119 pl->ranged_ob = 0;
3494 elmex 1.1 }
3495 root 1.101
3496     sint8
3497     player::visibility_at (maptile *map, int x, int y) const
3498     {
3499     if (!ns)
3500     return 0;
3501    
3502     int dx, dy;
3503     if (!adjacent_map (map, ns->current_map, &dx, &dy))
3504     return 0;
3505    
3506     x += dx - ns->current_x + ns->mapx / 2;
3507     y += dy - ns->current_y + ns->mapy / 2;
3508    
3509     if (!IN_RANGE_EXC (x, 0, ns->mapx) || !IN_RANGE_EXC (y, 0, ns->mapy))
3510     return 0;
3511    
3512     return 100 - blocked_los [x][y];
3513     }