ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/player.C
Revision: 1.107
Committed: Wed Mar 14 04:12:29 2007 UTC (17 years, 2 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.106: +21 -21 lines
Log Message:
- rewrote more face handling code
- automatically send smooth faces, as the client will need them anyways
  and it makes little sense to wait for the client to axk for it. of course,
  gcfclient suffers from weird ordering problems again.
- UP_OBJ_FACE was often abused in situations where other things changed,
  updated lots of spaces, probably more to be done.
- update_smooth became so small that inlining it actually clarified
  the code. similar for update_space, which is not inlined for other reasons.
- faces were not initialised properly
- add versioncheck for face data
- rewrite invisibility handling a bit: god finger etc. now makes you blink,
  blinking routine has changed to be less annoying and more useful while
  still indicating invisibleness.

File Contents

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