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

Comparing deliantra/server/server/apply.C (file contents):
Revision 1.172 by root, Mon Sep 29 10:32:50 2008 UTC vs.
Revision 1.185 by root, Mon Jan 12 19:12:16 2009 UTC

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 GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>. 19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * 20 *
21 * The authors can be reached via e-mail to <support@deliantra.net> 21 * The authors can be reached via e-mail to <support@deliantra.net>
22 */ 22 */
23 23
24#include <cmath> 24#include <cmath>
25 25
160 * matching item. 160 * matching item.
161 **/ 161 **/
162void 162void
163handle_apply_yield (object *tmp) 163handle_apply_yield (object *tmp)
164{ 164{
165 if (shstr yield = tmp->kv (shstr_on_use_yield)) 165 if (shstr_tmp yield = tmp->kv (shstr_on_use_yield))
166 archetype::get (yield)->insert_at (tmp, tmp, INS_BELOW_ORIGINATOR); 166 archetype::get (yield)->insert_at (tmp, tmp, INS_BELOW_ORIGINATOR);
167} 167}
168 168
169/** 169/**
170 * Handles applying a potion. 170 * Handles applying a potion.
406 406
407/** 407/**
408 * This returns the sum of nrof of item (arch name). 408 * This returns the sum of nrof of item (arch name).
409 */ 409 */
410static int 410static int
411check_item (object *op, const char *item) 411check_item (object *op, shstr_cmp item)
412{ 412{
413 int count = 0; 413 int count = 0;
414 414
415 if (!item) 415 if (!item)
416 return 0; 416 return 0;
417 417
418 for (op = op->below; op; op = op->below) 418 for (op = op->below; op; op = op->below)
419 {
420 if (strcmp (op->arch->archname, item) == 0) 419 if (op->arch->archname == item)
421 {
422 if (!QUERY_FLAG (op, FLAG_CURSED) && !QUERY_FLAG (op, FLAG_DAMNED) 420 if (!QUERY_FLAG (op, FLAG_CURSED) && !QUERY_FLAG (op, FLAG_DAMNED)
423 /* Loophole bug? -FD- */ && !QUERY_FLAG (op, FLAG_UNPAID)) 421 && /* Loophole bug? -FD- */ !QUERY_FLAG (op, FLAG_UNPAID))
424 {
425 if (op->nrof == 0) /* this is necessary for artifact sacrifices --FD-- */
426 count++;
427 else
428 count += op->nrof; 422 count += op->number_of ();
429 }
430 }
431 }
432 423
433 return count; 424 return count;
434} 425}
435 426
436/** 427/**
438 * op is typically the player, which is only 429 * op is typically the player, which is only
439 * really used to determine what space to look at. 430 * really used to determine what space to look at.
440 * Modified to only eat 'nrof' of objects. 431 * Modified to only eat 'nrof' of objects.
441 */ 432 */
442static void 433static void
443eat_item (object *op, const char *item, uint32 nrof) 434eat_item (object *op, shstr_cmp item, uint32 nrof)
444{ 435{
445 object *prev; 436 object *prev;
446 437
447 prev = op; 438 prev = op;
448 op = op->below; 439 op = op->below;
449 440
450 while (op) 441 while (op)
451 { 442 {
452 if (strcmp (op->arch->archname, item) == 0) 443 if (op->arch->archname == item)
453 { 444 {
454 if (op->nrof >= nrof) 445 if (op->nrof >= nrof)
455 { 446 {
456 op->decrease (nrof); 447 op->decrease (nrof);
457 return; 448 return;
995 item->nrof = give; 986 item->nrof = give;
996 987
997 if (nr) 988 if (nr)
998 item->nrof *= nr; 989 item->nrof *= nr;
999 990
1000 if (is_in_shop (converter)) 991 if (converter->flag [FLAG_PRECIOUS])
1001 SET_FLAG (item, FLAG_UNPAID); 992 SET_FLAG (item, FLAG_UNPAID);
993
994 if (is_in_shop (converter))
995 {
996 // converters on shop floors don't work anymore, bug lets check for it
997 // and report in case someone still does it.
998 LOG (llevDebug, "ITEMBUG: broken converter, converters on shop floor don't work: %s\n",
999 converter->debug_desc ());
1000 SET_FLAG (item, FLAG_UNPAID);
1001 }
1002 else if (price_in < sint64 (item->nrof) * item->value) 1002 else if (price_in < sint64 (item->nrof) * item->value)
1003 { 1003 {
1004 LOG (llevDebug, "converter output price higher than input: %s at %s (%d, %d) in value %d, out value %d for %s\n", 1004 LOG (llevDebug, "converter output price higher than input: %s at %s (%d, %d) in value %d, out value %d for %s\n",
1005 &converter->name, &converter->map->path, converter->x, converter->y, price_in, item->nrof * item->value, &item->name); 1005 &converter->name, &converter->map->path, converter->x, converter->y, price_in, item->nrof * item->value, &item->name);
1006 /** 1006 /**
1117/* push_button (altar);*/ 1117/* push_button (altar);*/
1118 } 1118 }
1119 else 1119 else
1120 { 1120 {
1121 altar->value = 1; /* works only once */ 1121 altar->value = 1; /* works only once */
1122 push_button (altar); 1122 push_button (altar, originator);
1123 } 1123 }
1124 1124
1125 return !sacrifice; 1125 return !sacrifice;
1126 } 1126 }
1127 else 1127 else
1153 { 1153 {
1154 has_unpaid = true; 1154 has_unpaid = true;
1155 break; 1155 break;
1156 } 1156 }
1157 1157
1158 if (op->type != PLAYER) 1158 if (!op->is_player ())
1159 { 1159 {
1160 /* Remove all the unpaid objects that may be carried here. 1160 /* Remove all the unpaid objects that may be carried here.
1161 * This could be pets or monsters that are somehow in 1161 * This could be pets or monsters that are somehow in
1162 * the shop. 1162 * the shop.
1163 */ 1163 */
1167 1167
1168 if (QUERY_FLAG (tmp, FLAG_UNPAID)) 1168 if (QUERY_FLAG (tmp, FLAG_UNPAID))
1169 { 1169 {
1170 int i = find_free_spot (tmp, op->map, op->x, op->y, 1, 9); 1170 int i = find_free_spot (tmp, op->map, op->x, op->y, 1, 9);
1171 1171
1172 if (i >= 0)
1172 tmp->remove (); 1173 tmp->move (i);
1173
1174 if (i == -1)
1175 i = 0;
1176
1177 tmp->map = op->map;
1178 tmp->x = op->x + freearr_x[i];
1179 tmp->y = op->y + freearr_y[i];
1180 insert_ob_in_map (tmp, op->map, op, 0);
1181 } 1174 }
1182 } 1175 }
1183 1176
1184 /* Don't teleport things like spell effects */ 1177 /* Don't teleport things like spell effects */
1185 if (QUERY_FLAG (op, FLAG_NO_PICK)) 1178 if (QUERY_FLAG (op, FLAG_NO_PICK))
1196 if (i != -1) 1189 if (i != -1)
1197 rv = transfer_ob (op, op->x + freearr_x[i], op->y + freearr_y[i], 0, shop_mat); 1190 rv = transfer_ob (op, op->x + freearr_x[i], op->y + freearr_y[i], 0, shop_mat);
1198 1191
1199 return 0; 1192 return 0;
1200 } 1193 }
1194
1201 /* Removed code that checked for multipart objects - it appears that 1195 /* Removed code that checked for multipart objects - it appears that
1202 * the teleport function should be able to handle this just fine. 1196 * the teleport function should be able to handle this just fine.
1203 */ 1197 */
1204 rv = teleport (shop_mat, SHOP_MAT, op); 1198 rv = teleport (shop_mat, SHOP_MAT, op);
1205 } 1199 }
1260 * Handles applying a sign. 1254 * Handles applying a sign.
1261 */ 1255 */
1262static void 1256static void
1263apply_sign (object *op, object *sign, int autoapply) 1257apply_sign (object *op, object *sign, int autoapply)
1264{ 1258{
1259 if (!op->is_player())
1260 return;
1261
1265 if (sign->has_dialogue ()) 1262 if (sign->has_dialogue ())
1266 { 1263 {
1267 op->statusmsg (form ("Maybe you should I<talk> to the %s instead?", &sign->name)); 1264 op->statusmsg (format ("Maybe you should I<talk> to the %s instead?", &sign->name));
1268 return; 1265 return;
1269 } 1266 }
1270 1267
1271 if (!sign->msg) 1268 if (!sign->msg)
1272 { 1269 {
1273 op->statusmsg ("Nothing is written on it."); 1270 op->contr->infobox (MSG_CHANNEL ("examine"),
1271 format ("T<%s>\n\n Nothing %sis written on it.",
1272 &sign->name,
1273 sign->name == sign->arch->name ? "" : "else "));
1274 return; 1274 return;
1275 } 1275 }
1276 1276
1277 if (sign->stats.food) 1277 if (sign->stats.food)
1278 { 1278 {
1279 if (sign->last_eat >= sign->stats.food) 1279 if (sign->last_eat >= sign->stats.food)
1280 { 1280 {
1281 if (!sign->move_on) 1281 if (!sign->move_on)
1282 op->statusmsg ("You cannot read it anymore."); 1282 op->failmsg ("You cannot read it anymore.");
1283 1283
1284 return; 1284 return;
1285 } 1285 }
1286 1286
1287 if (!QUERY_FLAG (op, FLAG_WIZPASS)) 1287 if (!QUERY_FLAG (op, FLAG_WIZPASS))
1305 if (sign->sound) 1305 if (sign->sound)
1306 ns->play_sound (sign->sound); 1306 ns->play_sound (sign->sound);
1307 else if (autoapply) 1307 else if (autoapply)
1308 ns->play_sound (sound_find ("msg_voice")); 1308 ns->play_sound (sound_find ("msg_voice"));
1309 1309
1310 if (ns->can_msg)
1311 op->contr->infobox (MSG_CHANNEL ("examine"), format ("T<%s>\n\n%s", &sign->name, &sign->msg)); 1310 op->contr->infobox (MSG_CHANNEL ("examine"), format ("T<%s>\n\n%s", &sign->name, &sign->msg));
1312 else
1313 {
1314 readable_message_type *msgType = get_readable_message_type (sign);
1315 const char *somemsg = format ("%u %s", autoapply ? 1 : 0, &sign->msg);
1316 draw_ext_info (NDI_UNIQUE | NDI_NAVY, 0, op, msgType->message_type, msgType->message_subtype, somemsg, &sign->msg);
1317 }
1318 } 1311 }
1319} 1312}
1320 1313
1321static void 1314static void
1322move_apply_hole (object *trap, object *victim) 1315move_apply_hole (object *trap, object *victim)
1430 } 1423 }
1431 goto leave; 1424 goto leave;
1432 1425
1433 case BUTTON: 1426 case BUTTON:
1434 case PEDESTAL: 1427 case PEDESTAL:
1435 update_button (trap); 1428 update_button (trap, originator);
1436 goto leave; 1429 goto leave;
1437 1430
1438 case ALTAR: 1431 case ALTAR:
1439 /* sacrifice victim on trap */ 1432 /* sacrifice victim on trap */
1440 apply_altar (trap, victim, originator); 1433 apply_altar (trap, victim, originator);
1533 if (victim->type == PLAYER && EXIT_PATH (trap)) 1526 if (victim->type == PLAYER && EXIT_PATH (trap))
1534 { 1527 {
1535 /* Basically, don't show exits leading to random maps the 1528 /* Basically, don't show exits leading to random maps the
1536 * players output. 1529 * players output.
1537 */ 1530 */
1538 if (trap->msg && strncmp (EXIT_PATH (trap), "/!", 2)) 1531 if (trap->msg && !EXIT_PATH (trap).starts_with ("/!"))
1539 victim->statusmsg (trap->msg, NDI_NAVY); 1532 victim->statusmsg (trap->msg, NDI_NAVY);
1540 1533
1541 trap->play_sound (trap->sound); 1534 trap->play_sound (trap->sound);
1542 victim->enter_exit (trap); 1535 victim->enter_exit (trap);
1543 } 1536 }
1626 1619
1627 readable_message_type *msgType = get_readable_message_type (tmp); 1620 readable_message_type *msgType = get_readable_message_type (tmp);
1628 1621
1629 if (player *pl = op->contr) 1622 if (player *pl = op->contr)
1630 if (client *ns = pl->ns) 1623 if (client *ns = pl->ns)
1631 if (ns->can_msg)
1632 pl->infobox (MSG_CHANNEL ("book"), format ("T<%s>\n\n%s", (char *)long_desc (tmp, op), &tmp->msg)); 1624 pl->infobox (MSG_CHANNEL ("book"), format ("T<%s>\n\n%s", (char *)long_desc (tmp, op), &tmp->msg));
1633 else
1634 draw_ext_info_format (NDI_UNIQUE | NDI_NAVY, 0, op,
1635 msgType->message_type, msgType->message_subtype,
1636 "You open the %s and start reading.\n%s", (char *)"%s\n%s",
1637 long_desc (tmp, op), &tmp->msg);
1638 1625
1639 /* gain xp from reading */ 1626 /* gain xp from reading */
1640 if (!QUERY_FLAG (tmp, FLAG_NO_SKILL_IDENT)) 1627 if (!QUERY_FLAG (tmp, FLAG_NO_SKILL_IDENT))
1641 { /* only if not read before */ 1628 { /* only if not read before */
1642 int exp_gain = calc_skill_exp (op, tmp, skill_ob); 1629 int exp_gain = calc_skill_exp (op, tmp, skill_ob);
2170 op->statusmsg (buf); 2157 op->statusmsg (buf);
2171 2158
2172 /* now choose a winner if we have any */ 2159 /* now choose a winner if we have any */
2173 i = -1; 2160 i = -1;
2174 if (winners > 0) 2161 if (winners > 0)
2175 i = atnr_winner[RANDOM () % winners]; 2162 i = atnr_winner [rndm (winners)];
2176 2163
2177 if (i >= 0 && i < NROFATTACKS && skin->resist[i] < 95) 2164 if (i >= 0 && i < NROFATTACKS && skin->resist[i] < 95)
2178 { 2165 {
2179 /* resistance increased! */ 2166 /* resistance increased! */
2180 skin->resist[i]++; 2167 skin->resist[i]++;
2355 2342
2356 return 0; 2343 return 0;
2357} 2344}
2358 2345
2359/** 2346/**
2347 * This function will try to apply a lighter and in case no lighter
2348 * is specified it will try to find a lighter in the players inventory,
2349 * and inform him about this requirement.
2350 *
2351 * who - the player
2352 * op - the item we want to light
2353 * ligher - the lighter or 0 if a lighter has yet to be found
2354 */
2355object *auto_apply_lighter (object *who, object *op, object *lighter)
2356{
2357 if (lighter == 0)
2358 {
2359 for (object *tmp = who->inv; tmp; tmp = tmp->below)
2360 {
2361 if (tmp->type == LIGHTER)
2362 {
2363 lighter = tmp;
2364 break;
2365 }
2366 }
2367
2368 if (!lighter)
2369 {
2370 who->failmsg (format (
2371 "You can't light up the %s with your bare hands! "
2372 "H<You need a lighter in your inventory, for example a flint and steel.>",
2373 &op->name));
2374 return 0;
2375 }
2376 }
2377
2378 // last_eat == 0 means the lighter is not being used up!
2379 if (lighter->last_eat && lighter->stats.food)
2380 {
2381 /* lighter gets used up */
2382 lighter = lighter->split ();
2383 lighter->stats.food--;
2384 who->insert (lighter);
2385 }
2386 else if (lighter->last_eat)
2387 {
2388 /* no charges left in lighter */
2389 who->failmsg (format (
2390 "You attempt to light the %s with a used up %s.",
2391 &op->name, &lighter->name));
2392 return 0;
2393 }
2394
2395 return lighter;
2396}
2397
2398/**
2399 * Designed primarily to light torches/lanterns/etc.
2400 * Also burns up burnable material too. First object in the inventory is
2401 * the selected object to "burn". -b.t.
2402 */
2403void
2404apply_lighter (object *who, object *lighter)
2405{
2406 object *item;
2407 int is_player_env = 0;
2408
2409 item = find_marked_object (who);
2410 if (item)
2411 {
2412 if (!auto_apply_lighter (who, 0, lighter))
2413 return;
2414
2415 /* Perhaps we should split what we are trying to light on fire?
2416 * I can't see many times when you would want to light multiple
2417 * objects at once.
2418 */
2419
2420 save_throw_object (item, AT_FIRE, who);
2421
2422 if (item->destroyed ()
2423 || ((item->type == LAMP || item->type == TORCH)
2424 && item->glow_radius > 0))
2425 who->statusmsg (format (
2426 "You light the %s with the %s.",
2427 &item->name, &lighter->name));
2428 else
2429 who->failmsg (format (
2430 "You attempt to light the %s with the %s and fail.",
2431 &item->name, &lighter->name));
2432 }
2433 else
2434 who->failmsg ("You need to mark a lightable object.");
2435}
2436
2437/**
2438 * Apply for players and lamps
2439 *
2440 * who - the player
2441 * op - the lamp
2442 */
2443void player_apply_lamp (object *who, object *op)
2444{
2445 bool switch_on = op->glow_radius ? false : true;
2446
2447 if (switch_on)
2448 {
2449 object *lighter = 0;
2450
2451 if (op->flag [FLAG_IS_LIGHTABLE]
2452 && !(lighter = auto_apply_lighter (who, op, 0)))
2453 return;
2454
2455 if (op->stats.food < 1)
2456 {
2457 if (op->type == LAMP)
2458 who->failmsg (format (
2459 "The %s is out of fuel! "
2460 "H<Lamps and similar items need fuel. They cannot be refilled.>",
2461 &op->name));
2462 else
2463 who->failmsg (format (
2464 "The %s is burnt out! "
2465 "H<Torches and similar items burn out and become worthless.>",
2466 &op->name));
2467 return;
2468 }
2469
2470 if (lighter)
2471 who->statusmsg (format (
2472 "You light up the %s with the %s.", &op->name, &lighter->name));
2473 else
2474 who->statusmsg (format ("You light up the %s.", &op->name));
2475 }
2476 else
2477 {
2478 if (op->type == TORCH)
2479 {
2480 if (!op->flag [FLAG_IS_LIGHTABLE])
2481 {
2482 who->statusmsg (format (
2483 "You put out the %s. "
2484 "H<The %s can't be used anymore, as it can't be lighted up again.>",
2485 &op->name, &op->name));
2486 }
2487 else
2488 who->statusmsg (format (
2489 "You put out the %s."
2490 "H<Torches wear out if you put them out.>",
2491 &op->name));
2492 }
2493 else
2494 who->statusmsg (format ("You turn off the %s.", &op->name));
2495 }
2496
2497 apply_lamp (op, switch_on);
2498}
2499
2500void lamp_get_animation_from_arch (object *op, arch_ptr a)
2501{
2502 op->animation_id = a->animation_id;
2503 op->flag [FLAG_IS_TURNABLE] = a->flag [FLAG_IS_TURNABLE];
2504 op->flag [FLAG_ANIMATE] = a->flag [FLAG_ANIMATE];
2505 op->anim_speed = a->anim_speed;
2506 op->last_anim = 0;
2507 op->state = 0;
2508 op->face = a->face;
2509
2510 if (NUM_ANIMATIONS(op) > 1)
2511 {
2512 SET_ANIMATION(op, 0);
2513 animate_object (op, op->direction);
2514 }
2515 else
2516 update_object (op, UP_OBJ_FACE);
2517}
2518
2519/**
2520 * Apply for LAMPs and TORCHes.
2521 *
2522 * op - the lamp
2523 * switch_on - a flag which says whether the lamp should be switched on or off
2524 */
2525void apply_lamp (object *op, bool switch_on)
2526{
2527 op->set_glow_radius (switch_on ? op->range : 0);
2528 op->set_speed (switch_on ? op->arch->speed : 0);
2529
2530 // torches wear out if you put them out
2531 if (op->type == TORCH && !switch_on)
2532 {
2533 if (op->flag [FLAG_IS_LIGHTABLE])
2534 {
2535 op->stats.food -= (double) op->arch->stats.food / 15;
2536 if (op->stats.food < 0)
2537 op->stats.food = 0;
2538 }
2539 else
2540 op->stats.food = 0;
2541 }
2542
2543 // lamps and torched get worthless when used up
2544 if (op->stats.food <= 0)
2545 op->value = 0;
2546
2547 // FIXME: This is a hack to make the more sane torches and lamps
2548 // still animated ;-/
2549 if (op->other_arch)
2550 lamp_get_animation_from_arch (op, switch_on ? op->other_arch : op->arch);
2551
2552 if (object *pl = op->visible_to ())
2553 esrv_update_item (UPD_ANIM | UPD_FACE | UPD_NAME, pl, op);
2554}
2555
2556/**
2360 * Main apply handler. 2557 * Main apply handler.
2361 * 2558 *
2362 * Checks for unpaid items before applying. 2559 * Checks for unpaid items before applying.
2363 * 2560 *
2364 * Return value: 2561 * Return value:
2365 * 0: player or monster can't apply objects of that type 2562 * 0: player or monster can't apply objects of that type
2366 * 1: has been applied, or there was an error applying the object 2563 * 1: has been applied, or there was an error applying the object
2367 * 2: objects of that type can't be applied if not in inventory 2564 * 2: objects of that type can't be applied if not in inventory
2368 * 2565 *
2369 * op is the object that is causing object to be applied, tmp is the object 2566 * who is the object that is causing object to be applied, op is the object
2370 * being applied. 2567 * being applied.
2371 * 2568 *
2372 * aflag is special (always apply/unapply) flags. Nothing is done with 2569 * aflag is special (always apply/unapply) flags. Nothing is done with
2373 * them in this function - they are passed to apply_special 2570 * them in this function - they are passed to apply_special
2374 */ 2571 */
2375int 2572int
2376manual_apply (object *op, object *tmp, int aflag) 2573manual_apply (object *who, object *op, int aflag)
2377{ 2574{
2378 tmp = tmp->head_ (); 2575 op = op->head_ ();
2379 2576
2380 if (QUERY_FLAG (tmp, FLAG_UNPAID) && !QUERY_FLAG (tmp, FLAG_APPLIED)) 2577 if (QUERY_FLAG (op, FLAG_UNPAID) && !QUERY_FLAG (op, FLAG_APPLIED))
2381 { 2578 {
2382 if (op->type == PLAYER) 2579 if (who->type == PLAYER)
2383 { 2580 {
2581 examine (who, op);
2384 op->failmsg ("You should pay for it first! H<You cannot use items marked as unpaid.>"); 2582 //who->failmsg ("You should pay for it first! H<You cannot use items marked as unpaid.>");//TODO remove
2385 return 1; 2583 return 1;
2386 } 2584 }
2387 else 2585 else
2388 return 0; /* monsters just skip unpaid items */ 2586 return 0; /* monsters just skip unpaid items */
2389 } 2587 }
2390 2588
2391 if (INVOKE_OBJECT (APPLY, tmp, ARG_OBJECT (op))) 2589 if (INVOKE_OBJECT (APPLY, op, ARG_OBJECT (who)))
2392 return RESULT_INT (0); 2590 return RESULT_INT (0);
2393 2591
2394 switch (tmp->type) 2592 switch (op->type)
2395 { 2593 {
2396 case CF_HANDLE: 2594 case CF_HANDLE:
2397 op->play_sound (sound_find ("turn_handle")); 2595 who->play_sound (sound_find ("turn_handle"));
2398 op->statusmsg ("You turn the handle."); 2596 who->statusmsg ("You turn the handle.");
2399 tmp->value = tmp->value ? 0 : 1; 2597 op->value = op->value ? 0 : 1;
2400 SET_ANIMATION (tmp, tmp->value); 2598 SET_ANIMATION (op, op->value);
2401 update_object (tmp, UP_OBJ_FACE); 2599 update_object (op, UP_OBJ_FACE);
2402 push_button (tmp); 2600 push_button (op, who);
2403 return 1; 2601 return 1;
2404 2602
2405 case TRIGGER: 2603 case TRIGGER:
2406 if (check_trigger (tmp, op)) 2604 if (check_trigger (op, who))
2407 { 2605 {
2408 op->statusmsg ("You turn the handle."); 2606 who->statusmsg ("You turn the handle.");
2409 op->play_sound (sound_find ("turn_handle")); 2607 who->play_sound (sound_find ("turn_handle"));
2410 } 2608 }
2411 else 2609 else
2412 op->failmsg ("The handle doesn't move."); 2610 who->failmsg ("The handle doesn't move.");
2413 2611
2414 return 1; 2612 return 1;
2415 2613
2416 case EXIT: 2614 case EXIT:
2417 if (op->type != PLAYER) 2615 if (who->type != PLAYER)
2418 return 0; 2616 return 0;
2419 2617
2420 if (!EXIT_PATH (tmp) || !is_legal_2ways_exit (op, tmp)) 2618 if (!EXIT_PATH (op) || !is_legal_2ways_exit (who, op))
2421 op->failmsg (format ("The %s is closed.", query_name (tmp))); 2619 who->failmsg (format ("The %s is closed.", query_name (op)));
2422 else 2620 else
2423 { 2621 {
2424 /* Don't display messages for random maps. */ 2622 /* Don't display messages for random maps. */
2425 if (tmp->msg && strncmp (EXIT_PATH (tmp), "/!", 2)) 2623 if (op->msg && !EXIT_PATH (op).starts_with ("/!"))
2426 op->statusmsg (tmp->msg, NDI_NAVY); 2624 who->statusmsg (op->msg, NDI_NAVY);
2427 2625
2428 op->enter_exit (tmp); 2626 who->enter_exit (op);
2429 } 2627 }
2430 2628
2431 return 1; 2629 return 1;
2432 2630
2433 case INSCRIBABLE: 2631 case INSCRIBABLE:
2434 op->statusmsg (tmp->msg); 2632 who->statusmsg (op->msg);
2435 // maybe show a spell menu to chose from or something like that 2633 // maybe show a spell menu to chose from or something like that
2436 return 1; 2634 return 1;
2437 2635
2438 case SIGN: 2636 case SIGN:
2439 apply_sign (op, tmp, 0); 2637 apply_sign (who, op, 0);
2440 return 1; 2638 return 1;
2441 2639
2442 case BOOK: 2640 case BOOK:
2443 if (op->type == PLAYER) 2641 if (who->type == PLAYER)
2444 { 2642 {
2445 apply_book (op, tmp); 2643 apply_book (who, op);
2446 return 1; 2644 return 1;
2447 } 2645 }
2448 else 2646 else
2449 return 0; 2647 return 0;
2450 2648
2451 case SKILLSCROLL: 2649 case SKILLSCROLL:
2452 if (op->type == PLAYER) 2650 if (who->type == PLAYER)
2453 { 2651 {
2454 apply_skillscroll (op, tmp); 2652 apply_skillscroll (who, op);
2455 return 1; 2653 return 1;
2456 } 2654 }
2457 else 2655 else
2458 return 0; 2656 return 0;
2459 2657
2460 case SPELLBOOK: 2658 case SPELLBOOK:
2461 if (op->type == PLAYER) 2659 if (who->type == PLAYER)
2462 { 2660 {
2463 apply_spellbook (op, tmp); 2661 apply_spellbook (who, op);
2464 return 1; 2662 return 1;
2465 } 2663 }
2466 else 2664 else
2467 return 0; 2665 return 0;
2468 2666
2469 case SCROLL: 2667 case SCROLL:
2470 apply_scroll (op, tmp, 0); 2668 apply_scroll (who, op, 0);
2471 return 1; 2669 return 1;
2472 2670
2473 case POTION: 2671 case POTION:
2474 apply_potion (op, tmp); 2672 apply_potion (who, op);
2475 return 1; 2673 return 1;
2476 2674
2477 /* Eneq(@csd.uu.se): Handle apply on containers. */ 2675 /* Eneq(@csd.uu.se): Handle apply on containers. */
2478 //TODO: remove, as it is unsed? 2676 //TODO: remove, as it is unsed?
2479 case CLOSE_CON: 2677 case CLOSE_CON:
2480 apply_container (op, tmp->env); 2678 apply_container (who, op->env);
2481 return 1; 2679 return 1;
2482 2680
2483 case CONTAINER: 2681 case CONTAINER:
2484 apply_container (op, tmp); 2682 apply_container (who, op);
2485 return 1; 2683 return 1;
2486 2684
2487 case TREASURE: 2685 case TREASURE:
2488 if (op->type == PLAYER) 2686 if (who->type == PLAYER)
2489 { 2687 {
2490 apply_treasure (op, tmp); 2688 apply_treasure (who, op);
2491 return 1; 2689 return 1;
2492 } 2690 }
2493 else 2691 else
2494 return 0; 2692 return 0;
2693
2694 case LAMP:
2695 case TORCH:
2696 player_apply_lamp (who, op);
2697 return 1;
2495 2698
2496 case WEAPON: 2699 case WEAPON:
2497 case ARMOUR: 2700 case ARMOUR:
2498 case BOOTS: 2701 case BOOTS:
2499 case GLOVES: 2702 case GLOVES:
2507 case WAND: 2710 case WAND:
2508 case ROD: 2711 case ROD:
2509 case HORN: 2712 case HORN:
2510 case SKILL: 2713 case SKILL:
2511 case BOW: 2714 case BOW:
2512 case LAMP:
2513 case BUILDER: 2715 case BUILDER:
2514 case SKILL_TOOL: 2716 case SKILL_TOOL:
2515 if (tmp->env != op) 2717 if (op->env != who)
2516 return 2; /* not in inventory */ 2718 return 2; /* not in inventory */
2517 2719
2518 apply_special (op, tmp, aflag); 2720 apply_special (who, op, aflag);
2519 return 1; 2721 return 1;
2520 2722
2521 case DRINK: 2723 case DRINK:
2522 case FOOD: 2724 case FOOD:
2523 case FLESH: 2725 case FLESH:
2524 apply_food (op, tmp); 2726 apply_food (who, op);
2525 return 1; 2727 return 1;
2526 2728
2527 case POISON: 2729 case POISON:
2528 apply_poison (op, tmp); 2730 apply_poison (who, op);
2529 return 1; 2731 return 1;
2530 2732
2531 case SAVEBED: 2733 case SAVEBED:
2532 return 1; 2734 return 1;
2533 2735
2534 case ARMOUR_IMPROVER: 2736 case ARMOUR_IMPROVER:
2535 if (op->type == PLAYER) 2737 if (who->type == PLAYER)
2536 { 2738 {
2537 apply_armour_improver (op, tmp); 2739 apply_armour_improver (who, op);
2538 return 1; 2740 return 1;
2539 } 2741 }
2540 else 2742 else
2541 return 0; 2743 return 0;
2542 2744
2543 case WEAPON_IMPROVER: 2745 case WEAPON_IMPROVER:
2544 check_improve_weapon (op, tmp); 2746 check_improve_weapon (who, op);
2545 return 1; 2747 return 1;
2546 2748
2547 case CLOCK: 2749 case CLOCK:
2548 if (op->type == PLAYER) 2750 if (who->type == PLAYER)
2549 { 2751 {
2550 char buf[MAX_BUF]; 2752 char buf[MAX_BUF];
2551 timeofday_t tod; 2753 timeofday_t tod;
2552 2754
2553 get_tod (&tod); 2755 get_tod (&tod);
2554 op->play_sound (sound_find ("sound_clock")); 2756 who->play_sound (sound_find ("sound_clock"));
2555 op->statusmsg (format ( 2757 who->statusmsg (format (
2556 "It is %d minute%s past %d o'clock %s", 2758 "It is %d minute%s past %d o'clock %s",
2557 tod.minute + 1, ((tod.minute + 1 < 2) ? "" : "s"), 2759 tod.minute + 1, ((tod.minute + 1 < 2) ? "" : "s"),
2558 ((tod.hour % 14 == 0) ? 14 : ((tod.hour) % 14)), ((tod.hour >= 14) ? "pm" : "am") 2760 ((tod.hour % 14 == 0) ? 14 : ((tod.hour) % 14)), ((tod.hour >= 14) ? "pm" : "am")
2559 )); 2761 ));
2560 return 1; 2762 return 1;
2561 } 2763 }
2562 else 2764 else
2563 return 0; 2765 return 0;
2564 2766
2565 case MENU: 2767 case MENU:
2566 if (op->type == PLAYER) 2768 if (who->type == PLAYER)
2567 { 2769 {
2568 shop_listing (tmp, op); 2770 shop_listing (op, who);
2569 return 1; 2771 return 1;
2570 } 2772 }
2571 else 2773 else
2572 return 0; 2774 return 0;
2573 2775
2574 case POWER_CRYSTAL: 2776 case POWER_CRYSTAL:
2575 apply_power_crystal (op, tmp); /* see egoitem.c */ 2777 apply_power_crystal (who, op); /* see egoitem.c */
2576 return 1; 2778 return 1;
2577 2779
2578 case LIGHTER: /* for lighting torches/lanterns/etc */ 2780 case LIGHTER: /* for lighting torches/lanterns/etc */
2579 if (op->type == PLAYER) 2781 if (who->type == PLAYER)
2580 { 2782 {
2581 apply_lighter (op, tmp); 2783 apply_lighter (who, op);
2582 return 1; 2784 return 1;
2583 } 2785 }
2584 else 2786 else
2585 return 0; 2787 return 0;
2586 2788
2587 case ITEM_TRANSFORMER: 2789 case ITEM_TRANSFORMER:
2588 apply_item_transformer (op, tmp); 2790 apply_item_transformer (who, op);
2589 return 1; 2791 return 1;
2590 2792
2591 default: 2793 default:
2592 return 0; 2794 return 0;
2593 } 2795 }
2660 * person moving on it, also activate. Added code to make it 2862 * person moving on it, also activate. Added code to make it
2661 * so that at least one of players movement types be that which 2863 * so that at least one of players movement types be that which
2662 * the item needs. 2864 * the item needs.
2663 */ 2865 */
2664 if (!tmp->invisible || (tmp->move_on & pl->move_type)) 2866 if (!tmp->invisible || (tmp->move_on & pl->move_type))
2665 {
2666 if (player_apply (pl, tmp, 0, 1) == 1) 2867 if (player_apply (pl, tmp, 0, 1) == 1)
2667 return; 2868 return;
2668 } 2869
2669 if (floors >= 2) 2870 if (floors >= 2)
2670 return; /* process at most two floor objects */ 2871 return; /* process at most two floor objects */
2671 } 2872 }
2672} 2873}
2673 2874
2745 case BRACERS: 2946 case BRACERS:
2746 case CLOAK: 2947 case CLOAK:
2747 who->statusmsg (format ("You unwear %s.", query_name (op))); 2948 who->statusmsg (format ("You unwear %s.", query_name (op)));
2748 change_abil (who, op); 2949 change_abil (who, op);
2749 break; 2950 break;
2750
2751 case LAMP:
2752 {
2753 who->statusmsg (format ("You turn off your %s.", &op->name));
2754
2755 object *tmp2 = arch_to_object (op->other_arch);
2756 tmp2->x = op->x;
2757 tmp2->y = op->y;
2758 tmp2->map = op->map;
2759 tmp2->below = op->below;
2760 tmp2->above = op->above;
2761 tmp2->stats.food = op->stats.food;
2762 CLEAR_FLAG (tmp2, FLAG_APPLIED);
2763
2764 if (QUERY_FLAG (op, FLAG_INV_LOCKED))
2765 SET_FLAG (tmp2, FLAG_INV_LOCKED);
2766
2767 op->destroy ();
2768 who->insert (tmp2);
2769 who->update_stats ();
2770
2771 if (who->contr)
2772 {
2773 if (QUERY_FLAG (op, FLAG_CURSED) || QUERY_FLAG (op, FLAG_DAMNED))
2774 {
2775 who->failmsg ("Oops, it feels deadly cold!");
2776 SET_FLAG (tmp2, FLAG_KNOWN_CURSED);
2777 }
2778 }
2779 }
2780
2781 return 1; /* otherwise, an attempt to drop causes problems */
2782 2951
2783 case BOW: 2952 case BOW:
2784 case WAND: 2953 case WAND:
2785 case ROD: 2954 case ROD:
2786 case HORN: 2955 case HORN:
3226 return 1; 3395 return 1;
3227 } 3396 }
3228 3397
3229 //TODO: this obviously fails for players using a shorter prefix 3398 //TODO: this obviously fails for players using a shorter prefix
3230 // i.e. "R" can use Ragnarok's sword. 3399 // i.e. "R" can use Ragnarok's sword.
3231 if (op->level && (strncmp (op->name, who->name, strlen (who->name)))) 3400 if (op->level && !op->name.starts_with (who->name))
3232 { 3401 {
3233 /* if the weapon does not have the name as the character, can't use it. */ 3402 /* if the weapon does not have the name as the character, can't use it. */
3234 /* (Ragnarok's sword attempted to be used by Foo: won't work) */ 3403 /* (Ragnarok's sword attempted to be used by Foo: won't work) */
3235 who->failmsg ("The weapon does not recognize you as its owner. H<Its name indicates that it belongs to somebody else.>"); 3404 who->failmsg ("The weapon does not recognize you as its owner. H<Its name indicates that it belongs to somebody else.>");
3236 3405
3270 case AMULET: 3439 case AMULET:
3271 SET_FLAG (op, FLAG_APPLIED); 3440 SET_FLAG (op, FLAG_APPLIED);
3272 who->statusmsg (format ("You wear %s.", query_name (op))); 3441 who->statusmsg (format ("You wear %s.", query_name (op)));
3273 change_abil (who, op); 3442 change_abil (who, op);
3274 break; 3443 break;
3275
3276 case LAMP:
3277 if (op->stats.food < 1)
3278 {
3279 who->failmsg (format (
3280 "Your %s is out of fuel! "
3281 "H<Lamps and similar items need fuel. They cannot be refilled.>",
3282 &op->name
3283 ));
3284 return 1;
3285 }
3286
3287 who->statusmsg (format ("You turn on your %s.", &op->name));
3288
3289 tmp2 = arch_to_object (op->other_arch);
3290 tmp2->stats.food = op->stats.food;
3291 SET_FLAG (tmp2, FLAG_APPLIED);
3292
3293 if (QUERY_FLAG (op, FLAG_INV_LOCKED))
3294 SET_FLAG (tmp2, FLAG_INV_LOCKED);
3295
3296 who->insert (tmp2);
3297
3298 /* Remove the old lantern */
3299 op->destroy ();
3300
3301 /* insert the portion that was split off */
3302 if (tmp)
3303 who->insert (tmp);
3304
3305 who->update_stats ();
3306
3307 if (QUERY_FLAG (op, FLAG_CURSED) || QUERY_FLAG (op, FLAG_DAMNED))
3308 if (who->type == PLAYER)
3309 {
3310 who->failmsg ("Oops, it feels deadly cold! H<Maybe it wasn't such a bright idea to apply this cursed/damned item.>");
3311 SET_FLAG (tmp2, FLAG_KNOWN_CURSED);
3312 }
3313
3314 return 0;
3315 3444
3316 case SKILL_TOOL: 3445 case SKILL_TOOL:
3317 // applying a skill tool also readies the skill 3446 // applying a skill tool also readies the skill
3318 SET_FLAG (op, FLAG_APPLIED); 3447 SET_FLAG (op, FLAG_APPLIED);
3319 3448
3409 insert_ob_in_ob (tmp, who); 3538 insert_ob_in_ob (tmp, who);
3410 3539
3411 return 1; 3540 return 1;
3412 } 3541 }
3413 3542
3414 if (op->level && (strncmp (op->name, who->name, strlen (who->name)))) 3543 if (op->level && !op->name.starts_with (who->name))
3415 { 3544 {
3416 who->failmsg ("The weapon does not recognize you as its owner. " 3545 who->failmsg ("The weapon does not recognize you as its owner. "
3417 "H<Its name indicates that it belongs to somebody else.>"); 3546 "H<Its name indicates that it belongs to somebody else.>");
3418 if (tmp) 3547 if (tmp)
3419 insert_ob_in_ob (tmp, who); 3548 insert_ob_in_ob (tmp, who);
3493 if (QUERY_FLAG (op, FLAG_CURSED) || QUERY_FLAG (op, FLAG_DAMNED)) 3622 if (QUERY_FLAG (op, FLAG_CURSED) || QUERY_FLAG (op, FLAG_DAMNED))
3494 if (who->type == PLAYER) 3623 if (who->type == PLAYER)
3495 { 3624 {
3496 who->failmsg ( 3625 who->failmsg (
3497 "Oops, it feels deadly cold! " 3626 "Oops, it feels deadly cold! "
3498 "H<Maybe it wasn't such a bright idea to apply this cursed/damned item.>" 3627 "H<Maybe it wasn't such a bright idea to apply this cursed or damned item.>"
3499 ); 3628 );
3500 SET_FLAG (op, FLAG_KNOWN_CURSED); 3629 SET_FLAG (op, FLAG_KNOWN_CURSED);
3501 } 3630 }
3502 3631
3503 if (object *pl = op->visible_to ()) 3632 if (object *pl = op->visible_to ())
3769 } 3898 }
3770 3899
3771 who->update_stats (); 3900 who->update_stats ();
3772} 3901}
3773 3902
3774/**
3775 * Designed primarily to light torches/lanterns/etc.
3776 * Also burns up burnable material too. First object in the inventory is
3777 * the selected object to "burn". -b.t.
3778 */
3779void
3780apply_lighter (object *who, object *lighter)
3781{
3782 object *item;
3783 int is_player_env = 0;
3784
3785 item = find_marked_object (who);
3786 if (item)
3787 {
3788 if (lighter->last_eat && lighter->stats.food)
3789 { /* lighter gets used up */
3790 object *oneLighter = lighter->split ();
3791 oneLighter->stats.food--;
3792 who->insert (oneLighter);
3793 }
3794 else if (lighter->last_eat)
3795 {
3796 /* no charges left in lighter */
3797 who->failmsg (format ("You attempt to light the %s with a used up %s.", &item->name, &lighter->name));
3798 return;
3799 }
3800
3801 /* Perhaps we should split what we are trying to light on fire?
3802 * I can't see many times when you would want to light multiple
3803 * objects at once.
3804 */
3805
3806 if (who == item->in_player ())
3807 is_player_env = 1;
3808
3809 save_throw_object (item, AT_FIRE, who);
3810
3811 if (item->destroyed ())
3812 {
3813 who->statusmsg (format ("You light the %s with the %s.", &item->name, &lighter->name));
3814 /* Need to update the player so that the players glow radius
3815 * gets changed.
3816 */
3817 if (is_player_env)
3818 who->update_stats ();
3819 }
3820 else
3821 who->failmsg (format ("You attempt to light the %s with the %s and fail.", &item->name, &lighter->name));
3822 }
3823 else
3824 who->failmsg ("You need to mark a lightable object.");
3825}
3826 3903
3827/** 3904/**
3828 * op made some mistake with a scroll, this takes care of punishment. 3905 * op made some mistake with a scroll, this takes care of punishment.
3829 * scroll_failure()- hacked directly from spell_failure 3906 * scroll_failure()- hacked directly from spell_failure
3830 */ 3907 */
3930 } 4007 }
3931 4008
3932 /* insert the randomitems from the change's treasurelist into 4009 /* insert the randomitems from the change's treasurelist into
3933 * the player ref: player.c 4010 * the player ref: player.c
3934 */ 4011 */
3935 if (change->randomitems != NULL) 4012 if (change->randomitems)
3936 give_initial_items (pl, change->randomitems); 4013 give_initial_items (pl, change->randomitems);
3937 4014
3938 /* set up the face, for some races. */ 4015 /* set up the face, for some races. */
3939 4016
3940 /* first, look for the force object banning 4017 /* first, look for the force object banning
3941 * changing the face. Certain races never change face with class. 4018 * changing the face. Certain races never change face with class.
3942 */ 4019 */
3943 for (walk = pl->inv; walk != NULL; walk = walk->below) 4020 for (walk = pl->inv; walk; walk = walk->below)
3944 if (!strcmp (walk->name, "NOCLASSFACECHANGE")) 4021 if (walk->name == shstr_NOCLASSFACECHANGE)
3945 flag_change_face = 0; 4022 flag_change_face = 0;
3946 4023
3947 if (flag_change_face) 4024 if (flag_change_face)
3948 { 4025 {
3949 pl->face = change->face; 4026 pl->face = change->face;
3951 pl->flag [FLAG_ANIMATE] = change->flag [FLAG_ANIMATE]; 4028 pl->flag [FLAG_ANIMATE] = change->flag [FLAG_ANIMATE];
3952 } 4029 }
3953 4030
3954 /* check the special case of can't use weapons */ 4031 /* check the special case of can't use weapons */
3955 /*if(QUERY_FLAG(change,FLAG_USE_WEAPON)) CLEAR_FLAG(pl,FLAG_USE_WEAPON); */ 4032 /*if(QUERY_FLAG(change,FLAG_USE_WEAPON)) CLEAR_FLAG(pl,FLAG_USE_WEAPON); */
3956 if (!strcmp (change->name, "monk")) 4033 if (change->name == shstr_monk)
3957 CLEAR_FLAG (pl, FLAG_USE_WEAPON); 4034 CLEAR_FLAG (pl, FLAG_USE_WEAPON);
3958 4035
3959 break; 4036 break;
3960 } 4037 }
3961 } 4038 }
3998 pl->failmsg (format ("You can't use the %s with your %s!", query_name (transformer), query_name (marked))); 4075 pl->failmsg (format ("You can't use the %s with your %s!", query_name (transformer), query_name (marked)));
3999 return; 4076 return;
4000 } 4077 }
4001 4078
4002 /* check whether they are compatible or not */ 4079 /* check whether they are compatible or not */
4003 find = strstr (marked->slaying, transformer->arch->archname); 4080 find = strstr (&marked->slaying, transformer->arch->archname);
4004 if (!find || (*(find + strlen (transformer->arch->archname)) != ':')) 4081 if (!find || (*(find + strlen (transformer->arch->archname)) != ':'))
4005 { 4082 {
4006 pl->failmsg (format ("You can't use the %s with your %s!", query_name (transformer), query_name (marked))); 4083 pl->failmsg (format ("You can't use the %s with your %s!", query_name (transformer), query_name (marked)));
4007 return; 4084 return;
4008 } 4085 }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines