ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/c_object.C
(Generate patch)

Comparing deliantra/server/server/c_object.C (file contents):
Revision 1.64 by root, Sun Apr 20 00:44:13 2008 UTC vs.
Revision 1.119 by root, Sat Apr 10 04:54:09 2010 UTC

1/* 1/*
2 * This file is part of Deliantra, the Roguelike Realtime MMORPG. 2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 * 3 *
4 * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Deliantra team 4 * Copyright (©) 2005,2006,2007,2008,2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team 5 * Copyright (©) 2002 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992,2007 Frank Tore Johansen 6 * Copyright (©) 1992 Frank Tore Johansen
7 * 7 *
8 * Deliantra is free software: you can redistribute it and/or modify 8 * Deliantra is free software: you can redistribute it and/or modify it under
9 * it under the terms of the GNU General Public License as published by 9 * the terms of the Affero GNU General Public License as published by the
10 * the Free Software Foundation, either version 3 of the License, or 10 * Free Software Foundation, either version 3 of the License, or (at your
11 * (at your option) any later version. 11 * option) any later version.
12 * 12 *
13 * This program is distributed in the hope that it will be useful, 13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details. 16 * GNU General Public License for more details.
17 * 17 *
18 * You should have received a copy of the GNU General Public License 18 * You should have received a copy of the Affero GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 * and the GNU General Public License along with this program. If not, see
20 * <http://www.gnu.org/licenses/>.
20 * 21 *
21 * The authors can be reached via e-mail to <support@deliantra.net> 22 * The authors can be reached via e-mail to <support@deliantra.net>
22 */ 23 */
23 24
24/* 25/*
25 * Object (handling) commands 26 * Object (handling) commands
26 */ 27 */
27 28
28#include <global.h> 29#include <global.h>
29#include <loader.h>
30#include <skills.h> 30#include <skills.h>
31#include <sproto.h> 31#include <sproto.h>
32#include <living.h> 32#include <living.h>
33#include <math.h>
34 33
35/* 34/*
36 * Object id parsing functions 35 * Object id parsing functions
37 */ 36 */
38 37
91find_best_object_match (object *pl, const char *params) 90find_best_object_match (object *pl, const char *params)
92{ 91{
93 return find_best_apply_object_match (pl, params, AP_TOGGLE); 92 return find_best_apply_object_match (pl, params, AP_TOGGLE);
94} 93}
95 94
95static bool
96can_split (object *pl, object *&op, sint32 nrof)
97{
98 if (object *tmp = op->split (nrof ? nrof : op->number_of ()))
99 {
100 op = tmp;
101 return true;
102 }
103 else
104 {
105 if (op->nrof > 1)
106 new_draw_info_format (NDI_UNIQUE, 0, pl, "There are only %d %s.", op->nrof, &op->name_pl);
107 else
108 new_draw_info_format (NDI_UNIQUE, 0, pl, "There is only one %s.", &op->name);
109
110 return false;
111 }
112}
113
96int 114int
97command_uskill (object *pl, char *params) 115command_uskill (object *pl, char *params)
98{ 116{
99 if (!params) 117 if (!params)
100 { 118 {
114 { 132 {
115 new_draw_info (NDI_UNIQUE, 0, pl, "Usage: ready_skill <skill name>"); 133 new_draw_info (NDI_UNIQUE, 0, pl, "Usage: ready_skill <skill name>");
116 return 0; 134 return 0;
117 } 135 }
118 136
119 skill = find_skill_by_name (pl, params); 137 skill = find_skill_by_name_fuzzy (pl, params);
120 138
121 if (!skill) 139 if (!skill)
122 { 140 {
123 new_draw_info_format (NDI_UNIQUE, 0, pl, "You have no knowledge of the skill %s", params); 141 new_draw_info_format (NDI_UNIQUE, 0, pl, "You have no knowledge of the %s skill.", params);
124 return 0; 142 return 0;
125 } 143 }
126 144
127 pl->change_skill (0); 145 pl->apply (skill);
128 apply_special (pl, skill, AP_APPLY);
129 return 1; 146 return 1;
130}
131
132/* These functions (command_search, command_disarm) are really just wrappers for
133 * things like 'use_skill ...'). In fact, they should really be obsoleted
134 * and replaced with those.
135 */
136int
137command_search (object *op, char *params)
138{
139 return use_skill (op, skill_names[SK_FIND_TRAPS]);
140}
141
142int
143command_disarm (object *op, char *params)
144{
145 return use_skill (op, skill_names[SK_DISARM_TRAPS]);
146} 147}
147 148
148/* A little special because we do want to pass the full params along 149/* A little special because we do want to pass the full params along
149 * as it includes the object to throw. 150 * as it includes the object to throw.
150 */ 151 */
152command_throw (object *op, char *params) 153command_throw (object *op, char *params)
153{ 154{
154 if (object *skop = find_skill_by_name (op, skill_names[SK_THROWING])) 155 if (object *skop = find_skill_by_name (op, skill_names[SK_THROWING]))
155 return do_skill (op, op, skop, op->facing, params); 156 return do_skill (op, op, skop, op->facing, params);
156 else 157 else
157 new_draw_info (NDI_UNIQUE, 0, op, "You have no knowledge of the skill throwing."); 158 new_draw_info (NDI_UNIQUE, 0, op, "You have no knowledge of the throwing skill.");
158 159
159 return 0; 160 return 0;
160} 161}
161 162
162int 163int
188 189
189 while (*params == ' ') 190 while (*params == ' ')
190 params++; 191 params++;
191 192
192 if (object *inv = find_best_apply_object_match (op, params, aflag)) 193 if (object *inv = find_best_apply_object_match (op, params, aflag))
193 player_apply (op, inv, aflag, 0); 194 op->apply (inv, aflag);
194 else 195 else
195 new_draw_info_format (NDI_UNIQUE, 0, op, "Could not find any match to the %s.", params); 196 op->failmsgf ("Could not find any match to the %s.", params);
196 } 197 }
197 198
198 return 0; 199 return 0;
199} 200}
200 201
208 * not need to use split_ob and stuff. 209 * not need to use split_ob and stuff.
209 */ 210 */
210int 211int
211sack_can_hold (object *pl, object *sack, object *op, uint32 nrof) 212sack_can_hold (object *pl, object *sack, object *op, uint32 nrof)
212{ 213{
213
214 if (!QUERY_FLAG (sack, FLAG_APPLIED)) 214 if (!QUERY_FLAG (sack, FLAG_APPLIED))
215 { 215 {
216 new_draw_info_format (NDI_UNIQUE, 0, pl, "The %s is not active.", query_name (sack)); 216 new_draw_info_format (NDI_UNIQUE, 0, pl, "The %s is not active.", query_name (sack));
217 return 0; 217 return 0;
218 } 218 }
219
219 if (sack == op) 220 if (sack == op)
220 { 221 {
221 new_draw_info_format (NDI_UNIQUE, 0, pl, "You can't put the %s into itself.", query_name (sack)); 222 new_draw_info_format (NDI_UNIQUE, 0, pl, "You can't put the %s into itself.", query_name (sack));
222 return 0; 223 return 0;
223 } 224 }
225
224 if (sack->race && (sack->race != op->race || op->type == CONTAINER || (sack->stats.food && sack->stats.food != op->type))) 226 if (sack->race && (sack->race != op->race || op->type == CONTAINER || (sack->stats.food && sack->stats.food != op->type)))
225 { 227 {
226 new_draw_info_format (NDI_UNIQUE, 0, pl, "You can put only %s into the %s.", &sack->race, query_name (sack)); 228 new_draw_info_format (NDI_UNIQUE, 0, pl, "You can only put objects of type '%s' into the %s.", &sack->race, query_name (sack));
227 return 0; 229 return 0;
228 } 230 }
231
229 if (op->type == SPECIAL_KEY && sack->slaying && op->slaying) 232 if (op->type == SPECIAL_KEY && sack->slaying && op->slaying)
230 { 233 {
231 new_draw_info_format (NDI_UNIQUE, 0, pl, "You can't put the key into %s.", query_name (sack)); 234 new_draw_info_format (NDI_UNIQUE, 0, pl, "You can't put the key into %s.", query_name (sack));
232 return 0; 235 return 0;
233 } 236 }
237
234 if (sack->weight_limit && (sint32) (sack->carrying + (nrof ? nrof : 1) * 238 if (sack->weight_limit && (sint32) (sack->carrying + (nrof ? nrof : 1) *
235 (op->weight + (op->type == CONTAINER ? (op->carrying * op->stats.Str) : 0)) 239 (op->weight + (op->type == CONTAINER ? (op->carrying * op->stats.Str) : 0))
236 * (100 - sack->stats.Str) / 100) > sack->weight_limit) 240 * (100 - sack->stats.Str) / 100) > sack->weight_limit)
237 { 241 {
238 new_draw_info_format (NDI_UNIQUE, 0, pl, "That won't fit in the %s!", query_name (sack)); 242 new_draw_info_format (NDI_UNIQUE, 0, pl, "That won't fit in the %s!", query_name (sack));
239 return 0; 243 return 0;
240 } 244 }
245
241 /* All other checks pass, must be OK */ 246 /* All other checks pass, must be OK */
242 return 1; 247 return 1;
243} 248}
244 249
245/* Pick up commands follow */ 250/* Pick up commands follow */
252static void 257static void
253pick_up_object (object *pl, object *op, object *tmp, int nrof) 258pick_up_object (object *pl, object *op, object *tmp, int nrof)
254{ 259{
255 object *env = tmp->env; 260 object *env = tmp->env;
256 uint32 weight, effective_weight_limit; 261 uint32 weight, effective_weight_limit;
257 int tmp_nrof = tmp->nrof ? tmp->nrof : 1; 262 int tmp_nrof = tmp->number_of ();
258 263
259 /* IF the player is flying & trying to take the item out of a container 264 /* IF the player is flying & trying to take the item out of a container
260 * that is in his inventory, let him. tmp->env points to the container 265 * that is in his inventory, let him. tmp->env points to the container
261 * (sack, luggage, etc), tmp->env->env then points to the player (nested 266 * (sack, luggage, etc), tmp->env->env then points to the player (nested
262 * containers not allowed as of now) 267 * containers not allowed as of now)
263 */ 268 */
264 if ((pl->move_type & MOVE_FLYING) && !QUERY_FLAG (pl, FLAG_WIZ) && tmp->in_player () != pl) 269 if ((pl->move_type & MOVE_FLYING) && !QUERY_FLAG (pl, FLAG_WIZ) && tmp->in_player () != pl)
265 { 270 {
266 new_draw_info (NDI_UNIQUE, 0, pl, "You are levitating, you can't reach the ground!"); 271 pl->failmsg ("You are levitating, you can't reach the ground! "
272 "H<You have to stop levitating first, if you can, either by using your levitation skill, "
273 "or waiting till the levitation effect wears off.>");
267 return; 274 return;
268 } 275 }
269 276
270 if (QUERY_FLAG (tmp, FLAG_NO_DROP)) 277 if (QUERY_FLAG (tmp, FLAG_NO_DROP))
271 return; 278 return;
272 279
273 if (nrof > tmp_nrof || nrof == 0) 280 if (nrof > tmp_nrof || nrof <= 0)
274 nrof = tmp_nrof; 281 nrof = tmp_nrof;
275 282
276 /* Figure out how much weight this object will add to the player */ 283 /* Figure out how much weight this object will add to the player */
277 weight = tmp->weight * nrof; 284 weight = tmp->weight * nrof;
278 if (tmp->inv) 285 if (tmp->inv)
284 { 291 {
285 new_draw_info (0, 0, pl, "That item is too heavy for you to pick up."); 292 new_draw_info (0, 0, pl, "That item is too heavy for you to pick up.");
286 return; 293 return;
287 } 294 }
288 295
289 if (nrof != tmp_nrof) 296 if (!can_split (pl, tmp, nrof))
290 {
291 object *tmp2 = tmp;
292
293 tmp = get_split_ob (tmp, nrof);
294 if (!tmp)
295 {
296 new_draw_info (NDI_UNIQUE, 0, pl, errmsg);
297 return; 297 return;
298 }
299
300 /* Tell the client what happened to the rest of objects */
301 if (pl->contr)
302 if (tmp2->destroyed ())
303 esrv_del_item (pl->contr, tmp2->count);
304 else
305 esrv_update_item (UPD_NROF, pl, tmp2);
306 }
307 else
308 {
309 /* If the object is in a container, send a delete to the client.
310 * - we are moving all the items from the container to elsewhere,
311 * so it needs to be deleted.
312 */
313 if (!QUERY_FLAG (tmp, FLAG_REMOVED))
314 {
315 if (tmp->env && pl->type == PLAYER)
316 esrv_del_item (pl->contr, tmp->count);
317
318 tmp->remove (); /* Unlink it */
319 }
320 }
321 298
322 if (QUERY_FLAG (tmp, FLAG_UNPAID)) 299 if (QUERY_FLAG (tmp, FLAG_UNPAID))
300 {
301 tmp->flag.reset (FLAG_UNPAID);
323 new_draw_info_format (NDI_UNIQUE, 0, pl, "%s will cost you %s.", query_name (tmp), query_cost_string (tmp, pl, F_BUY | F_SHOP)); 302 new_draw_info_format (NDI_UNIQUE, 0, pl, "%s will cost you %s.", query_name (tmp), query_cost_string (tmp, pl, F_BUY | F_SHOP));
303 tmp->flag.set (FLAG_UNPAID);
304 }
324 else 305 else
325 new_draw_info_format (NDI_UNIQUE, 0, pl, "You pick up the %s.", query_name (tmp)); 306 new_draw_info_format (NDI_UNIQUE, 0, pl, "You pick up the %s.", query_name (tmp));
326 307
327 tmp = insert_ob_in_ob (tmp, op); 308 op->insert (tmp);
328
329 /* All the stuff below deals with client/server code, and is only
330 * usable by players
331 */
332 if (pl->contr)
333 {
334 esrv_send_item (pl, tmp);
335
336 /* These are needed to update the weight for the container we
337 * are putting the object in.
338 */
339 if (op != pl)
340 {
341 esrv_update_item (UPD_WEIGHT, pl, op);
342 esrv_send_item (pl, pl);
343 }
344
345 /* Update the container the object was in */
346 if (env && env != pl && env != op)
347 esrv_update_item (UPD_WEIGHT, pl, env);
348 }
349} 309}
350 310
351/* modified slightly to allow monsters use this -b.t. 5-31-95 */ 311/* modified slightly to allow monsters use this -b.t. 5-31-95 */
352void 312void
353pick_up (object *op, object *alt) 313pick_up (object *op, object *alt)
399 count = tmp->nrof; 359 count = tmp->nrof;
400 360
401 /* container is open, so use it */ 361 /* container is open, so use it */
402 if (tmp->flag [FLAG_STARTEQUIP]) 362 if (tmp->flag [FLAG_STARTEQUIP])
403 alt = op; 363 alt = op;
404 else if (op->container) 364 else if ((alt = op->container_ ()))
405 { 365 {
406 alt = op->container;
407 if (alt != tmp->env && !sack_can_hold (op, alt, tmp, count)) 366 if (alt != tmp->env && !sack_can_hold (op, alt, tmp, count))
408 goto leave; 367 goto leave;
409 } 368 }
410 else 369 else
411 { /* non container pickup */ 370 { /* non container pickup */
465int 424int
466command_take (object *op, char *params) 425command_take (object *op, char *params)
467{ 426{
468 object *tmp, *next; 427 object *tmp, *next;
469 428
470 if (op->container) 429 if (op->container_ ())
471 tmp = op->container->inv; 430 tmp = op->container_ ()->inv;
472 else 431 else
473 { 432 {
474 tmp = op->above; 433 tmp = op->above;
475 if (tmp) 434 if (tmp)
476 while (tmp->above) 435 while (tmp->above)
488 447
489 /* Makes processing easier */ 448 /* Makes processing easier */
490 if (params && *params == '\0') 449 if (params && *params == '\0')
491 params = 0; 450 params = 0;
492 451
493 int cnt = MAX_ITEM_PER_DROP; 452 int cnt = MAX_ITEM_PER_ACTION;
494 453
495 while (tmp) 454 while (tmp)
496 { 455 {
497 next = tmp->below; 456 next = tmp->below;
498 457
506 * but that probably will make it more difficult to read, and 465 * but that probably will make it more difficult to read, and
507 * not make it any more efficient 466 * not make it any more efficient
508 */ 467 */
509 if (params && item_matched_string (op, tmp, params)) 468 if (params && item_matched_string (op, tmp, params))
510 { 469 {
470 if (--cnt < 0) break;
511 pick_up (op, tmp); 471 pick_up (op, tmp);
512 if (--cnt <= 0) break;
513 } 472 }
514 else if (can_pick (op, tmp) && !params) 473 else if (can_pick (op, tmp) && !params)
515 { 474 {
475 if (--cnt < 0) break;
516 pick_up (op, tmp); 476 pick_up (op, tmp);
517 break; 477 break;
518 } 478 }
519 479
520 tmp = next; 480 tmp = next;
521 } 481 }
522 482
523 if (cnt <= 0) 483 if (cnt < 0)
524 { 484 {
525 op->failmsg ("Couldn't pick up so many items at once."); 485 op->failmsg ("Couldn't pick up so many items at once.");
526 return 0; 486 return 0;
527 } 487 }
528 488
540 } 500 }
541 501
542 return 0; 502 return 0;
543} 503}
544 504
545
546/* 505/*
547 * This function was part of drop, now is own function. 506 * This function was part of drop, now is own function.
548 * Player 'op' tries to put object 'tmp' into sack 'sack', 507 * Player 'op' tries to put object 'tmp' into sack 'sack',
549 * if nrof is non zero, then nrof objects is tried to put into sack. 508 * if nrof is non zero, then nrof objects is tried to put into sack.
509 *
550 * Note that the 'sack' in question can now be a transport, 510 * Note that the 'sack' in question can now be a transport,
551 * so this function isn't named very good anymore. 511 * so this function isn't named very good anymore.
552 */ 512 */
553void 513void
554put_object_in_sack (object *op, object *sack, object *tmp, uint32 nrof) 514put_object_in_sack (object *op, object *sack, object *tmp, uint32 nrof)
557 char buf[MAX_BUF]; 517 char buf[MAX_BUF];
558 518
559 if (sack == tmp) 519 if (sack == tmp)
560 return; /* Can't put an object in itself */ 520 return; /* Can't put an object in itself */
561 521
562 if (QUERY_FLAG (tmp, FLAG_STARTEQUIP)) 522 if (QUERY_FLAG (tmp, FLAG_STARTEQUIP) || QUERY_FLAG (tmp, FLAG_NO_DROP))
563 { 523 {
564 new_draw_info_format (NDI_UNIQUE, 0, op, "You cannot put the %s in the %s.", query_name (tmp), query_name (sack)); 524 new_draw_info_format (NDI_UNIQUE, 0, op, "You cannot put the %s in the %s.", query_name (tmp), query_name (sack));
565 return; 525 return;
566 } 526 }
567 527
568 if (tmp->type == CONTAINER && tmp->inv) 528 if (tmp->type == CONTAINER && tmp->inv)
569 { 529 {
570
571 /* Eneq(@csd.uu.se): If the object to be dropped is a container 530 /* Eneq(@csd.uu.se): If the object to be dropped is a container
572 * we instead move the contents of that container into the active 531 * we instead move the contents of that container into the active
573 * container, this is only done if the object has something in it. 532 * container, this is only done if the object has something in it.
574 */ 533 */
575 sack2 = tmp; 534 sack2 = tmp;
577 536
578 for (tmp2 = tmp->inv; tmp2; tmp2 = tmp) 537 for (tmp2 = tmp->inv; tmp2; tmp2 = tmp)
579 { 538 {
580 tmp = tmp2->below; 539 tmp = tmp2->below;
581 540
582 if ((sack->type == CONTAINER && sack_can_hold (op, op->container, tmp2, tmp2->nrof))) 541 if ((sack->type == CONTAINER && sack_can_hold (op, op->container_ (), tmp2, tmp2->nrof)))
583 {
584 put_object_in_sack (op, sack, tmp2, 0); 542 put_object_in_sack (op, sack, tmp2, 0);
585 }
586 else 543 else
587 { 544 {
588 sprintf (buf, "Your %s fills up.", query_name (sack)); 545 sprintf (buf, "Your %s fills up.", query_name (sack));
589 new_draw_info (NDI_UNIQUE, 0, op, buf); 546 new_draw_info (NDI_UNIQUE, 0, op, buf);
590 break; 547 break;
591 } 548 }
592 } 549 }
593 550
594 esrv_update_item (UPD_WEIGHT, op, sack2);
595 return; 551 return;
596 } 552 }
597 553
598 /* Don't worry about this for containers - our caller should have 554 /* Don't worry about this for containers - our caller should have
599 * already checked this. 555 * already checked this.
600 */ 556 */
601 if ((sack->type == CONTAINER) && !sack_can_hold (op, sack, tmp, (nrof ? nrof : tmp->nrof))) 557 if ((sack->type == CONTAINER) && !sack_can_hold (op, sack, tmp, (nrof ? nrof : tmp->nrof)))
602 return; 558 return;
603 559
604 if (QUERY_FLAG (tmp, FLAG_APPLIED)) 560 if (QUERY_FLAG (tmp, FLAG_APPLIED))
605 if (apply_special (op, tmp, AP_UNAPPLY | AP_NO_MERGE)) 561 if (!op->apply (tmp, AP_UNAPPLY | AP_NO_MERGE))
606 return; 562 return;
607 563
608 /* we want to put some portion of the item into the container */ 564 /* we want to put some portion of the item into the container */
609 if (nrof && tmp->nrof != nrof) 565 if (!can_split (op, tmp, nrof))
610 {
611 object *tmp2 = tmp;
612
613 tmp = get_split_ob (tmp, nrof);
614
615 if (!tmp)
616 {
617 new_draw_info (NDI_UNIQUE, 0, op, errmsg);
618 return; 566 return;
619 }
620 /* Tell a client what happened other objects */
621 if (tmp2->destroyed ())
622 esrv_del_item (op->contr, tmp2->count);
623 else /* this can proably be replaced with an update */
624 esrv_send_item (op, tmp2);
625 }
626 else
627 tmp->remove ();
628 567
629 new_draw_info_format (NDI_UNIQUE, 0, op, "You put the %s in %s.", query_name (tmp), query_name (sack)); 568 new_draw_info_format (NDI_UNIQUE, 0, op, "You put the %s in %s.", query_name (tmp), query_name (sack));
630 tmp2 = insert_ob_in_ob (tmp, sack); 569 sack->insert (tmp);
570}
631 571
632 // elmex: 2007-11-26: removed update_stats and replaced 572/* In contrast to drop_object (op, tmp, nrof) above this function takes the
633 // it by update_after_inventory_change () in the caller 573 * already split off object, and feeds it to the event handlers and does
634 // of this function 574 * other magic with it.
575 *
576 * <droppper> is the object that dropped this object and <obj> is the
577 * object that was dropped.
578 *
579 * Make sure to check what happened with <obj> after this function returns!
580 * Otherwise you may leak this object.
581 */
582void
583drop_object (object *dropper, object *obj)
584{
585 if (INVOKE_OBJECT (DROP, obj, ARG_OBJECT (dropper)))
586 return;
587
588 if (obj->destroyed () || obj->is_inserted ())
589 return;
635 590
636 /* If an object merged (and thus, different object), we need to 591 if (QUERY_FLAG (obj, FLAG_STARTEQUIP))
637 * delete the original. 592 {
593 dropper->statusmsg (format ("You drop the %s.", query_name (obj)));
594 dropper->statusmsg ("The god who lent it to you retrieves it.");
595
596 obj->destroy ();
597 dropper->update_stats ();
598 return;
599 }
600
601 for (object *floor = GET_MAP_OB (dropper->map, dropper->x, dropper->y);
602 floor;
603 floor = floor->above)
604 if (INVOKE_OBJECT (DROP_ON, floor, ARG_OBJECT (obj), ARG_OBJECT (dropper)))
605 return;
606
607 if (obj->destroyed () || obj->is_inserted ())
608 return;
609
610 if (dropper->is_in_shop () && !QUERY_FLAG (obj, FLAG_UNPAID) && obj->type != MONEY)
611 if (!sell_item (obj, dropper))
612 return;
613
614 if (!obj->can_drop_at (dropper->map, dropper->x, dropper->y, dropper))
615 return;
616
617 /* If nothing special happened with this object, the default action is to
618 * insert it below the dropper:
638 */ 619 */
639 if (tmp2 != tmp)
640 esrv_del_item (op->contr, tmp->count);
641 620
642 esrv_send_item (op, tmp2); 621 obj->x = dropper->x;
622 obj->y = dropper->y;
643 623
644 /* update the sacks weight */ 624 insert_ob_in_map (obj, dropper->map, dropper, INS_BELOW_ORIGINATOR);
645 esrv_update_item (UPD_WEIGHT, op, sack);
646} 625}
647 626
648/* 627/*
649 * This function was part of drop, now is own function. 628 * This function was part of drop, now is own function.
650 * Player 'op' tries to drop object 'tmp', if tmp is non zero, then 629 * Player 'op' tries to drop object 'tmp', if tmp is non zero, then
651 * nrof objects is tried to dropped. 630 * nrof objects are tried to drop.
652 * This is used when dropping objects onto the floor. 631 * This is used when dropping objects onto the floor.
653 */ 632 */
654void 633void
655drop_object (object *op, object *tmp, uint32 nrof) 634drop_object (object *op, object *tmp, uint32 nrof)
656{ 635{
657 object *floor;
658
659 if (QUERY_FLAG (tmp, FLAG_NO_DROP)) 636 if (QUERY_FLAG (tmp, FLAG_NO_DROP))
660 return; 637 return;
661 638
662 if (QUERY_FLAG (tmp, FLAG_APPLIED)) 639 if (QUERY_FLAG (tmp, FLAG_APPLIED))
663 if (apply_special (op, tmp, AP_UNAPPLY | AP_NO_MERGE)) 640 if (!op->apply (tmp, AP_UNAPPLY | AP_NO_MERGE))
664 return; /* can't unapply it */ 641 return; /* can't unapply it */
665
666 //fprintf (stderr, "ui, on space is %ld\n", op->ms ().volume ());//D
667 642
668 /* We are only dropping some of the items. We split the current object 643 /* We are only dropping some of the items. We split the current object
669 * off 644 * off
670 */ 645 */
671 if (nrof && tmp->nrof != nrof) 646 if (!can_split (op, tmp, nrof))
672 {
673 object *tmp2 = tmp;
674
675 tmp = get_split_ob (tmp, nrof);
676 if (!tmp)
677 {
678 new_draw_info (NDI_UNIQUE, 0, op, errmsg);
679 return;
680 }
681 /* Tell a client what happened rest of objects. tmp2 is now the
682 * original object
683 */
684 if (op->type == PLAYER)
685 {
686 if (tmp2->destroyed ())
687 esrv_del_item (op->contr, tmp2->count);
688 else
689 esrv_send_item (op, tmp2);
690 }
691 }
692 else
693 tmp->remove ();
694
695 if (INVOKE_OBJECT (DROP, tmp, ARG_OBJECT (op)))
696 return; 647 return;
697 648
698 if (QUERY_FLAG (tmp, FLAG_STARTEQUIP)) 649 drop_object (op, tmp);
699 {
700 op->statusmsg (format ("You drop the %s.", query_name (tmp)));
701 op->statusmsg ("The gods who lent it to you retrieves it.");
702 650
703 if (op->type == PLAYER) 651 if (!tmp->destroyed () && !tmp->is_inserted ())
704 esrv_del_item (op->contr, tmp->count);
705
706 tmp->destroy ();
707 op->update_stats ();
708 return;
709 } 652 {
710 653 // if nothing happened with the object we give it back
711 if (op->type == PLAYER) 654 op->insert (tmp);
712 esrv_del_item (op->contr, tmp->count);
713
714 /* Call this before we update the various windows/players. At least
715 * that we, we know the weight is correct.
716 */
717 // 2007-11-26: moved op->update_stats away and calling it later after
718 // all items of a drop command have been processed.
719
720 for (floor = GET_MAP_OB (op->map, op->x, op->y); floor; floor = floor->above)
721 if (INVOKE_OBJECT (DROP_ON, floor, ARG_OBJECT (tmp), ARG_OBJECT (op)))
722 return;
723
724 if (is_in_shop (op) && !QUERY_FLAG (tmp, FLAG_UNPAID) && tmp->type != MONEY)
725 sell_item (tmp, op);
726
727 tmp->x = op->x;
728 tmp->y = op->y;
729
730 insert_ob_in_map (tmp, op->map, op, INS_BELOW_ORIGINATOR);
731}
732
733void update_after_inventory_change (object *op)
734{
735 /* Call this before we update the various windows/players. At least
736 * that we, we know the weight is correct.
737 */
738 op->update_stats ();
739
740 // elmex: kept this for now, i have no idea what happens when i remove it:
741 if (op->type == PLAYER)
742 {
743 /* Need to update the weight for the player */
744 esrv_send_item (op, op);
745 op->contr->ns->floorbox_update ();
746 } 655 }
747} 656}
748 657
749void 658void
750drop (object *op, object *tmp) 659drop (object *op, object *tmp)
760 if (tmp->env && tmp->env->type != PLAYER) 669 if (tmp->env && tmp->env->type != PLAYER)
761 { 670 {
762 /* Just toss the object - probably shouldn't be hanging 671 /* Just toss the object - probably shouldn't be hanging
763 * around anyways 672 * around anyways
764 */ 673 */
765 tmp->remove ();
766 tmp->destroy (); 674 tmp->destroy ();
767 return; 675 return;
768 } 676 }
769 else 677 else
770 {
771 while (tmp != NULL && tmp->invisible) 678 while (tmp && tmp->invisible)
772 tmp = tmp->below; 679 tmp = tmp->below;
773 }
774 } 680 }
775 681
776 if (tmp == NULL) 682 if (!tmp)
777 { 683 {
778 new_draw_info (NDI_UNIQUE, 0, op, "You don't have anything to drop."); 684 new_draw_info (NDI_UNIQUE, 0, op, "You don't have anything to drop.");
779 return; 685 return;
780 } 686 }
687
781 if (QUERY_FLAG (tmp, FLAG_INV_LOCKED)) 688 if (QUERY_FLAG (tmp, FLAG_INV_LOCKED))
782 { 689 {
783 new_draw_info (NDI_UNIQUE, 0, op, "This item is locked"); 690 new_draw_info (NDI_UNIQUE, 0, op, "This item is locked");
784 return; 691 return;
785 } 692 }
693
786 if (QUERY_FLAG (tmp, FLAG_NO_DROP)) 694 if (QUERY_FLAG (tmp, FLAG_NO_DROP))
787 { 695 {
788#if 0 696#if 0
789 /* Eneq(@csd.uu.se): Objects with NO_DROP defined can't be dropped. */ 697 /* Eneq(@csd.uu.se): Objects with NO_DROP defined can't be dropped. */
790 new_draw_info (NDI_UNIQUE, 0, op, "This item can't be dropped."); 698 new_draw_info (NDI_UNIQUE, 0, op, "This item can't be dropped.");
793 } 701 }
794 702
795 if (op->type == PLAYER && op->contr->last_used == tmp) 703 if (op->type == PLAYER && op->contr->last_used == tmp)
796 op->contr->last_used = tmp->below ? tmp->below 704 op->contr->last_used = tmp->below ? tmp->below
797 : tmp->above ? tmp->above 705 : tmp->above ? tmp->above
798 : 0; 706 : (object *)0;
799 707
800 if (op->container) 708 if (op->container_ ())
801 { 709 {
802 if (op->type == PLAYER) 710 if (op->type == PLAYER)
803 put_object_in_sack (op, op->container, tmp, op->contr->count); 711 put_object_in_sack (op, op->container_ (), tmp, op->contr->count);
804 else 712 else
805 put_object_in_sack (op, op->container, tmp, 0); 713 put_object_in_sack (op, op->container_ (), tmp, 0);
806 } 714 }
807 else 715 else
808 { 716 {
809 if (op->type == PLAYER) 717 if (op->type == PLAYER)
810 drop_object (op, tmp, op->contr->count); 718 drop_object (op, tmp, op->contr->count);
814 722
815 if (op->type == PLAYER) 723 if (op->type == PLAYER)
816 op->contr->count = 0; 724 op->contr->count = 0;
817} 725}
818 726
819
820
821/* Command will drop all items that have not been locked */ 727/* Command will drop all items that have not been locked */
822int 728int
823command_dropall (object *op, char *params) 729command_dropall (object *op, char *params)
824{ 730{
825 731
826 object *curinv, *nextinv;
827
828 if (op->inv == NULL) 732 if (op->inv == NULL)
829 { 733 {
830 new_draw_info (NDI_UNIQUE, 0, op, "Nothing to drop!"); 734 new_draw_info (NDI_UNIQUE, 0, op, "Nothing to drop!");
831 return 0; 735 return 0;
832 } 736 }
833 737
834 curinv = op->inv; 738 object *curinv = op->inv;
739 object *nextinv;
835 740
836 /* 741 /*
837 This is the default. Drops everything not locked or considered 742 This is the default. Drops everything not locked or considered
838 not something that should be dropped. 743 not something that should be dropped.
839 */ 744 */
840 /* 745 /*
841 Care must be taken that the next item pointer is not to money as 746 Care must be taken that the next item pointer is not to money as
842 the drop() routine will do unknown things to it when dropping 747 the drop() routine will do unknown things to it when dropping
843 in a shop. --Tero.Pelander@utu.fi 748 in a shop. --Tero.Pelander@utu.fi
844 */ 749 */
845
846 int cnt = MAX_ITEM_PER_DROP; 750 int cnt = MAX_ITEM_PER_ACTION;
847 751
848 if (params == NULL) 752 if (!params)
849 { 753 {
850 while (curinv != NULL) 754 while (curinv)
851 { 755 {
852 nextinv = curinv->below; 756 nextinv = curinv->below;
757
853 while (nextinv && nextinv->type == MONEY) 758 while (nextinv && nextinv->type == MONEY)
854 nextinv = nextinv->below; 759 nextinv = nextinv->below;
760
855 if (!QUERY_FLAG (curinv, FLAG_INV_LOCKED) && curinv->type != MONEY && 761 if (!QUERY_FLAG (curinv, FLAG_INV_LOCKED)
856 curinv->type != FOOD && curinv->type != KEY && 762 && curinv->type != MONEY
857 curinv->type != SPECIAL_KEY && curinv->type != GEM && 763 && curinv->type != FOOD
764 && curinv->type != KEY
765 && curinv->type != SPECIAL_KEY
766 && curinv->type != GEM
767 && !curinv->invisible
858 !curinv->invisible && (curinv->type != CONTAINER || op->container != curinv)) 768 && (curinv->type != CONTAINER || op->container_ () != curinv))
859 { 769 {
860 drop (op, curinv); 770 drop (op, curinv);
861 if (--cnt <= 0) break; 771 if (--cnt <= 0) break;
862 } 772 }
773
863 curinv = nextinv; 774 curinv = nextinv;
864 } 775 }
865 } 776 }
866
867 else if (strcmp (params, "weapons") == 0) 777 else if (strcmp (params, "weapons") == 0)
868 { 778 {
869 while (curinv != NULL) 779 while (curinv)
870 { 780 {
871 nextinv = curinv->below; 781 nextinv = curinv->below;
782
872 while (nextinv && nextinv->type == MONEY) 783 while (nextinv && nextinv->type == MONEY)
873 nextinv = nextinv->below; 784 nextinv = nextinv->below;
785
874 if (!QUERY_FLAG (curinv, FLAG_INV_LOCKED) && ((curinv->type == WEAPON) || (curinv->type == BOW) || (curinv->type == ARROW))) 786 if (!QUERY_FLAG (curinv, FLAG_INV_LOCKED) && ((curinv->type == WEAPON) || (curinv->type == BOW) || (curinv->type == ARROW)))
875 { 787 {
876 drop (op, curinv); 788 drop (op, curinv);
877 if (--cnt <= 0) break; 789 if (--cnt <= 0) break;
878 } 790 }
791
879 curinv = nextinv; 792 curinv = nextinv;
880 } 793 }
881 } 794 }
882
883 else if (strcmp (params, "armor") == 0 || strcmp (params, "armour") == 0) 795 else if (strcmp (params, "armor") == 0 || strcmp (params, "armour") == 0)
884 { 796 {
885 while (curinv != NULL) 797 while (curinv)
886 { 798 {
887 nextinv = curinv->below; 799 nextinv = curinv->below;
800
888 while (nextinv && nextinv->type == MONEY) 801 while (nextinv && nextinv->type == MONEY)
889 nextinv = nextinv->below; 802 nextinv = nextinv->below;
803
890 if (!QUERY_FLAG (curinv, FLAG_INV_LOCKED) && ((curinv->type == ARMOUR) || curinv->type == SHIELD || curinv->type == HELMET)) 804 if (!QUERY_FLAG (curinv, FLAG_INV_LOCKED) && ((curinv->type == ARMOUR) || curinv->type == SHIELD || curinv->type == HELMET))
891 { 805 {
892 drop (op, curinv); 806 drop (op, curinv);
893 if (--cnt <= 0) break; 807 if (--cnt <= 0) break;
894 } 808 }
809
895 curinv = nextinv; 810 curinv = nextinv;
896 } 811 }
897 } 812 }
898
899 else if (strcmp (params, "misc") == 0) 813 else if (strcmp (params, "misc") == 0)
900 { 814 {
901 while (curinv != NULL) 815 while (curinv)
902 { 816 {
903 nextinv = curinv->below; 817 nextinv = curinv->below;
818
904 while (nextinv && nextinv->type == MONEY) 819 while (nextinv && nextinv->type == MONEY)
905 nextinv = nextinv->below; 820 nextinv = nextinv->below;
821
906 if (!QUERY_FLAG (curinv, FLAG_INV_LOCKED) && !QUERY_FLAG (curinv, FLAG_APPLIED)) 822 if (!QUERY_FLAG (curinv, FLAG_INV_LOCKED) && !QUERY_FLAG (curinv, FLAG_APPLIED))
907 { 823 {
908 switch (curinv->type) 824 switch (curinv->type)
909 { 825 {
910 case HORN: 826 case HORN:
928 break; 844 break;
929 default: 845 default:
930 curinv = nextinv; 846 curinv = nextinv;
931 break; 847 break;
932 } 848 }
849
933 if (--cnt <= 0) break; 850 if (--cnt <= 0) break;
934 } 851 }
852
935 curinv = nextinv; 853 curinv = nextinv;
936 } 854 }
937 } 855 }
938 856
939 if (cnt <= 0) 857 if (cnt <= 0)
940 op->failmsg ("Only dropped some items, can't drop that many items at once."); 858 op->failmsg ("Only dropped some items, can't drop that many items at once.");
941 859
942 update_after_inventory_change (op);
943
944/* draw_look(op);*/ 860/* draw_look(op);*/
945 return 0; 861 return 0;
946} 862}
947 863
864
865/* This function tries to drop all objects in the <objs> vector.
866 * <dropper> is the object that wants to drop them.
867 * <cnt> can be a 0 pointer or a pointer to the maximum number of
868 * drop operations to perform.
869 *
870 * Returns true if at least one item was dropped.
871 */
872static bool
873drop_vector (object *dropper, vector<object *> &objs, int *cnt)
874{
875 vector<object *>::iterator i;
876
877 bool did_one = false;
878
879 for (i = objs.begin (); i != objs.end (); i++)
880 {
881 drop (dropper, *i);
882 if (cnt && --*cnt <= 0) break;
883 did_one = true;
884 }
885
886 return did_one;
887}
888
948/* Object op wants to drop object(s) params. params can be a 889/* Object op wants to drop object(s) params. params can be a
949 * comma seperated list. 890 * comma seperated list.
950 */ 891 */
951
952int 892int
953command_drop (object *op, char *params) 893command_drop (object *op, char *params)
954{ 894{
955 object *tmp, *next; 895 object *tmp, *next;
956 int did_one = 0; 896 int did_one = 0;
960 new_draw_info (NDI_UNIQUE, 0, op, "Drop what?"); 900 new_draw_info (NDI_UNIQUE, 0, op, "Drop what?");
961 return 0; 901 return 0;
962 } 902 }
963 else 903 else
964 { 904 {
965 int cnt = MAX_ITEM_PER_DROP; 905 vector<object *> matched_objs;
966 906
967 for (tmp = op->inv; tmp; tmp = next) 907 for (tmp = op->inv; tmp; tmp = next)
968 { 908 {
969 next = tmp->below; 909 next = tmp->below;
970 if (QUERY_FLAG (tmp, FLAG_NO_DROP) || tmp->invisible) 910 if (QUERY_FLAG (tmp, FLAG_NO_DROP) || tmp->invisible)
971 continue; 911 continue;
972 912
973 if (item_matched_string (op, tmp, params)) 913 if (item_matched_string (op, tmp, params))
974 { 914 matched_objs.push_back (tmp);
975 drop (op, tmp);
976 if (--cnt <= 0) break;
977 did_one = 1;
978 } 915 }
979 }
980 916
981 if (!did_one) 917 int cnt = MAX_ITEM_PER_ACTION;
918
919 if (!drop_vector (op, matched_objs, &cnt))
982 new_draw_info (NDI_UNIQUE, 0, op, "Nothing to drop."); 920 new_draw_info (NDI_UNIQUE, 0, op, "Nothing to drop.");
983 921
984 if (cnt <= 0) 922 if (cnt <= 0)
985 op->failmsg ("Only dropped some items, can't drop that many items at once."); 923 op->failmsg ("Only dropped some items, can't drop that many items at once.");
986
987 update_after_inventory_change (op);
988 } 924 }
989 925
990 return 0; 926 return 0;
991} 927}
992 928
997 { 933 {
998 object *tmp = op->below; 934 object *tmp = op->below;
999 935
1000 while (tmp && !tmp->client_visible ()) 936 while (tmp && !tmp->client_visible ())
1001 tmp = tmp->below; 937 tmp = tmp->below;
938
1002 if (tmp) 939 if (tmp)
1003 examine (op, tmp); 940 examine (op, tmp);
1004 } 941 }
1005 else 942 else
1006 { 943 {
1007 object *tmp = find_best_object_match (op, params); 944 object *tmp = find_best_object_match (op, params);
1008 945
1009 if (tmp) 946 if (tmp)
1010 examine (op, tmp); 947 examine (op, tmp);
1011 else 948 else
1012 new_draw_info_format (NDI_UNIQUE, 0, op, "Could not find an object that matches %s", params); 949 op->contr->infobox (MSG_CHANNEL ("examine"), format ("Could not find an object that matches %s", params));
1013 } 950 }
951
1014 return 0; 952 return 0;
1015} 953}
1016 954
1017/* op should be a player. 955/* op should be a player.
1018 * we return the object the player has marked with the 'mark' command 956 * we return the object the player has marked with the 'mark' command
1065 dynbuf_text buf (512, 512); 1003 dynbuf_text buf (512, 512);
1066 1004
1067 object *mon = head ? head : this; 1005 object *mon = head ? head : this;
1068 1006
1069 if (QUERY_FLAG (mon, FLAG_UNDEAD)) 1007 if (QUERY_FLAG (mon, FLAG_UNDEAD))
1070 buf << "It is an undead force.\n"; 1008 buf << "It is an undead force.\r";
1071 1009
1072 if (mon->level > who->level) 1010 if (mon->level > who->level)
1073 buf << "It is likely more powerful than you.\n"; 1011 buf << "It is likely more powerful than you.\r";
1074 else if (mon->level < who->level) 1012 else if (mon->level < who->level)
1075 buf << "It is likely less powerful than you.\n"; 1013 buf << "It is likely less powerful than you.\r";
1076 else 1014 else
1077 buf << "It is probably as powerful as you.\n"; 1015 buf << "It is probably as powerful as you.\r";
1078 1016
1079 if (mon->attacktype & AT_ACID) 1017 if (mon->attacktype & AT_ACID)
1080 buf << "You seem to smell an acrid odor.\n"; 1018 buf << "You seem to smell an acrid odor.\r";
1081 1019
1082 /* Anyone know why this used to use the clone value instead of the 1020 /* Anyone know why this used to use the clone value instead of the
1083 * maxhp field? This seems that it should give more accurate results. 1021 * maxhp field? This seems that it should give more accurate results.
1084 */ 1022 */
1085 switch ((mon->stats.hp + 1) * 4 / (mon->stats.maxhp + 1)) 1023 switch ((mon->stats.hp + 1) * 4 / (mon->stats.maxhp + 1))
1086 { /* From 1-4 */ 1024 { /* From 1-4 */
1087 case 1: 1025 case 1:
1088 buf << "It is in a bad shape.\n"; 1026 buf << "It is in a bad shape.\r";
1089 break; 1027 break;
1090 case 2: 1028 case 2:
1091 buf << "It is hurt.\n"; 1029 buf << "It is hurt.\r";
1092 break; 1030 break;
1093 case 3: 1031 case 3:
1094 buf << "It is somewhat hurt.\n"; 1032 buf << "It is somewhat hurt.\r";
1095 break; 1033 break;
1096 case 4: 1034 case 4:
1097 buf << "It is in excellent shape.\n"; 1035 buf << "It is in excellent shape.\r";
1098 break; 1036 break;
1099 } 1037 }
1100 1038
1101 if (present_in_ob (POISONING, mon)) 1039 if (present_in_ob (POISONING, mon))
1102 buf << "It looks very ill.\n"; 1040 buf << "It looks very ill.\r";
1041
1042 buf << '\n';
1103 1043
1104 return buf; 1044 return buf;
1105} 1045}
1106 1046
1107/* tmp is the object being described, pl is who is examing it. */ 1047/* tmp is the object being described, pl is who is examing it. */
1114} 1054}
1115 1055
1116std::string 1056std::string
1117object::long_desc (object *who) 1057object::long_desc (object *who)
1118{ 1058{
1119 std::string buf (query_name (this)); 1059 std::string buf (query_name ());
1120 1060
1121 switch (type) 1061 switch (type)
1122 { 1062 {
1123 case RING: 1063 case RING:
1124 case SKILL: 1064 case SKILL:
1136 case CLOAK: 1076 case CLOAK:
1137 case FOOD: 1077 case FOOD:
1138 case DRINK: 1078 case DRINK:
1139 case FLESH: 1079 case FLESH:
1140 case SKILL_TOOL: 1080 case SKILL_TOOL:
1081 case LAMP:
1141 case POWER_CRYSTAL: 1082 case POWER_CRYSTAL:
1142 { 1083 {
1143 const char *cp = ::describe_item (this, who); 1084 const char *cp = ::describe_item (this, who);
1144 1085
1145 if (*cp) 1086 if (*cp)
1160examine_monster (object *op, object *tmp) 1101examine_monster (object *op, object *tmp)
1161{ 1102{
1162 new_draw_info (NDI_UNIQUE, 0, op, tmp->describe_monster (op).c_str ()); 1103 new_draw_info (NDI_UNIQUE, 0, op, tmp->describe_monster (op).c_str ());
1163} 1104}
1164 1105
1165std::string
1166object::describe (object *who)
1167{
1168 dynbuf_text buf (1024, 1024);
1169
1170 buf.printf ("That is: %s.\n", long_desc (who).c_str ());
1171
1172 if (custom_name)
1173 buf.printf ("You call it %s\n", &custom_name);
1174
1175 switch (type)
1176 {
1177 case SPELLBOOK:
1178 if (flag [FLAG_IDENTIFIED] && inv)
1179 buf.printf ("%s is a %s %s spell\n", &inv->name, get_levelnumber (inv->level), &inv->skill);
1180 break;
1181
1182 case BOOK:
1183 if (msg)
1184 buf << "Something is written in it.\n";
1185 break;
1186
1187 case CONTAINER:
1188 if (race != NULL)
1189 {
1190 if (weight_limit && stats.Str < 100)
1191 buf.printf ("It can hold only %s and its weight limit is %.1f kg.\n",
1192 &race, weight_limit / (10.0 * (100 - stats.Str)));
1193 else
1194 buf.printf ("It can hold only %s.\n", &race);
1195 }
1196 else if (weight_limit && stats.Str < 100)
1197 buf.printf ("Its weight limit is %.1f kg.\n", weight_limit / (10.0 * (100 - stats.Str)));
1198 break;
1199
1200 case WAND:
1201 if (flag [FLAG_IDENTIFIED])
1202 buf.printf ("It has %d charges left.\n", stats.food);
1203 break;
1204 }
1205
1206 if (materialname && !msg)
1207 buf.printf ("It is made of: %s.\n", &materialname);
1208
1209 if (who)
1210 /* Where to wear this item */
1211 for (int i = 0; i < NUM_BODY_LOCATIONS; i++)
1212 if (slot[i].info)
1213 {
1214 buf << (who->slot[i].info ? body_locations[i].use_name : body_locations[i].nonuse_name);
1215
1216 if (slot[i].info < -1 && who->slot[i].info)
1217 buf.printf ("(%d)", -slot[i].info);
1218
1219 buf << ".\n";
1220 }
1221
1222 if (weight)
1223 buf.printf (nrof > 1 ? "They weigh %3.3f kg.\n" : "It weighs %3.3f kg.\n", weight * (nrof ? nrof : 1) / 1000.0);
1224
1225 if (value && !flag [FLAG_STARTEQUIP] && !flag [FLAG_NO_PICK] && who)
1226 {
1227 buf.printf ("You reckon %s worth %s.\n", nrof > 1 ? "they are" : "it is", query_cost_string (this, who, F_TRUE | F_APPROX));
1228
1229 if (is_in_shop (who))
1230 {
1231 if (flag [FLAG_UNPAID])
1232 buf.printf ("%s would cost you %s.\n", nrof > 1 ? "They" : "It", query_cost_string (this, who, F_BUY | F_SHOP));
1233 else
1234 buf.printf ("You are offered %s for %s.\n", query_cost_string (this, who, F_SELL + F_SHOP), nrof > 1 ? "them" : "it");
1235 }
1236 }
1237
1238 if (flag [FLAG_MONSTER])
1239 buf << describe_monster (who);
1240
1241 /* Is this item buildable? */
1242 if (flag [FLAG_IS_BUILDABLE])
1243 buf << "This is a buildable item.\n";
1244
1245 /* Does the object have a message? Don't show message for all object
1246 * types - especially if the first entry is a match
1247 */
1248 if (msg && type != EXIT && type != BOOK && type != CORPSE && !move_on && *msg != '@')
1249 {
1250 /* This is just a hack so when identifying the items, we print
1251 * out the extra message
1252 */
1253 if (need_identify (this) && flag [FLAG_IDENTIFIED])
1254 buf << "The object has a story:\n";
1255
1256 buf << msg << '\n';
1257 }
1258
1259 buf << '\n';
1260
1261 return std::string (buf.linearise (), buf.size ());
1262}
1263
1264static void 1106static void
1265display_new_pickup (object *op) 1107display_new_pickup (object *op)
1266{ 1108{
1267 int i = op->contr->mode; 1109 int i = op->contr->mode;
1268 1110
1269 if (!(i & PU_NEWMODE))
1270 return;
1271
1272 new_draw_info_format (NDI_UNIQUE, 0, op, "%d NEWMODE", i & PU_NEWMODE ? 1 : 0);
1273 new_draw_info_format (NDI_UNIQUE, 0, op, "%d DEBUG", i & PU_DEBUG ? 1 : 0); 1111 new_draw_info_format (NDI_UNIQUE, 0, op, "%d DEBUG", i & PU_DEBUG ? 1 : 0);
1274 new_draw_info_format (NDI_UNIQUE, 0, op, "%d INHIBIT", i & PU_INHIBIT ? 1 : 0); 1112 new_draw_info_format (NDI_UNIQUE, 0, op, "%d INHIBIT", i & PU_INHIBIT ? 1 : 0);
1275 new_draw_info_format (NDI_UNIQUE, 0, op, "%d STOP", i & PU_STOP ? 1 : 0); 1113 new_draw_info_format (NDI_UNIQUE, 0, op, "%d STOP", i & PU_STOP ? 1 : 0);
1276 1114
1277 new_draw_info_format (NDI_UNIQUE, 0, op, "%d <= x pickup weight/value RATIO (0==off)", (i & PU_RATIO) * 5); 1115 new_draw_info_format (NDI_UNIQUE, 0, op, "%d <= x pickup weight/value RATIO (0==off)", (i & PU_RATIO) * 5);
1328 }; 1166 };
1329 1167
1330 if (!params) 1168 if (!params)
1331 { 1169 {
1332 /* if the new mode is used, just print the settings */ 1170 /* if the new mode is used, just print the settings */
1333 if (op->contr->mode & PU_NEWMODE)
1334 {
1335 display_new_pickup (op); 1171 display_new_pickup (op);
1336 return 1;
1337 }
1338 if (1)
1339 LOG (llevDebug, "command_pickup: !params\n");
1340 set_pickup_mode (op, (op->contr->mode > 6) ? 0 : op->contr->mode + 1);
1341 return 0; 1172 return 0;
1342 } 1173 }
1343 1174
1344 while (*params == ' ' && *params) 1175 while (*params == ' ' && *params)
1345 params++; 1176 params++;
1351 for (mode = 0; names[mode]; mode++) 1182 for (mode = 0; names[mode]; mode++)
1352 { 1183 {
1353 if (!strcmp (names[mode], params + 1)) 1184 if (!strcmp (names[mode], params + 1))
1354 { 1185 {
1355 i = op->contr->mode; 1186 i = op->contr->mode;
1356 if (!(i & PU_NEWMODE)) 1187
1357 i = PU_NEWMODE;
1358 if (*params == '+') 1188 if (*params == '+')
1359 i = i | modes[mode]; 1189 i = i | modes[mode];
1360 else 1190 else
1361 i = i & ~modes[mode]; 1191 i = i & ~modes[mode];
1192
1362 op->contr->mode = i; 1193 op->contr->mode = i;
1363 display_new_pickup (op); 1194 display_new_pickup (op);
1364 return 1; 1195 return 1;
1365 } 1196 }
1366 } 1197 }
1368 return 1; 1199 return 1;
1369 } 1200 }
1370 1201
1371 if (sscanf (params, "%u", &i) != 1) 1202 if (sscanf (params, "%u", &i) != 1)
1372 { 1203 {
1373 if (1)
1374 LOG (llevDebug, "command_pickup: params==NULL\n");
1375 new_draw_info (NDI_UNIQUE, 0, op, "Usage: pickup <0-7> or <value_density> ."); 1204 new_draw_info (NDI_UNIQUE, 0, op, "Usage: pickup <value_density> or [+-]type.");
1376 return 1; 1205 return 1;
1377 } 1206 }
1378 set_pickup_mode (op, i); 1207
1208 if (i <= PU_RATIO)
1209 i |= op->contr->mode & ~PU_RATIO;
1210
1211 op->contr->mode = i;
1379 1212
1380 return 1; 1213 return 1;
1381}
1382
1383void
1384set_pickup_mode (object *op, int i)
1385{
1386 switch (op->contr->mode = i)
1387 {
1388 case 0:
1389 new_draw_info (NDI_UNIQUE, 0, op, "Mode: Don't pick up.");
1390 break;
1391 case 1:
1392 new_draw_info (NDI_UNIQUE, 0, op, "Mode: Pick up one item.");
1393 break;
1394 case 2:
1395 new_draw_info (NDI_UNIQUE, 0, op, "Mode: Pick up one item and stop.");
1396 break;
1397 case 3:
1398 new_draw_info (NDI_UNIQUE, 0, op, "Mode: Stop before picking up.");
1399 break;
1400 case 4:
1401 new_draw_info (NDI_UNIQUE, 0, op, "Mode: Pick up all items.");
1402 break;
1403 case 5:
1404 new_draw_info (NDI_UNIQUE, 0, op, "Mode: Pick up all items and stop.");
1405 break;
1406 case 6:
1407 new_draw_info (NDI_UNIQUE, 0, op, "Mode: Pick up all magic items.");
1408 break;
1409 case 7:
1410 new_draw_info (NDI_UNIQUE, 0, op, "Mode: Pick up all coins and gems");
1411 break;
1412 }
1413} 1214}
1414 1215
1415int 1216int
1416command_search_items (object *op, char *params) 1217command_search_items (object *op, char *params)
1417{ 1218{
1418 char buf[MAX_BUF];
1419
1420 if (settings.search_items == FALSE)
1421 return 1;
1422
1423 if (params == NULL) 1219 if (params == NULL)
1424 { 1220 {
1425 if (op->contr->search_str[0] == '\0') 1221 if (op->contr->search_str[0] == '\0')
1426 { 1222 {
1427 new_draw_info (NDI_UNIQUE, 0, op, "Example: search magic+1"); 1223 new_draw_info (NDI_UNIQUE, 0, op, "Example: search-items magic+1");
1428 new_draw_info (NDI_UNIQUE, 0, op, "Would automatically pick up all"); 1224 new_draw_info (NDI_UNIQUE, 0, op, "Would automatically pick up all");
1429 new_draw_info (NDI_UNIQUE, 0, op, "items containing the word 'magic+1'."); 1225 new_draw_info (NDI_UNIQUE, 0, op, "items containing the word 'magic+1'.");
1430 return 1; 1226 return 1;
1431 } 1227 }
1432 1228
1433 op->contr->search_str[0] = '\0'; 1229 op->contr->search_str[0] = '\0';
1434 new_draw_info (NDI_UNIQUE, 0, op, "Search mode turned off."); 1230 new_draw_info (NDI_UNIQUE, 0, op, "Search mode turned off.");
1435 op->update_stats (); 1231 op->contr->queue_stats_update ();
1436 return 1; 1232 return 1;
1437 } 1233 }
1438 1234
1439 if ((int) strlen (params) >= MAX_BUF) 1235 if (strlen (params) >= sizeof (op->contr->search_str))
1440 { 1236 {
1441 new_draw_info (NDI_UNIQUE, 0, op, "Search string too long."); 1237 new_draw_info (NDI_UNIQUE, 0, op, "Search string too long.");
1442 return 1; 1238 return 1;
1443 } 1239 }
1444 1240
1445 strcpy (op->contr->search_str, params); 1241 strcpy (op->contr->search_str, params);
1446 sprintf (buf, "Searching for '%s'.", op->contr->search_str); 1242 new_draw_info (NDI_UNIQUE, 0, op, format ("Now searching for '%s'.", op->contr->search_str));
1447 new_draw_info (NDI_UNIQUE, 0, op, buf); 1243 op->contr->queue_stats_update ();
1448 op->update_stats (); 1244
1449 return 1; 1245 return 1;
1450} 1246}
1451 1247
1248int
1249command_unlock (object *op, char *params)
1250{
1251 /* if the unlock command typed with nothing, unlock everything,
1252 * this might be bad
1253 */
1254 if (params == NULL)
1255 {
1256 for (object *item = op->inv; item; item = item->below)
1257 {
1258 CLEAR_FLAG(item, FLAG_INV_LOCKED);
1259 //d// new_draw_info (NDI_UNIQUE, 0, op, "unlocked items with null param.");
1260 esrv_update_item (UPD_FLAGS, op, item);
1261 }
1262 return 0;
1263 }
1264
1265 /* if the unlock command is used with a param,
1266 * unlock what matches. i.e. unlock material, should unlock all the materials
1267 */
1268 for (object *item = op->inv; item; item = item->below)
1269 if (item->name.contains (params))
1270 {
1271 CLEAR_FLAG (item, FLAG_INV_LOCKED);
1272 //d// new_draw_info (NDI_UNIQUE, 0, op, "unlocked items with a param.");
1273 esrv_update_item (UPD_FLAGS, op, item);
1274 }
1275
1276 return 0;
1277}
1278
1279int
1280command_lock (object *op, char *params)
1281{
1282 /* if the lock command is typed by itself, lock everything
1283 */
1284 if (params == NULL)
1285 {
1286 for (object *item = op->inv; item; item = item->below)
1287 {
1288 SET_FLAG (item, FLAG_INV_LOCKED);
1289 //d// new_draw_info (NDI_UNIQUE, 0, op, "locked items with null param.");
1290 esrv_update_item (UPD_FLAGS, op, item);
1291 }
1292 return 0;
1293 }
1294
1295 /* if the lock command is used with a param, lock what matches.
1296 * i.e. lock material, should lock all the materials
1297 */
1298 for (object *item = op->inv; item; item = item->below)
1299 if (item->name.contains (params))
1300 {
1301 SET_FLAG (item, FLAG_INV_LOCKED);
1302 //d// new_draw_info (NDI_UNIQUE, 0, op, "locked items with param.");
1303 esrv_update_item (UPD_FLAGS, op, item);
1304 }
1305
1306 return 0;
1307}
1308
1309/* op should be a player, params is any params.
1310 * If no params given, we print out the currently marked object.
1311 * otherwise, try to find a matching object - try best match first.
1312 */
1313int
1314command_mark (object *op, char *params)
1315{
1316 if (!params)
1317 {
1318 if (object *mark = find_marked_object (op))
1319 op->statusmsg (format ("%s is marked.", query_name (mark)));
1320 else
1321 op->failmsg ("You have no marked object.");
1322 }
1323 else
1324 {
1325 if (object *mark = find_best_object_match (op, params))
1326 {
1327 op->contr->mark = mark;
1328 op->statusmsg (format ("Marked item %s", query_name (mark)));
1329 }
1330 else
1331 op->failmsgf ("Could not find an object that matches %s", params);
1332 }
1333
1334 return 0; /*shouldnt get here */
1335}
1336

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines