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 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 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. |
… | |
… | |
262 | new_draw_info (NDI_UNIQUE, 0, op, "You don't have enough experience to create any food."); |
262 | new_draw_info (NDI_UNIQUE, 0, op, "You don't have enough experience to create any food."); |
263 | return 0; |
263 | return 0; |
264 | } |
264 | } |
265 | |
265 | |
266 | food_value /= at->stats.food; |
266 | food_value /= at->stats.food; |
267 | new_op = arch_to_object (at); |
267 | new_op = at->instance (); |
268 | new_op->nrof = food_value; |
268 | new_op->nrof = food_value; |
269 | |
269 | |
270 | new_op->value = 0; |
270 | new_op->value = 0; |
271 | if (new_op->nrof < 1) |
271 | if (new_op->nrof < 1) |
272 | new_op->nrof = 1; |
272 | new_op->nrof = 1; |
… | |
… | |
594 | for (int i = 0; i < NUM_STATS; i++) |
594 | for (int i = 0; i < NUM_STATS; i++) |
595 | if (tmp->stats.stat (i) < 0) |
595 | if (tmp->stats.stat (i) < 0) |
596 | buf.printf (" - Your %s is depleted by %d.\n", statname[i], -tmp->stats.stat (i)); |
596 | buf.printf (" - Your %s is depleted by %d.\n", statname[i], -tmp->stats.stat (i)); |
597 | } |
597 | } |
598 | |
598 | |
599 | if (is_dragon_pl (op)) |
599 | if (op->is_dragon ()) |
600 | /* now grab the 'dragon_ability'-force from the player's inventory */ |
600 | /* now grab the 'dragon_ability'-force from the player's inventory */ |
601 | for (tmp = op->inv; tmp; tmp = tmp->below) |
601 | for (tmp = op->inv; tmp; tmp = tmp->below) |
602 | { |
602 | { |
603 | if (tmp->type == FORCE && tmp->arch->archname == shstr_dragon_ability_force) |
603 | if (tmp->type == FORCE && tmp->arch->archname == shstr_dragon_ability_force) |
604 | { |
604 | { |
… | |
… | |
650 | new_draw_info (NDI_UNIQUE, 0, op, "Something is in the way."); |
650 | new_draw_info (NDI_UNIQUE, 0, op, "Something is in the way."); |
651 | return 0; |
651 | return 0; |
652 | } |
652 | } |
653 | |
653 | |
654 | if (spell_ob->other_arch) |
654 | if (spell_ob->other_arch) |
655 | tmp = arch_to_object (spell_ob->other_arch); |
655 | tmp = spell_ob->other_arch->instance (); |
656 | else if (spell_ob->race) |
656 | else if (spell_ob->race) |
657 | { |
657 | { |
658 | char buf1[MAX_BUF]; |
658 | char buf1[MAX_BUF]; |
659 | |
659 | |
660 | sprintf (buf1, spell_ob->race, dir); |
660 | sprintf (buf1, spell_ob->race, dir); |
… | |
… | |
664 | LOG (llevError, "summon_wall: Unable to find archetype %s\n", buf1); |
664 | LOG (llevError, "summon_wall: Unable to find archetype %s\n", buf1); |
665 | new_draw_info (NDI_UNIQUE, 0, op, "This spell is broken."); |
665 | new_draw_info (NDI_UNIQUE, 0, op, "This spell is broken."); |
666 | return 0; |
666 | return 0; |
667 | } |
667 | } |
668 | |
668 | |
669 | tmp = arch_to_object (at); |
669 | tmp = at->instance (); |
670 | } |
670 | } |
671 | else |
671 | else |
672 | { |
672 | { |
673 | LOG (llevError, "magic_wall: spell %s lacks other_arch\n", &spell_ob->name); |
673 | LOG (llevError, "magic_wall: spell %s lacks other_arch\n", &spell_ob->name); |
674 | return 0; |
674 | return 0; |
… | |
… | |
718 | return 0; |
718 | return 0; |
719 | } |
719 | } |
720 | |
720 | |
721 | /* If this is a spellcasting wall, need to insert the spell object */ |
721 | /* If this is a spellcasting wall, need to insert the spell object */ |
722 | if (tmp->other_arch && tmp->other_arch->type == SPELL) |
722 | if (tmp->other_arch && tmp->other_arch->type == SPELL) |
723 | insert_ob_in_ob (arch_to_object (tmp->other_arch), tmp); |
723 | insert_ob_in_ob (tmp->other_arch->instance (), tmp); |
724 | |
724 | |
725 | /* This code causes the wall to extend some distance in |
725 | /* This code causes the wall to extend some distance in |
726 | * each direction, or until an obstruction is encountered. |
726 | * each direction, or until an obstruction is encountered. |
727 | * posblocked and negblocked help determine how far the |
727 | * posblocked and negblocked help determine how far the |
728 | * created wall can extend, it won't go extend through |
728 | * created wall can extend, it won't go extend through |
… | |
… | |
748 | object *tmp2 = tmp->clone (); |
748 | object *tmp2 = tmp->clone (); |
749 | m->insert (tmp2, x, y, op); |
749 | m->insert (tmp2, x, y, op); |
750 | |
750 | |
751 | /* If this is a spellcasting wall, need to insert the spell object */ |
751 | /* If this is a spellcasting wall, need to insert the spell object */ |
752 | if (tmp2->other_arch && tmp2->other_arch->type == SPELL) |
752 | if (tmp2->other_arch && tmp2->other_arch->type == SPELL) |
753 | tmp2->insert (arch_to_object (tmp2->other_arch)); |
753 | tmp2->insert (tmp2->other_arch->instance ()); |
754 | |
754 | |
755 | } |
755 | } |
756 | else |
756 | else |
757 | posblocked = 1; |
757 | posblocked = 1; |
758 | |
758 | |
… | |
… | |
765 | { |
765 | { |
766 | object *tmp2 = tmp->clone (); |
766 | object *tmp2 = tmp->clone (); |
767 | m->insert (tmp2, x, y, op); |
767 | m->insert (tmp2, x, y, op); |
768 | |
768 | |
769 | if (tmp2->other_arch && tmp2->other_arch->type == SPELL) |
769 | if (tmp2->other_arch && tmp2->other_arch->type == SPELL) |
770 | tmp2->insert (arch_to_object (tmp2->other_arch)); |
770 | tmp2->insert (tmp2->other_arch->instance ()); |
771 | } |
771 | } |
772 | else |
772 | else |
773 | negblocked = 1; |
773 | negblocked = 1; |
774 | } |
774 | } |
775 | |
775 | |
… | |
… | |
1002 | tmp->stats.grace = tmp->stats.maxgrace; |
1002 | tmp->stats.grace = tmp->stats.maxgrace; |
1003 | success = 1; |
1003 | success = 1; |
1004 | new_draw_info (NDI_UNIQUE, 0, tmp, "You feel redeemed with your god!"); |
1004 | new_draw_info (NDI_UNIQUE, 0, tmp, "You feel redeemed with your god!"); |
1005 | } |
1005 | } |
1006 | |
1006 | |
1007 | if (spell->stats.food && tmp->stats.food < 999) |
1007 | if (spell->stats.food && tmp->stats.food < MAX_FOOD) |
1008 | { |
1008 | { |
1009 | tmp->stats.food += spell->stats.food; |
1009 | tmp->stats.food += spell->stats.food; |
1010 | |
1010 | min_it (tmp->stats.food, MAX_FOOD); |
1011 | if (tmp->stats.food > 999) |
|
|
1012 | tmp->stats.food = 999; |
|
|
1013 | |
1011 | |
1014 | success = 1; |
1012 | success = 1; |
1015 | /* We could do something a bit better like the messages for healing above */ |
1013 | /* We could do something a bit better like the messages for healing above */ |
1016 | new_draw_info (NDI_UNIQUE, 0, tmp, "You feel your belly fill with food"); |
1014 | new_draw_info (NDI_UNIQUE, 0, tmp, "You feel your belly fill with food"); |
1017 | } |
1015 | } |
… | |
… | |
1399 | for (int i = 0; i < sizeof (nugget) / sizeof (nugget [0]); ++i) |
1397 | for (int i = 0; i < sizeof (nugget) / sizeof (nugget [0]); ++i) |
1400 | if (int nrof = value / nugget [i]->value) |
1398 | if (int nrof = value / nugget [i]->value) |
1401 | { |
1399 | { |
1402 | value -= nrof * nugget[i]->value; |
1400 | value -= nrof * nugget[i]->value; |
1403 | |
1401 | |
1404 | object *tmp = arch_to_object (nugget[i]); |
1402 | object *tmp = nugget[i]->instance (); |
1405 | tmp->nrof = nrof; |
1403 | tmp->nrof = nrof; |
1406 | tmp->flag [FLAG_IDENTIFIED] = true; |
1404 | tmp->flag [FLAG_IDENTIFIED] = true; |
1407 | op->map->insert (tmp, x, y, op, 0); |
1405 | op->map->insert (tmp, x, y, op, 0); |
1408 | } |
1406 | } |
1409 | |
1407 | |
… | |
… | |
1545 | range = spell->range + SP_level_range_adjust (caster, spell); |
1543 | range = spell->range + SP_level_range_adjust (caster, spell); |
1546 | |
1544 | |
1547 | if (!skill) |
1545 | if (!skill) |
1548 | skill = caster; |
1546 | skill = caster; |
1549 | |
1547 | |
|
|
1548 | dynbuf buf; |
1550 | unordered_mapwalk (op, -range, -range, range, range) |
1549 | unordered_mapwalk (buf, op, -range, -range, range, range) |
1551 | { |
1550 | { |
1552 | /* For most of the detections, we only detect objects above the |
1551 | /* For most of the detections, we only detect objects above the |
1553 | * floor. But this is not true for show invisible. |
1552 | * floor. But this is not true for show invisible. |
1554 | * Basically, we just go and find the top object and work |
1553 | * Basically, we just go and find the top object and work |
1555 | * down - that is easier than working up. |
1554 | * down - that is easier than working up. |
… | |
… | |
1568 | floor = 0; |
1567 | floor = 0; |
1569 | detect = NULL; |
1568 | detect = NULL; |
1570 | for (tmp = last; tmp; tmp = tmp->below) |
1569 | for (tmp = last; tmp; tmp = tmp->below) |
1571 | { |
1570 | { |
1572 | /* show invisible */ |
1571 | /* show invisible */ |
1573 | if (QUERY_FLAG (spell, FLAG_MAKE_INVIS) && |
1572 | if (QUERY_FLAG (spell, FLAG_MAKE_INVIS) |
1574 | /* Might there be other objects that we can make visible? */ |
1573 | /* Might there be other objects that we can make visible? */ |
1575 | (tmp->invisible && (QUERY_FLAG (tmp, FLAG_MONSTER) |
1574 | && (tmp->invisible && (QUERY_FLAG (tmp, FLAG_MONSTER) |
1576 | || (tmp->type == PLAYER && !QUERY_FLAG (tmp, FLAG_WIZ)) |
1575 | || (tmp->type == PLAYER && !QUERY_FLAG (tmp, FLAG_WIZ)) |
1577 | || tmp->type == T_HANDLE |
1576 | || tmp->type == T_HANDLE |
1578 | || tmp->type == TRAPDOOR |
1577 | || tmp->type == TRAPDOOR |
1579 | || tmp->type == EXIT |
1578 | || tmp->type == EXIT |
1580 | || tmp->type == HOLE |
1579 | || tmp->type == HOLE |
1581 | || tmp->type == BUTTON |
1580 | || tmp->type == BUTTON |
1582 | || tmp->type == TELEPORTER |
1581 | || tmp->type == TELEPORTER |
1583 | || tmp->type == GATE |
1582 | || tmp->type == GATE |
1584 | || tmp->type == LOCKED_DOOR |
1583 | || tmp->type == LOCKED_DOOR |
1585 | || tmp->type == WEAPON |
1584 | || tmp->type == WEAPON |
1586 | || tmp->type == ALTAR |
1585 | || tmp->type == ALTAR |
1587 | || tmp->type == SIGN |
1586 | || tmp->type == SIGN |
1588 | || tmp->type == TRIGGER_PEDESTAL |
1587 | || tmp->type == TRIGGER_PEDESTAL |
1589 | || tmp->type == SPECIAL_KEY |
1588 | || tmp->type == SPECIAL_KEY |
1590 | || tmp->type == TREASURE |
1589 | || tmp->type == TREASURE |
1591 | || tmp->type == BOOK |
1590 | || tmp->type == BOOK |
1592 | || tmp->type == HOLY_ALTAR |
1591 | || tmp->type == HOLY_ALTAR |
1593 | || tmp->type == CONTAINER))) |
1592 | || tmp->type == CONTAINER))) |
1594 | { |
1593 | { |
1595 | if (random_roll (0, skill->level - 1, op, PREFER_HIGH) > level / 4) |
1594 | if (random_roll (0, skill->level - 1, op, PREFER_HIGH) > level / 4) |
1596 | { |
1595 | { |
1597 | tmp->invisible = 0; |
1596 | tmp->invisible = 0; |
1598 | done_one = 1; |
1597 | done_one = 1; |
… | |
… | |
1620 | /* detect magic */ |
1619 | /* detect magic */ |
1621 | if (QUERY_FLAG (spell, FLAG_KNOWN_MAGICAL) && |
1620 | if (QUERY_FLAG (spell, FLAG_KNOWN_MAGICAL) && |
1622 | !QUERY_FLAG (tmp, FLAG_KNOWN_MAGICAL) && !QUERY_FLAG (tmp, FLAG_IDENTIFIED) && is_magical (tmp)) |
1621 | !QUERY_FLAG (tmp, FLAG_KNOWN_MAGICAL) && !QUERY_FLAG (tmp, FLAG_IDENTIFIED) && is_magical (tmp)) |
1623 | { |
1622 | { |
1624 | SET_FLAG (tmp, FLAG_KNOWN_MAGICAL); |
1623 | SET_FLAG (tmp, FLAG_KNOWN_MAGICAL); |
1625 | /* make runes more visibile */ |
1624 | /* make runes more visible */ |
1626 | if (tmp->type == RUNE && tmp->attacktype & AT_MAGIC) |
1625 | if (tmp->type == RUNE && tmp->attacktype & AT_MAGIC) |
1627 | tmp->stats.Cha /= 4; |
1626 | tmp->stats.Cha /= 4; |
1628 | |
1627 | |
1629 | done_one = 1; |
1628 | done_one = 1; |
1630 | } |
1629 | } |
… | |
… | |
1656 | (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED))) |
1655 | (QUERY_FLAG (tmp, FLAG_CURSED) || QUERY_FLAG (tmp, FLAG_DAMNED))) |
1657 | { |
1656 | { |
1658 | SET_FLAG (tmp, FLAG_KNOWN_CURSED); |
1657 | SET_FLAG (tmp, FLAG_KNOWN_CURSED); |
1659 | done_one = 1; |
1658 | done_one = 1; |
1660 | } |
1659 | } |
|
|
1660 | |
|
|
1661 | // Do mining detection spell: |
|
|
1662 | if (spell->last_sp == 1) // 1 - detect any vein |
|
|
1663 | { |
|
|
1664 | if (tmp->type == VEIN) |
|
|
1665 | { |
|
|
1666 | if (tmp->other_arch) |
|
|
1667 | { |
|
|
1668 | if (!detect) |
|
|
1669 | detect = tmp->other_arch; |
|
|
1670 | done_one = 2; |
|
|
1671 | } |
|
|
1672 | else |
|
|
1673 | done_one = 1; |
|
|
1674 | } |
|
|
1675 | } |
1661 | } /* for stack of objects on this space */ |
1676 | } /* for stack of objects on this space */ |
1662 | |
1677 | |
1663 | /* Code here puts an effect of the spell on the space, so you can see |
1678 | /* Code here puts an effect of the spell on the space, so you can see |
1664 | * where the magic is. |
1679 | * where the magic is. |
1665 | */ |
1680 | */ |
1666 | if (done_one) |
1681 | if (done_one) |
1667 | { |
1682 | { |
1668 | object *detect_ob = arch_to_object (spell->other_arch); |
1683 | object *detect_ob = spell->other_arch->instance (); |
1669 | |
1684 | |
1670 | /* if this is set, we want to copy the face */ |
1685 | /* if this is set, we want to copy the face */ |
1671 | if (done_one == 2 && detect) |
1686 | if (done_one == 2 && detect) |
1672 | { |
1687 | { |
1673 | detect_ob->face = detect->face; |
1688 | detect_ob->face = detect->face; |
… | |
… | |
1677 | /* by default, the detect_ob is already animated */ |
1692 | /* by default, the detect_ob is already animated */ |
1678 | if (!QUERY_FLAG (detect, FLAG_ANIMATE)) |
1693 | if (!QUERY_FLAG (detect, FLAG_ANIMATE)) |
1679 | CLEAR_FLAG (detect_ob, FLAG_ANIMATE); |
1694 | CLEAR_FLAG (detect_ob, FLAG_ANIMATE); |
1680 | } |
1695 | } |
1681 | |
1696 | |
1682 | m->insert (detect_ob, nx, ny, op); |
1697 | m->insert (detect_ob, nx, ny, op, INS_ON_TOP); |
1683 | } |
1698 | } |
1684 | } /* for processing the surrounding spaces */ |
1699 | } /* for processing the surrounding spaces */ |
1685 | |
1700 | |
1686 | |
1701 | |
1687 | /* Now process objects in the players inventory if detect curse or magic */ |
1702 | /* Now process objects in the players inventory if detect curse or magic */ |
… | |
… | |
2030 | } |
2045 | } |
2031 | |
2046 | |
2032 | weapon = weapon->split (); |
2047 | weapon = weapon->split (); |
2033 | |
2048 | |
2034 | /* create the golem object */ |
2049 | /* create the golem object */ |
2035 | tmp = arch_to_object (spell->other_arch); |
2050 | tmp = spell->other_arch->instance (); |
2036 | |
2051 | |
2037 | /* if animated by a player, give the player control of the golem */ |
2052 | /* if animated by a player, give the player control of the golem */ |
2038 | CLEAR_FLAG (tmp, FLAG_MONSTER); |
2053 | CLEAR_FLAG (tmp, FLAG_MONSTER); |
2039 | tmp->stats.exp = 0; |
2054 | tmp->stats.exp = 0; |
2040 | add_friendly_object (tmp); |
2055 | add_friendly_object (tmp); |
… | |
… | |
2174 | |
2189 | |
2175 | new_aura = present_arch_in_ob (spell->other_arch, op); |
2190 | new_aura = present_arch_in_ob (spell->other_arch, op); |
2176 | if (new_aura) |
2191 | if (new_aura) |
2177 | refresh = 1; |
2192 | refresh = 1; |
2178 | else |
2193 | else |
2179 | new_aura = arch_to_object (spell->other_arch); |
2194 | new_aura = spell->other_arch->instance (); |
2180 | |
2195 | |
2181 | new_aura->duration = spell->duration + 10 * SP_level_duration_adjust (caster, spell); |
2196 | new_aura->duration = spell->duration + 10 * SP_level_duration_adjust (caster, spell); |
2182 | |
2197 | |
2183 | new_aura->stats.dam = spell->stats.dam + SP_level_dam_adjust (caster, spell); |
2198 | new_aura->stats.dam = spell->stats.dam + SP_level_dam_adjust (caster, spell); |
2184 | |
2199 | |
… | |
… | |
2249 | if (pos.normalise () && !(OB_TYPE_MOVE_BLOCK (env, pos->move_block))) |
2264 | if (pos.normalise () && !(OB_TYPE_MOVE_BLOCK (env, pos->move_block))) |
2250 | { |
2265 | { |
2251 | hit_map (aura, i, aura->attacktype, 0); |
2266 | hit_map (aura, i, aura->attacktype, 0); |
2252 | |
2267 | |
2253 | if (aura->other_arch) |
2268 | if (aura->other_arch) |
2254 | pos.insert (arch_to_object (aura->other_arch), aura); |
2269 | pos.insert (aura->other_arch->instance (), aura); |
2255 | } |
2270 | } |
2256 | } |
2271 | } |
2257 | |
2272 | |
2258 | /* put the aura back in the player's inventory */ |
2273 | /* put the aura back in the player's inventory */ |
2259 | env->insert (aura); |
2274 | env->insert (aura); |
… | |
… | |
2331 | } |
2346 | } |
2332 | |
2347 | |
2333 | if (!spell->other_arch) |
2348 | if (!spell->other_arch) |
2334 | return 0; |
2349 | return 0; |
2335 | |
2350 | |
2336 | object *tmp = arch_to_object (spell->other_arch); |
2351 | object *tmp = spell->other_arch->instance (); |
2337 | |
2352 | |
2338 | tmp->race = op->name; /*Save the owner of the rune */ |
2353 | tmp->race = op->name; /*Save the owner of the rune */ |
2339 | tmp->msg = msg; |
2354 | tmp->msg = msg; |
2340 | |
2355 | |
2341 | tmp->insert_at (op, op, INS_BELOW_ORIGINATOR); |
2356 | tmp->insert_at (op, op, INS_BELOW_ORIGINATOR); |