ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/player.C
Revision: 1.82
Committed: Wed Jan 3 02:30:52 2007 UTC (17 years, 5 months ago) by elmex
Content type: text/plain
Branch: MAIN
Changes since 1.81: +1 -1 lines
Log Message:
implemented proper support for empty treasures, which
sadly occur in empty treasure lists. fixing treasurelists
to have no entries at all would be even more complicated,
but even when this is fixed, the current changes only make the
server more crash robust to bad treasures.
Also removed the 'NONE' specialcase for treasure lists. Developers
should use 'none' instead now.

File Contents

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