1 | /* |
1 | /* |
2 | * CrossFire, A Multiplayer game for X-windows |
2 | * This file is part of Crossfire TRT, the Roguelike Realtime MORPG. |
3 | * |
3 | * |
4 | * Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team |
4 | * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team |
5 | * Copyright (C) 2003 Mark Wedel & Crossfire Development Team |
5 | * Copyright (©) 2003,2007 Mark Wedel & Crossfire Development Team |
6 | * Copyright (C) 1992 Frank Tore Johansen |
6 | * Copyright (©) 1992,2007 Frank Tore Johansen |
7 | * |
7 | * |
8 | * This program is free software; you can redistribute it and/or modify |
8 | * Crossfire TRT is free software; you can redistribute it and/or modify it |
9 | * it under the terms of the GNU General Public License as published by |
9 | * under the terms of the GNU General Public License as published by the Free |
10 | * the Free Software Foundation; either version 2 of the License, or |
10 | * Software Foundation; either version 2 of the License, or (at your option) |
11 | * (at your option) any later version. |
11 | * 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, but |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
16 | * GNU General Public License for more details. |
16 | * 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 along |
19 | * along with this program; if not, write to the Free Software |
19 | * with Crossfire TRT; if not, write to the Free Software Foundation, Inc. 51 |
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
20 | * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
21 | * |
21 | * |
22 | * The authors can be reached via e-mail to <crossfire@schmorp.de> |
22 | * The authors can be reached via e-mail to <crossfire@schmorp.de> |
23 | */ |
23 | */ |
24 | |
24 | |
25 | #include <global.h> |
25 | #include <global.h> |
26 | #include <object.h> |
26 | #include <object.h> |
… | |
… | |
40 | return -1; |
40 | return -1; |
41 | |
41 | |
42 | /* Only prohibit stealing if the player does not have a free |
42 | /* Only prohibit stealing if the player does not have a free |
43 | * hand available and in fact does have hands. |
43 | * hand available and in fact does have hands. |
44 | */ |
44 | */ |
45 | if (op->type == PLAYER && op->slot[BODY_ARMS].used <= 0 && op->slot[BODY_ARMS].info) |
45 | if (op->type == PLAYER && op->slot[body_arm].used <= 0 && op->slot[body_arm].info) |
46 | { |
46 | { |
47 | new_draw_info (NDI_UNIQUE, 0, op, "But you have no free hands to steal with!"); |
47 | new_draw_info (NDI_UNIQUE, 0, op, "But you have no free hands to steal with!"); |
48 | return -1; |
48 | return -1; |
49 | } |
49 | } |
50 | |
50 | |
… | |
… | |
93 | * or not. |
93 | * or not. |
94 | * op is the target (person being pilfered) |
94 | * op is the target (person being pilfered) |
95 | * who is the person doing the stealing. |
95 | * who is the person doing the stealing. |
96 | * skill is the skill object (stealing). |
96 | * skill is the skill object (stealing). |
97 | */ |
97 | */ |
98 | |
|
|
99 | static int |
98 | static int |
100 | attempt_steal (object *op, object *who, object *skill) |
99 | attempt_steal (object *op, object *who, object *skill) |
101 | { |
100 | { |
102 | object *success = NULL, *tmp = NULL, *next; |
101 | object *success = NULL, *tmp = NULL, *next; |
103 | int roll = 0, chance = 0, stats_value; |
102 | int roll = 0, chance = 0, stats_value; |
… | |
… | |
121 | else /* help npc to detect thief next time by raising its wisdom */ |
120 | else /* help npc to detect thief next time by raising its wisdom */ |
122 | op->stats.Wis += (op->stats.Int / 5) + 1; |
121 | op->stats.Wis += (op->stats.Int / 5) + 1; |
123 | if (op->stats.Wis > MAX_STAT) |
122 | if (op->stats.Wis > MAX_STAT) |
124 | op->stats.Wis = MAX_STAT; |
123 | op->stats.Wis = MAX_STAT; |
125 | } |
124 | } |
|
|
125 | |
126 | if (op->type == PLAYER && QUERY_FLAG (op, FLAG_WIZ)) |
126 | if (op->type == PLAYER && QUERY_FLAG (op, FLAG_WIZ)) |
127 | { |
127 | { |
128 | new_draw_info (NDI_UNIQUE, 0, who, "You can't steal from the dungeon master!\n"); |
128 | new_draw_info (NDI_UNIQUE, 0, who, "You can't steal from the dungeon master!\n"); |
129 | return 0; |
129 | return 0; |
130 | } |
130 | } |
131 | #ifdef PROHIBIT_PLAYERKILL |
131 | |
|
|
132 | // only allow stealing between hostile players (TODO: probably should change) |
132 | if (op->type == PLAYER && who->type == PLAYER && (who->contr->peaceful || op->contr->peaceful)) |
133 | if (op->type == PLAYER && who->type == PLAYER && (who->contr->peaceful || op->contr->peaceful)) |
133 | { |
134 | { |
134 | new_draw_info (NDI_UNIQUE, 0, who, "You can't steal from other players!\n"); |
135 | new_draw_info (NDI_UNIQUE, 0, who, "You can't steal from other players!\n"); |
135 | return 0; |
136 | return 0; |
136 | } |
137 | } |
137 | #else |
|
|
138 | if (op->type == PLAYER && who->type == PLAYER && settings.no_player_stealing) |
|
|
139 | { |
|
|
140 | new_draw_info (NDI_UNIQUE, 0, who, "You can't steal from other players!\n"); |
|
|
141 | return 0; |
|
|
142 | } |
|
|
143 | #endif |
|
|
144 | |
|
|
145 | |
138 | |
146 | /* Ok then, go thru their inventory, stealing */ |
139 | /* Ok then, go thru their inventory, stealing */ |
147 | for (tmp = op->inv; tmp != NULL; tmp = next) |
140 | for (tmp = op->inv; tmp; tmp = next) |
148 | { |
141 | { |
149 | next = tmp->below; |
142 | next = tmp->below; |
150 | |
143 | |
151 | /* you can't steal worn items, starting items, wiz stuff, |
144 | /* you can't steal worn items, starting items, wiz stuff, |
152 | * innate abilities, or items w/o a type. Generally |
145 | * innate abilities, or items w/o a type. Generally |
… | |
… | |
156 | * future possible problems. -b.t. |
149 | * future possible problems. -b.t. |
157 | * Flesh items generated w/ fix_flesh_item should have FLAG_NO_STEAL |
150 | * Flesh items generated w/ fix_flesh_item should have FLAG_NO_STEAL |
158 | * already -b.t. |
151 | * already -b.t. |
159 | */ |
152 | */ |
160 | |
153 | |
161 | if (QUERY_FLAG (tmp, FLAG_WAS_WIZ) || QUERY_FLAG (tmp, FLAG_APPLIED) |
154 | if (QUERY_FLAG (tmp, FLAG_APPLIED) |
162 | || !(tmp->type) |
155 | || !tmp->type |
163 | || tmp->type == SPELL |
156 | || tmp->type == SPELL |
164 | || QUERY_FLAG (tmp, FLAG_STARTEQUIP) || QUERY_FLAG (tmp, FLAG_NO_STEAL) || tmp->invisible) |
157 | || QUERY_FLAG (tmp, FLAG_STARTEQUIP) |
|
|
158 | || QUERY_FLAG (tmp, FLAG_NO_STEAL) |
|
|
159 | || tmp->invisible) |
165 | continue; |
160 | continue; |
166 | |
161 | |
167 | /* Okay, try stealing this item. Dependent on dexterity of thief, |
162 | /* Okay, try stealing this item. Dependent on dexterity of thief, |
168 | * skill level, see the adj_stealroll fctn for more detail. |
163 | * skill level, see the adj_stealroll fctn for more detail. |
169 | */ |
164 | */ |
… | |
… | |
414 | new_draw_info (NDI_UNIQUE, 0, pl, "You fail to pick the lock."); |
409 | new_draw_info (NDI_UNIQUE, 0, pl, "You fail to pick the lock."); |
415 | return 0; |
410 | return 0; |
416 | } |
411 | } |
417 | } |
412 | } |
418 | |
413 | |
419 | |
|
|
420 | /* HIDE CODE. The user becomes undetectable (not just 'invisible') for |
414 | /* HIDE CODE. The user becomes undetectable (not just 'invisible') for |
421 | * a short while (success and duration dependant on player SK_level, |
415 | * a short while (success and duration dependant on player SK_level, |
422 | * dexterity, charisma, and map difficulty). |
416 | * dexterity, charisma, and map difficulty). |
423 | * Players have a good chance of becoming 'unhidden' if they move |
417 | * Players have a good chance of becoming 'unhidden' if they move |
424 | * and like invisiblity will be come visible if they attack |
418 | * and like invisiblity will be come visible if they attack |
425 | * Implemented by b.t. (thomas@astro.psu.edu) |
419 | * Implemented by b.t. (thomas@astro.psu.edu) |
426 | * July 7, 1995 - made hiding possible for monsters. -b.t. |
420 | * July 7, 1995 - made hiding possible for monsters. -b.t. |
427 | */ |
421 | */ |
428 | |
|
|
429 | static int |
422 | static int |
430 | attempt_hide (object *op, object *skill) |
423 | attempt_hide (object *op, object *skill) |
431 | { |
424 | { |
432 | int number, difficulty = op->map->difficulty; |
425 | int number, difficulty = op->map->difficulty; |
433 | int terrain = hideability (op); |
426 | int terrain = hideability (op); |
… | |
… | |
436 | return 0; |
429 | return 0; |
437 | |
430 | |
438 | /* Hiding success and duration dependant on skill level, |
431 | /* Hiding success and duration dependant on skill level, |
439 | * op->stats.Dex, map difficulty and terrain. |
432 | * op->stats.Dex, map difficulty and terrain. |
440 | */ |
433 | */ |
441 | |
|
|
442 | number = (die_roll (2, 25, op, PREFER_LOW) - 2) / 2; |
434 | number = (die_roll (2, 25, op, PREFER_LOW) - 2) / 2; |
|
|
435 | |
443 | if (!stand_near_hostile (op) && (number < (op->stats.Dex + skill->level + terrain - difficulty))) |
436 | if (!stand_near_hostile (op) && (number < (op->stats.Dex + skill->level + terrain - difficulty))) |
444 | { |
437 | { |
445 | op->invisible += 100; /* set the level of 'hiddeness' */ |
438 | op->invisible += 100; /* set the level of 'hiddeness' */ |
|
|
439 | |
446 | if (op->type == PLAYER) |
440 | if (op->type == PLAYER) |
447 | op->contr->tmp_invis = 1; |
441 | op->contr->tmp_invis = 1; |
|
|
442 | |
448 | op->hide = 1; |
443 | op->hide = 1; |
449 | return 1; |
444 | return 1; |
450 | } |
445 | } |
|
|
446 | |
451 | return 0; |
447 | return 0; |
452 | } |
448 | } |
453 | |
449 | |
454 | /* patched this to take terrain into consideration */ |
450 | /* patched this to take terrain into consideration */ |
455 | int |
451 | int |
456 | hide (object *op, object *skill) |
452 | hide (object *op, object *skill) |
457 | { |
453 | { |
458 | |
|
|
459 | /* the preliminaries -- Can we really hide now? */ |
454 | /* the preliminaries -- Can we really hide now? */ |
460 | /* this keeps monsters from using invisibilty spells and hiding */ |
455 | /* this keeps monsters from using invisibilty spells and hiding */ |
461 | |
456 | |
462 | if (QUERY_FLAG (op, FLAG_MAKE_INVIS)) |
457 | if (QUERY_FLAG (op, FLAG_MAKE_INVIS)) |
463 | { |
458 | { |
… | |
… | |
468 | { |
463 | { |
469 | new_draw_info (NDI_UNIQUE, 0, op, "Your attempt to hide breaks the invisibility spell!"); |
464 | new_draw_info (NDI_UNIQUE, 0, op, "Your attempt to hide breaks the invisibility spell!"); |
470 | make_visible (op); |
465 | make_visible (op); |
471 | } |
466 | } |
472 | |
467 | |
473 | if (op->invisible > (50 * skill->level)) |
468 | if (op->invisible > 50 * skill->level) |
474 | { |
469 | { |
475 | new_draw_info (NDI_UNIQUE, 0, op, "You are as hidden as you can get."); |
470 | new_draw_info (NDI_UNIQUE, 0, op, "You are as hidden as you can get."); |
476 | return 0; |
471 | return 0; |
477 | } |
472 | } |
478 | |
473 | |
… | |
… | |
480 | { |
475 | { |
481 | new_draw_info (NDI_UNIQUE, 0, op, "You hide in the shadows."); |
476 | new_draw_info (NDI_UNIQUE, 0, op, "You hide in the shadows."); |
482 | update_object (op, UP_OBJ_FACE); |
477 | update_object (op, UP_OBJ_FACE); |
483 | return calc_skill_exp (op, NULL, skill); |
478 | return calc_skill_exp (op, NULL, skill); |
484 | } |
479 | } |
|
|
480 | |
485 | new_draw_info (NDI_UNIQUE, 0, op, "You fail to conceal yourself."); |
481 | new_draw_info (NDI_UNIQUE, 0, op, "You fail to conceal yourself."); |
486 | return 0; |
482 | return 0; |
487 | } |
483 | } |
488 | |
|
|
489 | |
484 | |
490 | /* stop_jump() - End of jump. Clear flags, restore the map, and |
485 | /* stop_jump() - End of jump. Clear flags, restore the map, and |
491 | * freeze the jumper a while to simulate the exhaustion |
486 | * freeze the jumper a while to simulate the exhaustion |
492 | * of jumping. |
487 | * of jumping. |
493 | */ |
488 | */ |
… | |
… | |
813 | * -b.t. (thomas@astro.psu.edu) |
808 | * -b.t. (thomas@astro.psu.edu) |
814 | */ |
809 | */ |
815 | int |
810 | int |
816 | use_oratory (object *pl, int dir, object *skill) |
811 | use_oratory (object *pl, int dir, object *skill) |
817 | { |
812 | { |
818 | sint16 x = pl->x + freearr_x[dir], y = pl->y + freearr_y[dir]; |
|
|
819 | int mflags, chance; |
|
|
820 | object *tmp; |
|
|
821 | maptile *m; |
|
|
822 | |
|
|
823 | if (pl->type != PLAYER) |
813 | if (pl->type != PLAYER) |
824 | return 0; /* only players use this skill */ |
814 | return 0; /* only players use this skill */ |
|
|
815 | |
|
|
816 | sint16 x = pl->x + freearr_x[dir], |
|
|
817 | y = pl->y + freearr_y[dir]; |
825 | m = pl->map; |
818 | maptile *m = pl->map; |
|
|
819 | |
826 | mflags = get_map_flags (m, &m, x, y, &x, &y); |
820 | int mflags = get_map_flags (m, &m, x, y, &x, &y); |
827 | if (mflags & P_OUT_OF_MAP) |
821 | if (mflags & P_OUT_OF_MAP) |
828 | return 0; |
822 | return 0; |
829 | |
823 | |
830 | /* Save some processing - we have the flag already anyways |
824 | /* Save some processing - we have the flag already anyways |
831 | */ |
825 | */ |
… | |
… | |
833 | { |
827 | { |
834 | new_draw_info (NDI_UNIQUE, 0, pl, "There is nothing to orate to."); |
828 | new_draw_info (NDI_UNIQUE, 0, pl, "There is nothing to orate to."); |
835 | return 0; |
829 | return 0; |
836 | } |
830 | } |
837 | |
831 | |
|
|
832 | object *tmp; |
838 | for (tmp = GET_MAP_OB (m, x, y); tmp; tmp = tmp->above) |
833 | for (tmp = GET_MAP_OB (m, x, y); tmp; tmp = tmp->above) |
839 | { |
834 | { |
840 | /* can't persuade players - return because there is nothing else |
835 | /* can't persuade players - return because there is nothing else |
841 | * on that space to charm. Same for multi space monsters and |
836 | * on that space to charm. Same for multi space monsters and |
842 | * special monsters - we don't allow them to be charmed, and there |
837 | * special monsters - we don't allow them to be charmed, and there |
843 | * is no reason to do further processing since they should be the |
838 | * is no reason to do further processing since they should be the |
844 | * only monster on the space. |
839 | * only monster on the space. |
845 | */ |
840 | */ |
846 | if (tmp->type == PLAYER) |
841 | if (tmp->type == PLAYER |
847 | return 0; |
842 | || tmp->more || tmp->head_ () != tmp |
848 | if (tmp->more || tmp->head) |
843 | || tmp->msg) |
849 | return 0; |
|
|
850 | if (tmp->msg) |
|
|
851 | return 0; |
844 | return 0; |
852 | |
845 | |
853 | if (QUERY_FLAG (tmp, FLAG_MONSTER)) |
846 | if (QUERY_FLAG (tmp, FLAG_MONSTER)) |
854 | break; |
847 | break; |
855 | } |
848 | } |
… | |
… | |
870 | new_draw_info_format (NDI_UNIQUE, 0, pl, "Too bad the %s isn't listening!\n", query_name (tmp)); |
863 | new_draw_info_format (NDI_UNIQUE, 0, pl, "Too bad the %s isn't listening!\n", query_name (tmp)); |
871 | return 0; |
864 | return 0; |
872 | } |
865 | } |
873 | |
866 | |
874 | /* it's already allied! */ |
867 | /* it's already allied! */ |
875 | if (QUERY_FLAG (tmp, FLAG_FRIENDLY) && (tmp->attack_movement == PETMOVE)) |
868 | if (QUERY_FLAG (tmp, FLAG_FRIENDLY) && tmp->attack_movement == PETMOVE) |
876 | { |
869 | { |
877 | if (tmp->owner == pl) |
870 | if (tmp->owner == pl) |
878 | { |
871 | { |
879 | new_draw_info (NDI_UNIQUE, 0, pl, "Your follower loves your speech.\n"); |
872 | new_draw_info (NDI_UNIQUE, 0, pl, "Your follower loves your speech.\n"); |
880 | return 0; |
873 | return 0; |
… | |
… | |
883 | { |
876 | { |
884 | /* you steal the follower. Perhaps we should really look at the |
877 | /* you steal the follower. Perhaps we should really look at the |
885 | * level of the owner above? |
878 | * level of the owner above? |
886 | */ |
879 | */ |
887 | tmp->set_owner (pl); |
880 | tmp->set_owner (pl); |
|
|
881 | tmp->skill = skill->skill; |
|
|
882 | |
888 | new_draw_info_format (NDI_UNIQUE, 0, pl, "You convince the %s to follow you instead!\n", query_name (tmp)); |
883 | new_draw_info_format (NDI_UNIQUE, 0, pl, "You convince the %s to follow you instead!\n", query_name (tmp)); |
889 | /* Abuse fix - don't give exp since this can otherwise |
884 | /* Abuse fix - don't give exp since this can otherwise |
890 | * be used by a couple players to gets lots of exp. |
885 | * be used by a couple players to gets lots of exp. |
891 | */ |
886 | */ |
892 | return 0; |
887 | return 0; |
… | |
… | |
896 | /* In this case, you can't steal it from the other player */ |
891 | /* In this case, you can't steal it from the other player */ |
897 | return 0; |
892 | return 0; |
898 | } |
893 | } |
899 | } /* Creature was already a pet of someone */ |
894 | } /* Creature was already a pet of someone */ |
900 | |
895 | |
901 | chance = skill->level * 2 + (pl->stats.Cha - 2 * tmp->stats.Int) / 2; |
896 | int level = skill->level + (pl->stats.Cha - tmp->stats.Int) / 2; |
902 | |
897 | |
903 | /* Ok, got a 'sucker' lets try to make them a follower */ |
898 | /* Ok, got a 'sucker' lets try to make them a follower */ |
904 | if (chance > 0 && tmp->level < (random_roll (0, chance - 1, pl, PREFER_HIGH) - 1)) |
899 | if (level > 0 && tmp->level < (random_roll (0, level - 1, pl, PREFER_HIGH) - 1)) |
905 | { |
900 | { |
906 | new_draw_info_format (NDI_UNIQUE, 0, pl, "You convince the %s to become your follower.\n", query_name (tmp)); |
901 | new_draw_info_format (NDI_UNIQUE, 0, pl, "You convince the %s to become your follower.\n", query_name (tmp)); |
907 | |
902 | |
908 | tmp->set_owner (pl); |
903 | tmp->set_owner (pl); |
|
|
904 | tmp->skill = skill->skill; |
909 | tmp->stats.exp = 0; |
905 | tmp->stats.exp = 0; |
910 | add_friendly_object (tmp); |
906 | add_friendly_object (tmp); |
911 | tmp->attack_movement = PETMOVE; |
907 | tmp->attack_movement = PETMOVE; |
912 | return calc_skill_exp (pl, tmp, skill); |
908 | return calc_skill_exp (pl, tmp, skill); |
913 | } |
909 | } |
914 | |
|
|
915 | /* Charm failed. Creature may be angry now */ |
910 | /* Charm failed. Creature may be angry now */ |
916 | else if ((skill->level + ((pl->stats.Cha - 10) / 2)) < random_roll (1, 2 * tmp->level, pl, PREFER_LOW)) |
911 | else if ((skill->level + ((pl->stats.Cha - 10) / 2)) < random_roll (1, 2 * tmp->level, pl, PREFER_LOW)) |
917 | { |
912 | { |
918 | new_draw_info_format (NDI_UNIQUE, 0, pl, "Your speech angers the %s!\n", query_name (tmp)); |
913 | new_draw_info_format (NDI_UNIQUE, 0, pl, "Your speech angers the %s!\n", query_name (tmp)); |
919 | if (QUERY_FLAG (tmp, FLAG_FRIENDLY)) |
914 | if (QUERY_FLAG (tmp, FLAG_FRIENDLY)) |
… | |
… | |
936 | * successfully pacified the creature gets Int=1. Thus, a player |
931 | * successfully pacified the creature gets Int=1. Thus, a player |
937 | * may only pacify a creature once. |
932 | * may only pacify a creature once. |
938 | * BTW, I appologize for the naming of the skill, I couldnt think |
933 | * BTW, I appologize for the naming of the skill, I couldnt think |
939 | * of anything better! -b.t. |
934 | * of anything better! -b.t. |
940 | */ |
935 | */ |
941 | |
|
|
942 | int |
936 | int |
943 | singing (object *pl, int dir, object *skill) |
937 | singing (object *pl, int dir, object *skill) |
944 | { |
938 | { |
945 | int i, exp = 0, chance, mflags; |
939 | int i, exp = 0; |
946 | object *tmp; |
940 | object *tmp; |
947 | maptile *m; |
941 | maptile *m; |
948 | sint16 x, y; |
942 | sint16 x, y; |
949 | |
943 | |
950 | if (pl->type != PLAYER) |
944 | if (pl->type != PLAYER) |
… | |
… | |
955 | { |
949 | { |
956 | x = pl->x + freearr_x[i]; |
950 | x = pl->x + freearr_x[i]; |
957 | y = pl->y + freearr_y[i]; |
951 | y = pl->y + freearr_y[i]; |
958 | m = pl->map; |
952 | m = pl->map; |
959 | |
953 | |
960 | mflags = get_map_flags (m, &m, x, y, &x, &y); |
954 | int mflags = get_map_flags (m, &m, x, y, &x, &y); |
961 | if (mflags & P_OUT_OF_MAP) |
955 | if (mflags & P_OUT_OF_MAP) |
962 | continue; |
956 | continue; |
963 | if (!(mflags & P_IS_ALIVE)) |
957 | if (!(mflags & P_IS_ALIVE)) |
964 | continue; |
958 | continue; |
965 | |
959 | |
… | |
… | |
984 | |
978 | |
985 | /* stealing isn't really related (although, maybe it should |
979 | /* stealing isn't really related (although, maybe it should |
986 | * be). This is mainly to prevent singing to the same monster |
980 | * be). This is mainly to prevent singing to the same monster |
987 | * over and over again and getting exp for it. |
981 | * over and over again and getting exp for it. |
988 | */ |
982 | */ |
989 | chance = skill->level * 2 + (pl->stats.Cha - 5 - tmp->stats.Int) / 2; |
983 | int level = skill->level + (pl->stats.Cha - 5 - tmp->stats.Int) / 2; |
|
|
984 | |
990 | if (chance && tmp->level * 2 < random_roll (0, chance - 1, pl, PREFER_HIGH)) |
985 | if (level && tmp->level < random_roll (0, level - 1, pl, PREFER_HIGH)) |
991 | { |
986 | { |
992 | SET_FLAG (tmp, FLAG_UNAGGRESSIVE); |
987 | SET_FLAG (tmp, FLAG_UNAGGRESSIVE); |
993 | new_draw_info_format (NDI_UNIQUE, 0, pl, "You calm down the %s\n", query_name (tmp)); |
988 | new_draw_info_format (NDI_UNIQUE, 0, pl, "You calm down the %s\n", query_name (tmp)); |
994 | /* Give exp only if they are not aware */ |
989 | /* Give exp only if they are not aware */ |
|
|
990 | |
995 | if (!QUERY_FLAG (tmp, FLAG_NO_STEAL)) |
991 | if (!QUERY_FLAG (tmp, FLAG_NO_STEAL)) |
996 | exp += calc_skill_exp (pl, tmp, skill); |
992 | exp += calc_skill_exp (pl, tmp, skill); |
|
|
993 | |
997 | SET_FLAG (tmp, FLAG_NO_STEAL); |
994 | SET_FLAG (tmp, FLAG_NO_STEAL); |
998 | } |
995 | } |
999 | else |
996 | else |
1000 | { |
997 | { |
1001 | new_draw_info_format (NDI_UNIQUE, 0, pl, "Too bad the %s isn't listening!\n", query_name (tmp)); |
998 | new_draw_info_format (NDI_UNIQUE, 0, pl, "Too bad the %s isn't listening!\n", query_name (tmp)); |
… | |
… | |
1198 | return; |
1195 | return; |
1199 | } |
1196 | } |
1200 | else |
1197 | else |
1201 | { |
1198 | { |
1202 | for (tmp = pl->inv; tmp; tmp = tmp->below) |
1199 | for (tmp = pl->inv; tmp; tmp = tmp->below) |
1203 | if (((tmp->type == ARMOUR && skill->level < 12) |
1200 | if (((tmp->type == ARMOUR && skill->level < 12) |
1204 | || (tmp->type == HELMET && skill->level < 10) |
1201 | || (tmp->type == HELMET && skill->level < 10) |
1205 | || (tmp->type == SHIELD && skill->level < 6) |
1202 | || (tmp->type == SHIELD && skill->level < 6) |
1206 | || (tmp->type == BOOTS && skill->level < 4) || (tmp->type == GLOVES && skill->level < 2)) && QUERY_FLAG (tmp, FLAG_APPLIED)) |
1203 | || (tmp->type == BOOTS && skill->level < 4) |
|
|
1204 | || (tmp->type == GLOVES && skill->level < 2)) |
|
|
1205 | && QUERY_FLAG (tmp, FLAG_APPLIED)) |
1207 | { |
1206 | { |
1208 | new_draw_info (NDI_UNIQUE, 0, pl, "You can't concentrate while wearing so much armour!\n"); |
1207 | new_draw_info (NDI_UNIQUE, 0, pl, "You can't concentrate while wearing so much armour!\n"); |
1209 | return; |
1208 | return; |
1210 | } |
1209 | } |
1211 | } |
1210 | } |
… | |
… | |
1388 | insert_ob_in_ob (tmp, newscroll); |
1387 | insert_ob_in_ob (tmp, newscroll); |
1389 | |
1388 | |
1390 | /* Same code as from treasure.c - so they can better merge. |
1389 | /* Same code as from treasure.c - so they can better merge. |
1391 | * if players want to sell them, so be it. |
1390 | * if players want to sell them, so be it. |
1392 | */ |
1391 | */ |
1393 | newscroll->value = newscroll->arch->clone.value * newscroll->inv->value * (newscroll->level + 50) / (newscroll->inv->level + 50); |
1392 | newscroll->value = newscroll->arch->value * newscroll->inv->value * (newscroll->level + 50) / (newscroll->inv->level + 50); |
1394 | newscroll->stats.exp = newscroll->value / 5; |
1393 | newscroll->stats.exp = newscroll->value / 5; |
1395 | |
1394 | |
1396 | /* wait until finished manipulating the scroll before inserting it */ |
1395 | /* wait until finished manipulating the scroll before inserting it */ |
1397 | if (newscroll == scroll) |
1396 | if (newscroll == scroll) |
1398 | { |
1397 | { |
… | |
… | |
1455 | } |
1454 | } |
1456 | |
1455 | |
1457 | skat = get_archetype_by_type_subtype (SKILL, SK_LITERACY); |
1456 | skat = get_archetype_by_type_subtype (SKILL, SK_LITERACY); |
1458 | |
1457 | |
1459 | /* Need to be able to read before we can write! */ |
1458 | /* Need to be able to read before we can write! */ |
1460 | if (!find_skill_by_name (pl, skat->clone.skill)) |
1459 | if (!find_skill_by_name (pl, skat->skill)) |
1461 | { |
1460 | { |
1462 | new_draw_info (NDI_UNIQUE, 0, pl, "You must learn to read before you can write!"); |
1461 | new_draw_info (NDI_UNIQUE, 0, pl, "You must learn to read before you can write!"); |
1463 | return 0; |
1462 | return 0; |
1464 | } |
1463 | } |
1465 | |
1464 | |
… | |
… | |
1581 | |
1580 | |
1582 | /* make_throw_ob() We construct the 'carrier' object in |
1581 | /* make_throw_ob() We construct the 'carrier' object in |
1583 | * which we will insert the object that is being thrown. |
1582 | * which we will insert the object that is being thrown. |
1584 | * This combination becomes the 'thrown object'. -b.t. |
1583 | * This combination becomes the 'thrown object'. -b.t. |
1585 | */ |
1584 | */ |
1586 | |
|
|
1587 | static object * |
1585 | static object * |
1588 | make_throw_ob (object *orig) |
1586 | make_throw_ob (object *orig) |
1589 | { |
1587 | { |
1590 | if (!orig) |
1588 | if (!orig) |
1591 | return NULL; |
1589 | return NULL; |
… | |
… | |
1604 | toss_item->stats.dam = 0; /* default damage */ |
1602 | toss_item->stats.dam = 0; /* default damage */ |
1605 | insert_ob_in_ob (orig, toss_item); |
1603 | insert_ob_in_ob (orig, toss_item); |
1606 | return toss_item; |
1604 | return toss_item; |
1607 | } |
1605 | } |
1608 | |
1606 | |
1609 | |
|
|
1610 | /* do_throw() - op throws any object toss_item. This code |
1607 | /* do_throw() - op throws any object toss_item. This code |
1611 | * was borrowed from fire_bow. |
1608 | * was borrowed from fire_bow. |
1612 | * Returns 1 if skill was successfully used, 0 if not |
1609 | * Returns 1 if skill was successfully used, 0 if not |
1613 | */ |
1610 | */ |
1614 | |
|
|
1615 | static int |
1611 | static int |
1616 | do_throw (object *op, object *part, object *toss_item, int dir, object *skill) |
1612 | do_throw (object *op, object *part, object *toss_item, int dir, object *skill) |
1617 | { |
1613 | { |
1618 | object *throw_ob = toss_item, *left = NULL; |
1614 | object *throw_ob = toss_item, *left = NULL; |
1619 | int eff_str = 0, maxc, str = op->stats.Str, dam = 0; |
1615 | int eff_str = 0, maxc, str = op->stats.Str, dam = 0; |