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.65 by root, Sun Apr 20 18:48:51 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
1067 dynbuf_text buf (512, 512); 1003 dynbuf_text buf (512, 512);
1068 1004
1069 object *mon = head ? head : this; 1005 object *mon = head ? head : this;
1070 1006
1071 if (QUERY_FLAG (mon, FLAG_UNDEAD)) 1007 if (QUERY_FLAG (mon, FLAG_UNDEAD))
1072 buf << "It is an undead force.\n"; 1008 buf << "It is an undead force.\r";
1073 1009
1074 if (mon->level > who->level) 1010 if (mon->level > who->level)
1075 buf << "It is likely more powerful than you.\n"; 1011 buf << "It is likely more powerful than you.\r";
1076 else if (mon->level < who->level) 1012 else if (mon->level < who->level)
1077 buf << "It is likely less powerful than you.\n"; 1013 buf << "It is likely less powerful than you.\r";
1078 else 1014 else
1079 buf << "It is probably as powerful as you.\n"; 1015 buf << "It is probably as powerful as you.\r";
1080 1016
1081 if (mon->attacktype & AT_ACID) 1017 if (mon->attacktype & AT_ACID)
1082 buf << "You seem to smell an acrid odor.\n"; 1018 buf << "You seem to smell an acrid odor.\r";
1083 1019
1084 /* 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
1085 * maxhp field? This seems that it should give more accurate results. 1021 * maxhp field? This seems that it should give more accurate results.
1086 */ 1022 */
1087 switch ((mon->stats.hp + 1) * 4 / (mon->stats.maxhp + 1)) 1023 switch ((mon->stats.hp + 1) * 4 / (mon->stats.maxhp + 1))
1088 { /* From 1-4 */ 1024 { /* From 1-4 */
1089 case 1: 1025 case 1:
1090 buf << "It is in a bad shape.\n"; 1026 buf << "It is in a bad shape.\r";
1091 break; 1027 break;
1092 case 2: 1028 case 2:
1093 buf << "It is hurt.\n"; 1029 buf << "It is hurt.\r";
1094 break; 1030 break;
1095 case 3: 1031 case 3:
1096 buf << "It is somewhat hurt.\n"; 1032 buf << "It is somewhat hurt.\r";
1097 break; 1033 break;
1098 case 4: 1034 case 4:
1099 buf << "It is in excellent shape.\n"; 1035 buf << "It is in excellent shape.\r";
1100 break; 1036 break;
1101 } 1037 }
1102 1038
1103 if (present_in_ob (POISONING, mon)) 1039 if (present_in_ob (POISONING, mon))
1104 buf << "It looks very ill.\n"; 1040 buf << "It looks very ill.\r";
1041
1042 buf << '\n';
1105 1043
1106 return buf; 1044 return buf;
1107} 1045}
1108 1046
1109/* 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. */
1116} 1054}
1117 1055
1118std::string 1056std::string
1119object::long_desc (object *who) 1057object::long_desc (object *who)
1120{ 1058{
1121 std::string buf (query_name (this)); 1059 std::string buf (query_name ());
1122 1060
1123 switch (type) 1061 switch (type)
1124 { 1062 {
1125 case RING: 1063 case RING:
1126 case SKILL: 1064 case SKILL:
1138 case CLOAK: 1076 case CLOAK:
1139 case FOOD: 1077 case FOOD:
1140 case DRINK: 1078 case DRINK:
1141 case FLESH: 1079 case FLESH:
1142 case SKILL_TOOL: 1080 case SKILL_TOOL:
1081 case LAMP:
1143 case POWER_CRYSTAL: 1082 case POWER_CRYSTAL:
1144 { 1083 {
1145 const char *cp = ::describe_item (this, who); 1084 const char *cp = ::describe_item (this, who);
1146 1085
1147 if (*cp) 1086 if (*cp)
1162examine_monster (object *op, object *tmp) 1101examine_monster (object *op, object *tmp)
1163{ 1102{
1164 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 ());
1165} 1104}
1166 1105
1167std::string
1168object::describe (object *who)
1169{
1170 dynbuf_text buf (1024, 1024);
1171
1172 buf.printf ("That is: %s.\n", long_desc (who).c_str ());
1173
1174 if (custom_name)
1175 buf.printf ("You call it %s\n", &custom_name);
1176
1177 switch (type)
1178 {
1179 case SPELLBOOK:
1180 if (flag [FLAG_IDENTIFIED] && inv)
1181 buf.printf ("%s is a %s %s spell\n", &inv->name, get_levelnumber (inv->level), &inv->skill);
1182 break;
1183
1184 case BOOK:
1185 if (msg)
1186 buf << "Something is written in it.\n";
1187 break;
1188
1189 case CONTAINER:
1190 if (race != NULL)
1191 {
1192 if (weight_limit && stats.Str < 100)
1193 buf.printf ("It can hold only %s and its weight limit is %.1f kg.\n",
1194 &race, weight_limit / (10.0 * (100 - stats.Str)));
1195 else
1196 buf.printf ("It can hold only %s.\n", &race);
1197 }
1198 else if (weight_limit && stats.Str < 100)
1199 buf.printf ("Its weight limit is %.1f kg.\n", weight_limit / (10.0 * (100 - stats.Str)));
1200 break;
1201
1202 case WAND:
1203 if (flag [FLAG_IDENTIFIED])
1204 buf.printf ("It has %d charges left.\n", stats.food);
1205 break;
1206 }
1207
1208 if (materialname && !msg)
1209 buf.printf ("It is made of: %s.\n", &materialname);
1210
1211 if (who)
1212 /* Where to wear this item */
1213 for (int i = 0; i < NUM_BODY_LOCATIONS; i++)
1214 if (slot[i].info)
1215 {
1216 buf << (who->slot[i].info ? body_locations[i].use_name : body_locations[i].nonuse_name);
1217
1218 if (slot[i].info < -1 && who->slot[i].info)
1219 buf.printf ("(%d)", -slot[i].info);
1220
1221 buf << ".\n";
1222 }
1223
1224 if (weight)
1225 buf.printf (nrof > 1 ? "They weigh %3.3f kg.\n" : "It weighs %3.3f kg.\n", weight * (nrof ? nrof : 1) / 1000.0);
1226
1227 if (value && !flag [FLAG_STARTEQUIP] && !flag [FLAG_NO_PICK] && who)
1228 {
1229 buf.printf ("You reckon %s worth %s.\n", nrof > 1 ? "they are" : "it is", query_cost_string (this, who, F_TRUE | F_APPROX));
1230
1231 if (is_in_shop (who))
1232 {
1233 if (flag [FLAG_UNPAID])
1234 buf.printf ("%s would cost you %s.\n", nrof > 1 ? "They" : "It", query_cost_string (this, who, F_BUY | F_SHOP));
1235 else
1236 buf.printf ("You are offered %s for %s.\n", query_cost_string (this, who, F_SELL + F_SHOP), nrof > 1 ? "them" : "it");
1237 }
1238 }
1239
1240 if (flag [FLAG_MONSTER])
1241 buf << describe_monster (who);
1242
1243 /* Is this item buildable? */
1244 if (flag [FLAG_IS_BUILDABLE])
1245 buf << "This is a buildable item.\n";
1246
1247 /* Does the object have a message? Don't show message for all object
1248 * types - especially if the first entry is a match
1249 */
1250 if (msg && type != EXIT && type != BOOK && type != CORPSE && !move_on && *msg != '@')
1251 {
1252 /* This is just a hack so when identifying the items, we print
1253 * out the extra message
1254 */
1255 if (need_identify (this) && flag [FLAG_IDENTIFIED])
1256 buf << "The object has a story:\n";
1257
1258 buf << msg << '\n';
1259 }
1260
1261 buf << '\n';
1262
1263 return std::string (buf.linearise (), buf.size ());
1264}
1265
1266static void 1106static void
1267display_new_pickup (object *op) 1107display_new_pickup (object *op)
1268{ 1108{
1269 int i = op->contr->mode; 1109 int i = op->contr->mode;
1270 1110
1271 if (!(i & PU_NEWMODE))
1272 return;
1273
1274 new_draw_info_format (NDI_UNIQUE, 0, op, "%d NEWMODE", i & PU_NEWMODE ? 1 : 0);
1275 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);
1276 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);
1277 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);
1278 1114
1279 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);
1330 }; 1166 };
1331 1167
1332 if (!params) 1168 if (!params)
1333 { 1169 {
1334 /* if the new mode is used, just print the settings */ 1170 /* if the new mode is used, just print the settings */
1335 if (op->contr->mode & PU_NEWMODE)
1336 {
1337 display_new_pickup (op); 1171 display_new_pickup (op);
1338 return 1;
1339 }
1340 if (1)
1341 LOG (llevDebug, "command_pickup: !params\n");
1342 set_pickup_mode (op, (op->contr->mode > 6) ? 0 : op->contr->mode + 1);
1343 return 0; 1172 return 0;
1344 } 1173 }
1345 1174
1346 while (*params == ' ' && *params) 1175 while (*params == ' ' && *params)
1347 params++; 1176 params++;
1353 for (mode = 0; names[mode]; mode++) 1182 for (mode = 0; names[mode]; mode++)
1354 { 1183 {
1355 if (!strcmp (names[mode], params + 1)) 1184 if (!strcmp (names[mode], params + 1))
1356 { 1185 {
1357 i = op->contr->mode; 1186 i = op->contr->mode;
1358 if (!(i & PU_NEWMODE)) 1187
1359 i = PU_NEWMODE;
1360 if (*params == '+') 1188 if (*params == '+')
1361 i = i | modes[mode]; 1189 i = i | modes[mode];
1362 else 1190 else
1363 i = i & ~modes[mode]; 1191 i = i & ~modes[mode];
1192
1364 op->contr->mode = i; 1193 op->contr->mode = i;
1365 display_new_pickup (op); 1194 display_new_pickup (op);
1366 return 1; 1195 return 1;
1367 } 1196 }
1368 } 1197 }
1370 return 1; 1199 return 1;
1371 } 1200 }
1372 1201
1373 if (sscanf (params, "%u", &i) != 1) 1202 if (sscanf (params, "%u", &i) != 1)
1374 { 1203 {
1375 if (1)
1376 LOG (llevDebug, "command_pickup: params==NULL\n");
1377 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.");
1378 return 1; 1205 return 1;
1379 } 1206 }
1380 set_pickup_mode (op, i); 1207
1208 if (i <= PU_RATIO)
1209 i |= op->contr->mode & ~PU_RATIO;
1210
1211 op->contr->mode = i;
1381 1212
1382 return 1; 1213 return 1;
1383}
1384
1385void
1386set_pickup_mode (object *op, int i)
1387{
1388 switch (op->contr->mode = i)
1389 {
1390 case 0:
1391 new_draw_info (NDI_UNIQUE, 0, op, "Mode: Don't pick up.");
1392 break;
1393 case 1:
1394 new_draw_info (NDI_UNIQUE, 0, op, "Mode: Pick up one item.");
1395 break;
1396 case 2:
1397 new_draw_info (NDI_UNIQUE, 0, op, "Mode: Pick up one item and stop.");
1398 break;
1399 case 3:
1400 new_draw_info (NDI_UNIQUE, 0, op, "Mode: Stop before picking up.");
1401 break;
1402 case 4:
1403 new_draw_info (NDI_UNIQUE, 0, op, "Mode: Pick up all items.");
1404 break;
1405 case 5:
1406 new_draw_info (NDI_UNIQUE, 0, op, "Mode: Pick up all items and stop.");
1407 break;
1408 case 6:
1409 new_draw_info (NDI_UNIQUE, 0, op, "Mode: Pick up all magic items.");
1410 break;
1411 case 7:
1412 new_draw_info (NDI_UNIQUE, 0, op, "Mode: Pick up all coins and gems");
1413 break;
1414 }
1415} 1214}
1416 1215
1417int 1216int
1418command_search_items (object *op, char *params) 1217command_search_items (object *op, char *params)
1419{ 1218{
1420 char buf[MAX_BUF];
1421
1422 if (settings.search_items == FALSE)
1423 return 1;
1424
1425 if (params == NULL) 1219 if (params == NULL)
1426 { 1220 {
1427 if (op->contr->search_str[0] == '\0') 1221 if (op->contr->search_str[0] == '\0')
1428 { 1222 {
1429 new_draw_info (NDI_UNIQUE, 0, op, "Example: search magic+1"); 1223 new_draw_info (NDI_UNIQUE, 0, op, "Example: search-items magic+1");
1430 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");
1431 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'.");
1432 return 1; 1226 return 1;
1433 } 1227 }
1434 1228
1435 op->contr->search_str[0] = '\0'; 1229 op->contr->search_str[0] = '\0';
1436 new_draw_info (NDI_UNIQUE, 0, op, "Search mode turned off."); 1230 new_draw_info (NDI_UNIQUE, 0, op, "Search mode turned off.");
1437 op->update_stats (); 1231 op->contr->queue_stats_update ();
1438 return 1; 1232 return 1;
1439 } 1233 }
1440 1234
1441 if ((int) strlen (params) >= MAX_BUF) 1235 if (strlen (params) >= sizeof (op->contr->search_str))
1442 { 1236 {
1443 new_draw_info (NDI_UNIQUE, 0, op, "Search string too long."); 1237 new_draw_info (NDI_UNIQUE, 0, op, "Search string too long.");
1444 return 1; 1238 return 1;
1445 } 1239 }
1446 1240
1447 strcpy (op->contr->search_str, params); 1241 strcpy (op->contr->search_str, params);
1448 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));
1449 new_draw_info (NDI_UNIQUE, 0, op, buf); 1243 op->contr->queue_stats_update ();
1450 op->update_stats (); 1244
1451 return 1; 1245 return 1;
1452} 1246}
1453 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