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,2008,2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team |
4 | * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012 Marc Alexander Lehmann / Robin Redeker / the Deliantra team |
5 | * Copyright (©) 2003 Mark Wedel & Crossfire Development Team |
5 | * Copyright (©) 2003 Mark Wedel & Crossfire Development Team |
6 | * Copyright (©) 1992 Frank Tore Johansen |
6 | * Copyright (©) 1992 Frank Tore Johansen |
7 | * |
7 | * |
8 | * Deliantra is free software: you can redistribute it and/or modify it under |
8 | * Deliantra is free software: you can redistribute it and/or modify it under |
9 | * the terms of the Affero GNU General Public License as published by the |
9 | * the terms of the Affero GNU General Public License as published by the |
10 | * Free Software Foundation, either version 3 of the License, or (at your |
10 | * Free Software Foundation, either version 3 of the License, or (at your |
11 | * 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 Affero GNU General Public License |
18 | * You should have received a copy of the Affero GNU General Public License |
19 | * and the GNU General Public License along with this program. If not, see |
19 | * and the GNU General Public License along with this program. If not, see |
20 | * <http://www.gnu.org/licenses/>. |
20 | * <http://www.gnu.org/licenses/>. |
21 | * |
21 | * |
22 | * 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> |
23 | */ |
23 | */ |
24 | |
24 | |
25 | #include <global.h> |
25 | #include <global.h> |
26 | #include <object.h> |
26 | #include <object.h> |
… | |
… | |
281 | |
281 | |
282 | /* For all the stacked objects at this point, attempt a steal */ |
282 | /* For all the stacked objects at this point, attempt a steal */ |
283 | for (; tmp; tmp = next) |
283 | for (; tmp; tmp = next) |
284 | { |
284 | { |
285 | next = tmp->below; |
285 | next = tmp->below; |
286 | /* Minor hack--for multi square beings - make sure we get |
286 | /* Minor hack--for multi square beings - make sure we get |
287 | * the 'head' coz 'tail' objects have no inventory! - b.t. |
287 | * the 'head' coz 'tail' objects have no inventory! - b.t. |
288 | */ |
288 | */ |
289 | if (tmp->head) |
289 | if (tmp->head) |
290 | tmp = tmp->head; |
290 | tmp = tmp->head; |
291 | |
291 | |
292 | if (tmp->type != PLAYER && !tmp->flag [FLAG_MONSTER]) |
292 | if (tmp->type != PLAYER && !tmp->flag [FLAG_MONSTER]) |
293 | continue; |
|
|
294 | |
|
|
295 | /* do not reveal hidden DMs */ |
|
|
296 | if (tmp->type == PLAYER && tmp->flag [FLAG_WIZ] && tmp->contr->hidden) |
|
|
297 | continue; |
293 | continue; |
298 | |
294 | |
299 | if (attempt_steal (tmp, op, skill)) |
295 | if (attempt_steal (tmp, op, skill)) |
300 | { |
296 | { |
301 | if (tmp->type == PLAYER) /* no xp for stealing from another player */ |
297 | if (tmp->type == PLAYER) /* no xp for stealing from another player */ |
… | |
… | |
355 | |
351 | |
356 | int |
352 | int |
357 | pick_lock (object *pl, int dir, object *skill) |
353 | pick_lock (object *pl, int dir, object *skill) |
358 | { |
354 | { |
359 | object *tmp; |
355 | object *tmp; |
360 | int x = pl->x + freearr_x[dir]; |
|
|
361 | int y = pl->y + freearr_y[dir]; |
|
|
362 | |
356 | |
363 | if (!dir) |
357 | if (!dir) |
364 | dir = pl->facing; |
358 | dir = pl->facing; |
365 | |
359 | |
|
|
360 | mapxy pos (pl); pos.move (dir); |
|
|
361 | |
366 | /* For all the stacked objects at this point find a door */ |
362 | /* For all the stacked objects at this point find a door */ |
367 | if (out_of_map (pl->map, x, y)) |
363 | if (!pos.normalise ()) |
368 | { |
364 | { |
369 | pl->failmsg ("There is no lock there."); |
365 | pl->failmsg ("There is no lock there."); |
370 | return 0; |
366 | return 0; |
371 | } |
367 | } |
372 | |
368 | |
373 | for (tmp = GET_MAP_OB (pl->map, x, y); tmp; tmp = tmp->above) |
369 | for (tmp = pos->bot; tmp; tmp = tmp->above) |
374 | if (tmp->type == DOOR || tmp->type == LOCKED_DOOR) |
370 | if (tmp->type == DOOR || tmp->type == LOCKED_DOOR) |
375 | break; |
371 | break; |
376 | |
372 | |
377 | if (!tmp) |
373 | if (!tmp) |
378 | { |
374 | { |
… | |
… | |
519 | } |
515 | } |
520 | |
516 | |
521 | for (tmp = GET_MAP_OB (m, x, y); tmp; tmp = tmp->above) |
517 | for (tmp = GET_MAP_OB (m, x, y); tmp; tmp = tmp->above) |
522 | { |
518 | { |
523 | /* Jump into creature */ |
519 | /* Jump into creature */ |
524 | if (tmp->flag [FLAG_MONSTER] |
520 | if (tmp->flag [FLAG_MONSTER] || tmp->type == PLAYER) |
525 | || (tmp->type == PLAYER && (!tmp->flag [FLAG_WIZ] || !tmp->contr->hidden))) |
|
|
526 | { |
521 | { |
527 | new_draw_info_format (NDI_UNIQUE, 0, pl, "You jump into %s%s.", tmp->type == PLAYER ? "" : "the ", &tmp->name); |
522 | new_draw_info_format (NDI_UNIQUE, 0, pl, "You jump into %s%s.", tmp->type == PLAYER ? "" : "the ", &tmp->name); |
528 | |
523 | |
529 | stop_jump (pl, i, spaces); |
524 | stop_jump (pl, i, spaces); |
530 | |
525 | |
… | |
… | |
587 | } |
582 | } |
588 | |
583 | |
589 | return attempt_jump (pl, dir, spaces, skill); |
584 | return attempt_jump (pl, dir, spaces, skill); |
590 | } |
585 | } |
591 | |
586 | |
592 | /* skill_ident() - this code is supposed to allow players to identify |
587 | /* skill_ident() - this code is supposed to allow players to identify |
593 | * classes of objects with the various "auto-ident" skills. Player must |
588 | * classes of objects with the various "auto-ident" skills. Player must |
594 | * have unidentified objects of the right type in order for the skill |
589 | * have unidentified objects of the right type in order for the skill |
595 | * to work. While multiple classes of objects may be identified, |
590 | * to work. While multiple classes of objects may be identified, |
596 | * this code is kind of yucky -- it would be nice to make it a bit |
591 | * this code is kind of yucky -- it would be nice to make it a bit |
597 | * more generalized. Right now, skill indices are embedded in this routine. |
592 | * more generalized. Right now, skill indices are embedded in this routine. |
598 | * Returns amount of experience gained (on successful ident). |
593 | * Returns amount of experience gained (on successful ident). |
599 | * - b.t. (thomas@astro.psu.edu) |
594 | * - b.t. (thomas@astro.psu.edu) |
600 | */ |
595 | */ |
601 | static int |
596 | static int |
602 | do_skill_detect_curse (object *pl, object *skill) |
597 | do_skill_detect_curse (object *pl, object *skill) |
603 | { |
598 | { |
604 | object *tmp; |
|
|
605 | int success = 0; |
599 | int success = 0; |
606 | |
600 | |
607 | for (tmp = pl->inv; tmp; tmp = tmp->below) |
601 | for (object *tmp = pl->inv; tmp; tmp = tmp->below) |
608 | if (!tmp->invisible |
602 | if (!tmp->invisible |
|
|
603 | && tmp->need_identify () |
609 | && !tmp->flag [FLAG_IDENTIFIED] && !tmp->flag [FLAG_KNOWN_CURSED] |
604 | && !tmp->flag [FLAG_IDENTIFIED] && !tmp->flag [FLAG_KNOWN_CURSED] |
610 | && (tmp->flag [FLAG_CURSED] || tmp->flag [FLAG_DAMNED]) && tmp->item_power < skill->level) |
605 | && (tmp->flag [FLAG_CURSED] || tmp->flag [FLAG_DAMNED]) |
|
|
606 | && tmp->item_power < skill->level) |
611 | { |
607 | { |
612 | tmp->set_flag (FLAG_KNOWN_CURSED); |
608 | tmp->set_flag (FLAG_KNOWN_CURSED); |
613 | esrv_update_item (UPD_FLAGS, pl, tmp); |
609 | esrv_update_item (UPD_FLAGS, pl, tmp); |
614 | success += calc_skill_exp (pl, tmp, skill); |
610 | success += calc_skill_exp (pl, tmp, skill); |
615 | } |
611 | } |
616 | |
612 | |
617 | /* Check ground, too, but only objects the player could pick up */ |
613 | /* Check ground, too, but only objects the player could pick up */ |
618 | for (tmp = GET_MAP_OB (pl->map, pl->x, pl->y); tmp; tmp = tmp->above) |
614 | for (object *tmp = GET_MAP_OB (pl->map, pl->x, pl->y); tmp; tmp = tmp->above) |
619 | if (can_pick (pl, tmp) && |
615 | if (can_pick (pl, tmp) |
620 | !tmp->flag [FLAG_IDENTIFIED] && |
616 | && tmp->need_identify () |
621 | !tmp->flag [FLAG_KNOWN_CURSED] |
617 | && !tmp->flag [FLAG_IDENTIFIED] && !tmp->flag [FLAG_KNOWN_CURSED] |
622 | && (tmp->flag [FLAG_CURSED] || tmp->flag [FLAG_DAMNED]) && tmp->item_power < skill->level) |
618 | && (tmp->flag [FLAG_CURSED] || tmp->flag [FLAG_DAMNED]) |
|
|
619 | && tmp->item_power < skill->level) |
623 | { |
620 | { |
624 | tmp->set_flag (FLAG_KNOWN_CURSED); |
621 | tmp->set_flag (FLAG_KNOWN_CURSED); |
625 | esrv_update_item (UPD_FLAGS, pl, tmp); |
622 | esrv_update_item (UPD_FLAGS, pl, tmp); |
626 | success += calc_skill_exp (pl, tmp, skill); |
623 | success += calc_skill_exp (pl, tmp, skill); |
627 | } |
624 | } |
… | |
… | |
630 | } |
627 | } |
631 | |
628 | |
632 | static int |
629 | static int |
633 | do_skill_detect_magic (object *pl, object *skill) |
630 | do_skill_detect_magic (object *pl, object *skill) |
634 | { |
631 | { |
635 | object *tmp; |
|
|
636 | int success = 0; |
632 | int success = 0; |
637 | |
633 | |
638 | for (tmp = pl->inv; tmp; tmp = tmp->below) |
634 | for (object *tmp = pl->inv; tmp; tmp = tmp->below) |
639 | if (!tmp->invisible |
635 | if (!tmp->invisible |
|
|
636 | && tmp->need_identify () |
640 | && !tmp->flag [FLAG_IDENTIFIED] && !tmp->flag [FLAG_KNOWN_MAGICAL] |
637 | && !tmp->flag [FLAG_IDENTIFIED] && !tmp->flag [FLAG_KNOWN_MAGICAL] |
|
|
638 | && is_magical (tmp) |
641 | && (is_magical (tmp)) && tmp->item_power < skill->level) |
639 | && tmp->item_power < skill->level) |
642 | { |
640 | { |
643 | tmp->set_flag (FLAG_KNOWN_MAGICAL); |
641 | tmp->set_flag (FLAG_KNOWN_MAGICAL); |
644 | esrv_update_item (UPD_FLAGS, pl, tmp); |
642 | esrv_update_item (UPD_FLAGS, pl, tmp); |
645 | success += calc_skill_exp (pl, tmp, skill); |
643 | success += calc_skill_exp (pl, tmp, skill); |
646 | } |
644 | } |
647 | |
645 | |
648 | /* Check ground, too, but like above, only if the object can be picked up */ |
646 | /* Check ground, too, but like above, only if the object can be picked up */ |
649 | for (tmp = GET_MAP_OB (pl->map, pl->x, pl->y); tmp; tmp = tmp->above) |
647 | for (object *tmp = GET_MAP_OB (pl->map, pl->x, pl->y); tmp; tmp = tmp->above) |
650 | if (can_pick (pl, tmp) && |
648 | if (can_pick (pl, tmp) |
651 | !tmp->flag [FLAG_IDENTIFIED] && !tmp->flag [FLAG_KNOWN_MAGICAL] && (is_magical (tmp)) && tmp->item_power < skill->level) |
649 | && tmp->need_identify () |
|
|
650 | && !tmp->flag [FLAG_IDENTIFIED] && !tmp->flag [FLAG_KNOWN_MAGICAL] |
|
|
651 | && is_magical (tmp) |
|
|
652 | && tmp->item_power < skill->level) |
652 | { |
653 | { |
653 | tmp->set_flag (FLAG_KNOWN_MAGICAL); |
654 | tmp->set_flag (FLAG_KNOWN_MAGICAL); |
654 | esrv_update_item (UPD_FLAGS, pl, tmp); |
655 | esrv_update_item (UPD_FLAGS, pl, tmp); |
655 | success += calc_skill_exp (pl, tmp, skill); |
656 | success += calc_skill_exp (pl, tmp, skill); |
656 | } |
657 | } |
… | |
… | |
665 | do_skill_ident2 (object *tmp, object *pl, int obj_class, object *skill) |
666 | do_skill_ident2 (object *tmp, object *pl, int obj_class, object *skill) |
666 | { |
667 | { |
667 | int success = 0, chance; |
668 | int success = 0, chance; |
668 | int skill_value = skill->level * pl->stats.Int ? pl->stats.Int : 10; |
669 | int skill_value = skill->level * pl->stats.Int ? pl->stats.Int : 10; |
669 | |
670 | |
670 | if (!tmp->flag [FLAG_IDENTIFIED] && !tmp->flag [FLAG_NO_SKILL_IDENT] |
671 | if (!tmp->flag [FLAG_IDENTIFIED] |
671 | && tmp->need_identify () && !tmp->invisible && tmp->type == obj_class) |
672 | && !tmp->flag [FLAG_NO_SKILL_IDENT] |
|
|
673 | && tmp->need_identify () |
|
|
674 | && !tmp->invisible |
|
|
675 | && tmp->type == obj_class) |
672 | { |
676 | { |
673 | chance = die_roll (3, 10, pl, PREFER_LOW) - 3 + rndm (0, (tmp->magic ? tmp->magic * 5 : 1) - 1); |
677 | chance = die_roll (3, 10, pl, PREFER_LOW) - 3 + rndm (0, (tmp->magic ? tmp->magic * 5 : 1) - 1); |
674 | |
678 | |
675 | if (skill_value >= chance) |
679 | if (skill_value >= chance) |
676 | { |
680 | { |
… | |
… | |
770 | break; |
774 | break; |
771 | |
775 | |
772 | default: |
776 | default: |
773 | LOG (llevError, "Error: bad call to skill_ident()\n"); |
777 | LOG (llevError, "Error: bad call to skill_ident()\n"); |
774 | return 0; |
778 | return 0; |
775 | break; |
|
|
776 | } |
779 | } |
777 | |
780 | |
778 | if (!success) |
781 | if (!success) |
779 | new_draw_info (NDI_UNIQUE, 0, pl, "... and learn nothing more."); |
782 | new_draw_info (NDI_UNIQUE, 0, pl, "... and learn nothing more."); |
780 | |
783 | |
… | |
… | |
922 | * of anything better! -b.t. |
925 | * of anything better! -b.t. |
923 | */ |
926 | */ |
924 | int |
927 | int |
925 | singing (object *pl, int dir, object *skill) |
928 | singing (object *pl, int dir, object *skill) |
926 | { |
929 | { |
927 | int i, exp = 0; |
930 | int exp = 0; |
928 | object *tmp; |
931 | object *tmp; |
929 | maptile *m; |
932 | maptile *m; |
930 | sint16 x, y; |
933 | sint16 x, y; |
931 | |
934 | |
932 | if (pl->type != PLAYER) |
935 | if (pl->type != PLAYER) |
… | |
… | |
1205 | |
1208 | |
1206 | /* ok let's meditate! Spell points are regained first, then once |
1209 | /* ok let's meditate! Spell points are regained first, then once |
1207 | * they are maxed we get back hp. Actual incrementing of values |
1210 | * they are maxed we get back hp. Actual incrementing of values |
1208 | * is handled by the do_some_living() (in player.c). This way magical |
1211 | * is handled by the do_some_living() (in player.c). This way magical |
1209 | * bonuses for healing/sp regeneration are included properly |
1212 | * bonuses for healing/sp regeneration are included properly |
1210 | * No matter what, we will eat up some playing time trying to |
1213 | * No matter what, we will eat up some playing time trying to |
1211 | * meditate. (see 'factor' variable for what sets the amount of time) |
1214 | * meditate. (see 'factor' variable for what sets the amount of time) |
1212 | */ |
1215 | */ |
1213 | |
1216 | |
1214 | new_draw_info (NDI_BLACK, 0, pl, "You meditate."); |
1217 | new_draw_info (NDI_BLACK, 0, pl, "You meditate."); |
1215 | |
1218 | |
1216 | if (pl->stats.sp < pl->stats.maxsp) |
1219 | if (pl->stats.sp < pl->stats.maxsp) |
… | |
… | |
1223 | pl->stats.hp++; |
1226 | pl->stats.hp++; |
1224 | pl->last_heal = -1; |
1227 | pl->last_heal = -1; |
1225 | } |
1228 | } |
1226 | } |
1229 | } |
1227 | |
1230 | |
1228 | /* write_note() - this routine allows players to inscribe messages in |
1231 | /* write_note() - this routine allows players to inscribe messages in |
1229 | * ordinary inscribable 'books' (anything that is not a SPELL). b.t. |
1232 | * ordinary inscribable 'books' (anything that is not a SPELL). b.t. |
1230 | */ |
1233 | */ |
1231 | static int |
1234 | static int |
1232 | write_note (object *pl, object *item, const char *msg, object *skill) |
1235 | write_note (object *pl, object *item, const char *msg, object *skill) |
1233 | { |
1236 | { |
… | |
… | |
1278 | return 0; |
1281 | return 0; |
1279 | } |
1282 | } |
1280 | |
1283 | |
1281 | /* write_scroll() - this routine allows players to inscribe spell scrolls |
1284 | /* write_scroll() - this routine allows players to inscribe spell scrolls |
1282 | * of spells which they know. Backfire effects are possible with the |
1285 | * of spells which they know. Backfire effects are possible with the |
1283 | * severity of the backlash correlated with the difficulty of the scroll |
1286 | * severity of the backlash correlated with the difficulty of the scroll |
1284 | * that is attempted. -b.t. thomas@astro.psu.edu |
1287 | * that is attempted. -b.t. thomas@astro.psu.edu |
1285 | */ |
1288 | */ |
1286 | static int |
1289 | static int |
1287 | write_scroll (object *pl, object *scroll, object *skill) |
1290 | write_scroll (object *pl, object *scroll, object *skill) |
1288 | { |
1291 | { |
… | |
… | |
1320 | if (random_roll (0, chosen_spell->level * 4 - 1, pl, PREFER_LOW) < skill->level) |
1323 | if (random_roll (0, chosen_spell->level * 4 - 1, pl, PREFER_LOW) < skill->level) |
1321 | { |
1324 | { |
1322 | object *newscroll = scroll->other_arch->instance (); |
1325 | object *newscroll = scroll->other_arch->instance (); |
1323 | scroll->decrease (); |
1326 | scroll->decrease (); |
1324 | newscroll->nrof = 1; |
1327 | newscroll->nrof = 1; |
|
|
1328 | newscroll->randomitems = 0; // make sure randomitems doesn't destroy the scroll |
1325 | |
1329 | |
1326 | pl->contr->play_sound (sound_find ("inscribe_success")); |
1330 | pl->contr->play_sound (sound_find ("inscribe_success")); |
1327 | |
1331 | |
1328 | if (!confused) |
1332 | if (!confused) |
1329 | { |
1333 | { |
… | |
… | |
1340 | newscroll->level = max (skill->level, chosen_spell->level); |
1344 | newscroll->level = max (skill->level, chosen_spell->level); |
1341 | new_draw_info (NDI_UNIQUE, 0, pl, "In your confused state, you write down some odd spell."); |
1345 | new_draw_info (NDI_UNIQUE, 0, pl, "In your confused state, you write down some odd spell."); |
1342 | } |
1346 | } |
1343 | |
1347 | |
1344 | object *tmp = chosen_spell->clone (); |
1348 | object *tmp = chosen_spell->clone (); |
|
|
1349 | tmp->flag [FLAG_APPLIED] = false; |
1345 | insert_ob_in_ob (tmp, newscroll); |
1350 | insert_ob_in_ob (tmp, newscroll); |
1346 | |
1351 | |
1347 | /* Same code as from treasure.C - so they can better merge. |
1352 | /* Same code as from treasure.C - so they can better merge. |
1348 | * if players want to sell them, so be it. |
1353 | * if players want to sell them, so be it. |
1349 | */ |
1354 | */ |
… | |
… | |
1784 | throw_ob->map = part->map; |
1789 | throw_ob->map = part->map; |
1785 | |
1790 | |
1786 | throw_ob->move_type = MOVE_FLY_LOW; |
1791 | throw_ob->move_type = MOVE_FLY_LOW; |
1787 | throw_ob->move_on = MOVE_FLY_LOW | MOVE_WALK; |
1792 | throw_ob->move_on = MOVE_FLY_LOW | MOVE_WALK; |
1788 | |
1793 | |
|
|
1794 | throw_ob->set_speed (throw_ob->speed); |
|
|
1795 | |
1789 | #if 0 |
1796 | #if 0 |
1790 | /* need to put in a good sound for this */ |
1797 | /* need to put in a good sound for this */ |
1791 | play_sound_map (op->map, op->x, op->y, SOUND_THROW_OBJ); |
1798 | play_sound_map (op->map, op->x, op->y, SOUND_THROW_OBJ); |
1792 | #endif |
1799 | #endif |
1793 | |
1800 | |
… | |
… | |
1819 | throw_ob = find_mon_throw_ob (op); |
1826 | throw_ob = find_mon_throw_ob (op); |
1820 | |
1827 | |
1821 | return do_throw (op, part, throw_ob, dir, skill); |
1828 | return do_throw (op, part, throw_ob, dir, skill); |
1822 | } |
1829 | } |
1823 | |
1830 | |
|
|
1831 | static void |
|
|
1832 | give_player_quad_material_for (object *pl, object *ob) |
|
|
1833 | { |
|
|
1834 | if (!ob->flag [FLAG_IS_QUAD] || !ob->other_arch) |
|
|
1835 | return; |
|
|
1836 | |
|
|
1837 | object *t = ob->other_arch->instance (); |
|
|
1838 | pl->insert (t); |
|
|
1839 | } |
|
|
1840 | |
1824 | bool |
1841 | bool |
1825 | skill_mining (object *who, object *tool, object *skill, int dir, const char *string) |
1842 | skill_mining (object *who, object *tool, object *skill, int dir, const char *string) |
1826 | { |
1843 | { |
1827 | if (!who->is_player ()) |
1844 | if (!who->is_player ()) |
1828 | return 0; |
1845 | return 0; |
… | |
… | |
1845 | return 0; |
1862 | return 0; |
1846 | } |
1863 | } |
1847 | |
1864 | |
1848 | mapspace &ms = pos.ms (); |
1865 | mapspace &ms = pos.ms (); |
1849 | |
1866 | |
1850 | for (object *vein = pos.ms ().top; vein; vein = vein->below) |
1867 | for (object *mine_obj = pos.ms ().top; mine_obj; mine_obj = mine_obj->below) |
1851 | if (vein->type == VEIN) |
1868 | if (mine_obj->type == VEIN) |
1852 | { |
1869 | { |
1853 | who->speed_left -= who->speed / tool->speed; |
1870 | who->speed_left -= who->speed / tool->speed; |
1854 | |
1871 | |
1855 | who->play_sound (tool->sound); |
1872 | who->play_sound (tool->sound); |
1856 | |
1873 | |
1857 | if (rndm (100 - vein->stats.ac) > rndm (tool->stats.wc)) |
1874 | if (rndm (100 - mine_obj->stats.ac) > rndm (tool->stats.wc)) |
1858 | who->failmsgf ( |
1875 | who->failmsgf ( |
1859 | "You use your %s.... nothing. " |
1876 | "You use your %s.... nothing. " |
1860 | "H<Try again, perhaps?>", |
1877 | "H<Try again, perhaps?>", |
1861 | &tool->name |
1878 | &tool->name |
1862 | ); |
1879 | ); |
1863 | else if (vein->race != tool->race) |
1880 | else if (mine_obj->race != tool->race) |
1864 | who->failmsgf ( |
1881 | who->failmsgf ( |
1865 | "You use your %s.... but it doesn't work. " |
1882 | "You use your %s.... but it doesn't work. " |
1866 | "H<Maybe you are using the wrong tool?>", |
1883 | "H<Maybe you are using the wrong tool?>", |
1867 | &tool->name |
1884 | &tool->name |
1868 | ); |
1885 | ); |
1869 | else if (!vein->stats.food) |
1886 | else if (!mine_obj->stats.food) |
1870 | who->failmsgf ( |
1887 | who->failmsgf ( |
1871 | "You use your %s.... but there is nothing. " |
1888 | "You use your %s.... but there is nothing. " |
1872 | "H<This space is exhausted, you should try somewhere else.>", |
1889 | "H<This space is exhausted, you should try somewhere else.>", |
1873 | &tool->name |
1890 | &tool->name |
1874 | ); |
1891 | ); |
1875 | else |
1892 | else |
1876 | { |
1893 | { |
1877 | --vein->stats.food; |
1894 | --mine_obj->stats.food; |
1878 | |
1895 | |
1879 | object *ore = vein->other_arch->instance (); |
1896 | object *ore = mine_obj->other_arch->instance (); |
1880 | |
1897 | |
1881 | who->statusmsg (format ( |
1898 | who->statusmsg (format ( |
1882 | "You use your %s.... and find some %s!", |
1899 | "You use your %s.... and find some %s!", |
1883 | &tool->name, &ore->name |
1900 | &tool->name, &ore->name |
1884 | )); |
1901 | )); |
… | |
… | |
1886 | ore->insert_at (who); |
1903 | ore->insert_at (who); |
1887 | |
1904 | |
1888 | return true; |
1905 | return true; |
1889 | } |
1906 | } |
1890 | } |
1907 | } |
|
|
1908 | else if (mine_obj->flag [FLAG_IS_QUAD]) |
|
|
1909 | { |
|
|
1910 | if (mine_obj->flag [FLAG_IS_FLOOR]) |
|
|
1911 | { |
|
|
1912 | maptile *lower_floor = pos.m->tile_available (TILE_DOWN); |
|
|
1913 | |
|
|
1914 | if (!lower_floor) |
|
|
1915 | { |
|
|
1916 | who->failmsgf ( |
|
|
1917 | "Whoops, you failed to remove the %s. H<You may try again.>", |
|
|
1918 | &mine_obj->name |
|
|
1919 | ); |
|
|
1920 | return false; |
|
|
1921 | } |
|
|
1922 | |
|
|
1923 | mapxy below_pos (lower_floor, pos.x, pos.y); |
|
|
1924 | |
|
|
1925 | if (!below_pos.normalise ()) |
|
|
1926 | { |
|
|
1927 | who->failmsgf ( |
|
|
1928 | "Whoops, you failed to remove the %s. H<You may try again.>", |
|
|
1929 | &mine_obj->name |
|
|
1930 | ); |
|
|
1931 | return false; |
|
|
1932 | } |
|
|
1933 | |
|
|
1934 | // first insert open space here: |
|
|
1935 | object *open_space_floor = archetype::get (shstr_quad_open_space); |
|
|
1936 | open_space_floor->stats.hp = pos.x; |
|
|
1937 | open_space_floor->stats.sp = pos.y; |
|
|
1938 | insert_ob_in_map_at (open_space_floor, pos.m, mine_obj, |
|
|
1939 | INS_BELOW_ORIGINATOR, pos.x, pos.y); |
|
|
1940 | |
|
|
1941 | // next we will remove the wall in the lower layer: |
|
|
1942 | mapspace &below_ms = below_pos.ms (); |
|
|
1943 | for (object *quad_obj = below_ms.top; quad_obj; quad_obj = quad_obj->below) |
|
|
1944 | { |
|
|
1945 | if (quad_obj->flag [FLAG_IS_FLOOR]) |
|
|
1946 | break; |
|
|
1947 | |
|
|
1948 | if (quad_obj->flag [FLAG_IS_QUAD]) |
|
|
1949 | { |
|
|
1950 | quad_obj->map->queue_physics_at (quad_obj->x, quad_obj->y); |
|
|
1951 | give_player_quad_material_for (who, quad_obj); |
|
|
1952 | quad_obj->destroy (); |
|
|
1953 | break; |
|
|
1954 | } |
|
|
1955 | } |
|
|
1956 | } |
|
|
1957 | |
|
|
1958 | mine_obj->map->queue_physics_at (mine_obj->x, mine_obj->y); |
|
|
1959 | |
|
|
1960 | // FIXME: there should be chance assigned, like above with veins! |
|
|
1961 | who->play_sound (tool->sound); |
|
|
1962 | give_player_quad_material_for (who, mine_obj); |
|
|
1963 | mine_obj->destroy (); |
|
|
1964 | who->contr->fire_on = 0; // TODO: stopgap, do not remove more than one per keypress |
|
|
1965 | return true; |
|
|
1966 | } |
1891 | |
1967 | |
1892 | return false; |
1968 | return false; |
1893 | } |
1969 | } |
1894 | |
1970 | |