1 | /* |
1 | /* |
2 | * CrossFire, A Multiplayer game |
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> |
… | |
… | |
409 | 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."); |
410 | return 0; |
410 | return 0; |
411 | } |
411 | } |
412 | } |
412 | } |
413 | |
413 | |
414 | |
|
|
415 | /* HIDE CODE. The user becomes undetectable (not just 'invisible') for |
414 | /* HIDE CODE. The user becomes undetectable (not just 'invisible') for |
416 | * a short while (success and duration dependant on player SK_level, |
415 | * a short while (success and duration dependant on player SK_level, |
417 | * dexterity, charisma, and map difficulty). |
416 | * dexterity, charisma, and map difficulty). |
418 | * Players have a good chance of becoming 'unhidden' if they move |
417 | * Players have a good chance of becoming 'unhidden' if they move |
419 | * and like invisiblity will be come visible if they attack |
418 | * and like invisiblity will be come visible if they attack |
420 | * Implemented by b.t. (thomas@astro.psu.edu) |
419 | * Implemented by b.t. (thomas@astro.psu.edu) |
421 | * July 7, 1995 - made hiding possible for monsters. -b.t. |
420 | * July 7, 1995 - made hiding possible for monsters. -b.t. |
422 | */ |
421 | */ |
423 | |
|
|
424 | static int |
422 | static int |
425 | attempt_hide (object *op, object *skill) |
423 | attempt_hide (object *op, object *skill) |
426 | { |
424 | { |
427 | int number, difficulty = op->map->difficulty; |
425 | int number, difficulty = op->map->difficulty; |
428 | int terrain = hideability (op); |
426 | int terrain = hideability (op); |
… | |
… | |
431 | return 0; |
429 | return 0; |
432 | |
430 | |
433 | /* Hiding success and duration dependant on skill level, |
431 | /* Hiding success and duration dependant on skill level, |
434 | * op->stats.Dex, map difficulty and terrain. |
432 | * op->stats.Dex, map difficulty and terrain. |
435 | */ |
433 | */ |
436 | |
|
|
437 | number = (die_roll (2, 25, op, PREFER_LOW) - 2) / 2; |
434 | number = (die_roll (2, 25, op, PREFER_LOW) - 2) / 2; |
|
|
435 | |
438 | 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))) |
439 | { |
437 | { |
440 | op->invisible += 100; /* set the level of 'hiddeness' */ |
438 | op->invisible += 100; /* set the level of 'hiddeness' */ |
|
|
439 | |
441 | if (op->type == PLAYER) |
440 | if (op->type == PLAYER) |
442 | op->contr->tmp_invis = 1; |
441 | op->contr->tmp_invis = 1; |
|
|
442 | |
443 | op->hide = 1; |
443 | op->hide = 1; |
444 | return 1; |
444 | return 1; |
445 | } |
445 | } |
|
|
446 | |
446 | return 0; |
447 | return 0; |
447 | } |
448 | } |
448 | |
449 | |
449 | /* patched this to take terrain into consideration */ |
450 | /* patched this to take terrain into consideration */ |
450 | int |
451 | int |
451 | hide (object *op, object *skill) |
452 | hide (object *op, object *skill) |
452 | { |
453 | { |
453 | |
|
|
454 | /* the preliminaries -- Can we really hide now? */ |
454 | /* the preliminaries -- Can we really hide now? */ |
455 | /* this keeps monsters from using invisibilty spells and hiding */ |
455 | /* this keeps monsters from using invisibilty spells and hiding */ |
456 | |
456 | |
457 | if (QUERY_FLAG (op, FLAG_MAKE_INVIS)) |
457 | if (QUERY_FLAG (op, FLAG_MAKE_INVIS)) |
458 | { |
458 | { |
… | |
… | |
463 | { |
463 | { |
464 | 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!"); |
465 | make_visible (op); |
465 | make_visible (op); |
466 | } |
466 | } |
467 | |
467 | |
468 | if (op->invisible > (50 * skill->level)) |
468 | if (op->invisible > 50 * skill->level) |
469 | { |
469 | { |
470 | 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."); |
471 | return 0; |
471 | return 0; |
472 | } |
472 | } |
473 | |
473 | |
… | |
… | |
475 | { |
475 | { |
476 | 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."); |
477 | update_object (op, UP_OBJ_FACE); |
477 | update_object (op, UP_OBJ_FACE); |
478 | return calc_skill_exp (op, NULL, skill); |
478 | return calc_skill_exp (op, NULL, skill); |
479 | } |
479 | } |
|
|
480 | |
480 | 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."); |
481 | return 0; |
482 | return 0; |
482 | } |
483 | } |
483 | |
|
|
484 | |
484 | |
485 | /* stop_jump() - End of jump. Clear flags, restore the map, and |
485 | /* stop_jump() - End of jump. Clear flags, restore the map, and |
486 | * freeze the jumper a while to simulate the exhaustion |
486 | * freeze the jumper a while to simulate the exhaustion |
487 | * of jumping. |
487 | * of jumping. |
488 | */ |
488 | */ |
… | |
… | |
808 | * -b.t. (thomas@astro.psu.edu) |
808 | * -b.t. (thomas@astro.psu.edu) |
809 | */ |
809 | */ |
810 | int |
810 | int |
811 | use_oratory (object *pl, int dir, object *skill) |
811 | use_oratory (object *pl, int dir, object *skill) |
812 | { |
812 | { |
813 | sint16 x = pl->x + freearr_x[dir], y = pl->y + freearr_y[dir]; |
|
|
814 | int mflags, chance; |
|
|
815 | object *tmp; |
|
|
816 | maptile *m; |
|
|
817 | |
|
|
818 | if (pl->type != PLAYER) |
813 | if (pl->type != PLAYER) |
819 | return 0; /* only players use this skill */ |
814 | return 0; /* only players use this skill */ |
820 | |
815 | |
|
|
816 | sint16 x = pl->x + freearr_x[dir], |
|
|
817 | y = pl->y + freearr_y[dir]; |
821 | m = pl->map; |
818 | maptile *m = pl->map; |
|
|
819 | |
822 | mflags = get_map_flags (m, &m, x, y, &x, &y); |
820 | int mflags = get_map_flags (m, &m, x, y, &x, &y); |
823 | if (mflags & P_OUT_OF_MAP) |
821 | if (mflags & P_OUT_OF_MAP) |
824 | return 0; |
822 | return 0; |
825 | |
823 | |
826 | /* Save some processing - we have the flag already anyways |
824 | /* Save some processing - we have the flag already anyways |
827 | */ |
825 | */ |
… | |
… | |
829 | { |
827 | { |
830 | 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."); |
831 | return 0; |
829 | return 0; |
832 | } |
830 | } |
833 | |
831 | |
|
|
832 | object *tmp; |
834 | 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) |
835 | { |
834 | { |
836 | /* can't persuade players - return because there is nothing else |
835 | /* can't persuade players - return because there is nothing else |
837 | * on that space to charm. Same for multi space monsters and |
836 | * on that space to charm. Same for multi space monsters and |
838 | * 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 |
… | |
… | |
864 | 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)); |
865 | return 0; |
864 | return 0; |
866 | } |
865 | } |
867 | |
866 | |
868 | /* it's already allied! */ |
867 | /* it's already allied! */ |
869 | if (QUERY_FLAG (tmp, FLAG_FRIENDLY) && (tmp->attack_movement == PETMOVE)) |
868 | if (QUERY_FLAG (tmp, FLAG_FRIENDLY) && tmp->attack_movement == PETMOVE) |
870 | { |
869 | { |
871 | if (tmp->owner == pl) |
870 | if (tmp->owner == pl) |
872 | { |
871 | { |
873 | 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"); |
874 | return 0; |
873 | return 0; |
… | |
… | |
892 | /* 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 */ |
893 | return 0; |
892 | return 0; |
894 | } |
893 | } |
895 | } /* Creature was already a pet of someone */ |
894 | } /* Creature was already a pet of someone */ |
896 | |
895 | |
897 | chance = skill->level * 2 + (pl->stats.Cha - 2 * tmp->stats.Int) / 2; |
896 | int level = skill->level + (pl->stats.Cha - tmp->stats.Int) / 2; |
898 | |
897 | |
899 | /* Ok, got a 'sucker' lets try to make them a follower */ |
898 | /* Ok, got a 'sucker' lets try to make them a follower */ |
900 | 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)) |
901 | { |
900 | { |
902 | 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)); |
903 | |
902 | |
904 | tmp->set_owner (pl); |
903 | tmp->set_owner (pl); |
905 | tmp->skill = skill->skill; |
904 | tmp->skill = skill->skill; |
… | |
… | |
932 | * successfully pacified the creature gets Int=1. Thus, a player |
931 | * successfully pacified the creature gets Int=1. Thus, a player |
933 | * may only pacify a creature once. |
932 | * may only pacify a creature once. |
934 | * 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 |
935 | * of anything better! -b.t. |
934 | * of anything better! -b.t. |
936 | */ |
935 | */ |
937 | |
|
|
938 | int |
936 | int |
939 | singing (object *pl, int dir, object *skill) |
937 | singing (object *pl, int dir, object *skill) |
940 | { |
938 | { |
941 | int i, exp = 0, chance, mflags; |
939 | int i, exp = 0; |
942 | object *tmp; |
940 | object *tmp; |
943 | maptile *m; |
941 | maptile *m; |
944 | sint16 x, y; |
942 | sint16 x, y; |
945 | |
943 | |
946 | if (pl->type != PLAYER) |
944 | if (pl->type != PLAYER) |
… | |
… | |
951 | { |
949 | { |
952 | x = pl->x + freearr_x[i]; |
950 | x = pl->x + freearr_x[i]; |
953 | y = pl->y + freearr_y[i]; |
951 | y = pl->y + freearr_y[i]; |
954 | m = pl->map; |
952 | m = pl->map; |
955 | |
953 | |
956 | mflags = get_map_flags (m, &m, x, y, &x, &y); |
954 | int mflags = get_map_flags (m, &m, x, y, &x, &y); |
957 | if (mflags & P_OUT_OF_MAP) |
955 | if (mflags & P_OUT_OF_MAP) |
958 | continue; |
956 | continue; |
959 | if (!(mflags & P_IS_ALIVE)) |
957 | if (!(mflags & P_IS_ALIVE)) |
960 | continue; |
958 | continue; |
961 | |
959 | |
… | |
… | |
980 | |
978 | |
981 | /* stealing isn't really related (although, maybe it should |
979 | /* stealing isn't really related (although, maybe it should |
982 | * be). This is mainly to prevent singing to the same monster |
980 | * be). This is mainly to prevent singing to the same monster |
983 | * over and over again and getting exp for it. |
981 | * over and over again and getting exp for it. |
984 | */ |
982 | */ |
985 | 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 | |
986 | 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)) |
987 | { |
986 | { |
988 | SET_FLAG (tmp, FLAG_UNAGGRESSIVE); |
987 | SET_FLAG (tmp, FLAG_UNAGGRESSIVE); |
989 | 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)); |
990 | /* Give exp only if they are not aware */ |
989 | /* Give exp only if they are not aware */ |
|
|
990 | |
991 | if (!QUERY_FLAG (tmp, FLAG_NO_STEAL)) |
991 | if (!QUERY_FLAG (tmp, FLAG_NO_STEAL)) |
992 | exp += calc_skill_exp (pl, tmp, skill); |
992 | exp += calc_skill_exp (pl, tmp, skill); |
|
|
993 | |
993 | SET_FLAG (tmp, FLAG_NO_STEAL); |
994 | SET_FLAG (tmp, FLAG_NO_STEAL); |
994 | } |
995 | } |
995 | else |
996 | else |
996 | { |
997 | { |
997 | 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)); |
… | |
… | |
1194 | return; |
1195 | return; |
1195 | } |
1196 | } |
1196 | else |
1197 | else |
1197 | { |
1198 | { |
1198 | for (tmp = pl->inv; tmp; tmp = tmp->below) |
1199 | for (tmp = pl->inv; tmp; tmp = tmp->below) |
1199 | if (((tmp->type == ARMOUR && skill->level < 12) |
1200 | if (((tmp->type == ARMOUR && skill->level < 12) |
1200 | || (tmp->type == HELMET && skill->level < 10) |
1201 | || (tmp->type == HELMET && skill->level < 10) |
1201 | || (tmp->type == SHIELD && skill->level < 6) |
1202 | || (tmp->type == SHIELD && skill->level < 6) |
1202 | || (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)) |
1203 | { |
1206 | { |
1204 | 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"); |
1205 | return; |
1208 | return; |
1206 | } |
1209 | } |
1207 | } |
1210 | } |
… | |
… | |
1384 | insert_ob_in_ob (tmp, newscroll); |
1387 | insert_ob_in_ob (tmp, newscroll); |
1385 | |
1388 | |
1386 | /* Same code as from treasure.c - so they can better merge. |
1389 | /* Same code as from treasure.c - so they can better merge. |
1387 | * if players want to sell them, so be it. |
1390 | * if players want to sell them, so be it. |
1388 | */ |
1391 | */ |
1389 | 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); |
1390 | newscroll->stats.exp = newscroll->value / 5; |
1393 | newscroll->stats.exp = newscroll->value / 5; |
1391 | |
1394 | |
1392 | /* wait until finished manipulating the scroll before inserting it */ |
1395 | /* wait until finished manipulating the scroll before inserting it */ |
1393 | if (newscroll == scroll) |
1396 | if (newscroll == scroll) |
1394 | { |
1397 | { |
… | |
… | |
1451 | } |
1454 | } |
1452 | |
1455 | |
1453 | skat = get_archetype_by_type_subtype (SKILL, SK_LITERACY); |
1456 | skat = get_archetype_by_type_subtype (SKILL, SK_LITERACY); |
1454 | |
1457 | |
1455 | /* Need to be able to read before we can write! */ |
1458 | /* Need to be able to read before we can write! */ |
1456 | if (!find_skill_by_name (pl, skat->clone.skill)) |
1459 | if (!find_skill_by_name (pl, skat->skill)) |
1457 | { |
1460 | { |
1458 | 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!"); |
1459 | return 0; |
1462 | return 0; |
1460 | } |
1463 | } |
1461 | |
1464 | |