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 Marc Alexander Lehmann / Robin Redeker / the Deliantra team |
4 | * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team |
5 | * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team |
5 | * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team |
6 | * Copyright (©) 1992,2007 Frank Tore Johansen |
6 | * Copyright (©) 1992,2007 Frank Tore Johansen |
7 | * |
7 | * |
8 | * Deliantra is free software: you can redistribute it and/or modify |
8 | * Deliantra is free software: you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by |
9 | * it under the terms of the GNU General Public License as published by |
… | |
… | |
291 | new_draw_info (NDI_UNIQUE, 0, op, "You come to earth."); |
291 | new_draw_info (NDI_UNIQUE, 0, op, "You come to earth."); |
292 | } |
292 | } |
293 | else |
293 | else |
294 | { |
294 | { |
295 | SET_FLAG (skill, FLAG_APPLIED); |
295 | SET_FLAG (skill, FLAG_APPLIED); |
296 | new_draw_info (NDI_UNIQUE, 0, op, "You rise into the air!."); |
296 | new_draw_info (NDI_UNIQUE, 0, op, "You rise into the air!"); |
297 | } |
297 | } |
298 | |
298 | |
299 | op->update_stats (); |
299 | op->update_stats (); |
300 | success = 1; |
300 | success = 1; |
301 | break; |
301 | break; |
… | |
… | |
311 | case SK_HIDING: |
311 | case SK_HIDING: |
312 | exp = success = hide (op, skill); |
312 | exp = success = hide (op, skill); |
313 | break; |
313 | break; |
314 | |
314 | |
315 | case SK_JUMPING: |
315 | case SK_JUMPING: |
316 | success = jump (op, dir, skill); |
316 | exp = success = jump (op, dir, skill); |
317 | break; |
317 | break; |
318 | |
318 | |
319 | case SK_INSCRIPTION: |
319 | case SK_INSCRIPTION: |
320 | exp = success = write_on_item (op, string, skill); |
320 | exp = success = write_on_item (op, string, skill); |
321 | break; |
321 | break; |
… | |
… | |
452 | * Monsters have no skill use time because of the random nature in |
452 | * Monsters have no skill use time because of the random nature in |
453 | * which use_monster_skill is called already simulates this. |
453 | * which use_monster_skill is called already simulates this. |
454 | * If certain skills should take more/less time, that should be |
454 | * If certain skills should take more/less time, that should be |
455 | * in the code for the skill itself. |
455 | * in the code for the skill itself. |
456 | */ |
456 | */ |
457 | |
|
|
458 | if (op->type == PLAYER) |
457 | if (op->type == PLAYER) |
459 | op->speed_left -= 1.f; |
458 | op->speed_left -= 1.f; |
460 | |
459 | |
461 | /* this is a good place to add experience for successfull use of skills. |
460 | /* this is a good place to add experience for successfull use of skills. |
462 | * Note that add_exp() will figure out player/monster experience |
461 | * Note that add_exp() will figure out player/monster experience |
… | |
… | |
510 | * If an object is not alive and magical we set the base exp higher to |
509 | * If an object is not alive and magical we set the base exp higher to |
511 | * help out exp awards for skill_ident skills. Also, if |
510 | * help out exp awards for skill_ident skills. Also, if |
512 | * an item is type RUNE, we give out exp based on stats.Cha |
511 | * an item is type RUNE, we give out exp based on stats.Cha |
513 | * and level (this was the old system) -b.t. |
512 | * and level (this was the old system) -b.t. |
514 | */ |
513 | */ |
515 | |
|
|
516 | if (!op) |
514 | if (!op) |
517 | { /* no item/creature */ |
515 | { /* no item/creature */ |
518 | op_lvl = who->map->difficulty < 1 ? 1 : who->map->difficulty; |
516 | op_lvl = max (1, who->map->difficulty); |
519 | op_exp = 0; |
517 | op_exp = 0; |
520 | } |
518 | } |
521 | else if (op->type == RUNE || op->type == TRAP) |
519 | else if (op->type == RUNE || op->type == TRAP) |
522 | { /* all traps. If stats.Cha > 1 we use that |
520 | { /* all traps. If stats.Cha > 1 we use that |
523 | * for the amount of experience */ |
521 | * for the amount of experience */ |
… | |
… | |
527 | else |
525 | else |
528 | { /* all other items/living creatures */ |
526 | { /* all other items/living creatures */ |
529 | op_exp = op->stats.exp; |
527 | op_exp = op->stats.exp; |
530 | op_lvl = op->level; |
528 | op_lvl = op->level; |
531 | if (!QUERY_FLAG (op, FLAG_ALIVE)) |
529 | if (!QUERY_FLAG (op, FLAG_ALIVE)) |
532 | { /* for ident/make items */ |
530 | op_lvl += 5 * abs (op->magic); /* for ident/make items */ |
533 | op_lvl += 5 * abs (op->magic); |
|
|
534 | } |
|
|
535 | } |
531 | } |
536 | |
532 | |
537 | if (op_lvl < 1) |
533 | if (op_lvl < 1) |
538 | op_lvl = 1; |
534 | op_lvl = 1; |
539 | |
535 | |
… | |
… | |
566 | } |
562 | } |
567 | } |
563 | } |
568 | else |
564 | else |
569 | { |
565 | { |
570 | /* Don't divide by zero here! */ |
566 | /* Don't divide by zero here! */ |
571 | lvl_mult = (float) op_lvl / (float) (skill->level ? skill->level : 1); |
567 | lvl_mult = (float) op_lvl / (float) max (1, skill->level); |
572 | } |
568 | } |
573 | } |
569 | } |
574 | |
570 | |
575 | /* assemble the exp total, and return value */ |
571 | /* assemble the exp total, and return value */ |
576 | |
572 | |
… | |
… | |
820 | * the caller should have set it appropriately). We still want to pass |
816 | * the caller should have set it appropriately). We still want to pass |
821 | * through that code if skill is set to change to the skill. |
817 | * through that code if skill is set to change to the skill. |
822 | */ |
818 | */ |
823 | if (player *pl = op->contr) |
819 | if (player *pl = op->contr) |
824 | { |
820 | { |
825 | if (!pl->combat_ob) |
821 | if (skill) |
|
|
822 | op->change_skill (skill); |
|
|
823 | else |
826 | { |
824 | { |
827 | if (QUERY_FLAG (op, FLAG_READY_WEAPON)) |
|
|
828 | { |
|
|
829 | for (tmp = op->inv; tmp; tmp = tmp->below) |
|
|
830 | if (tmp->type == WEAPON && QUERY_FLAG (tmp, FLAG_APPLIED)) |
|
|
831 | break; |
|
|
832 | |
|
|
833 | if (!tmp) |
|
|
834 | LOG (llevError, "Could not find applied weapon on %s\n", &op->name); |
|
|
835 | |
|
|
836 | pl->combat_ob = tmp; |
|
|
837 | } |
|
|
838 | |
|
|
839 | if (!pl->combat_ob) |
825 | if (!pl->combat_ob) |
840 | { |
826 | { |
|
|
827 | if (QUERY_FLAG (op, FLAG_READY_WEAPON)) |
|
|
828 | { |
|
|
829 | for (tmp = op->inv; tmp; tmp = tmp->below) |
|
|
830 | if (tmp->type == WEAPON && QUERY_FLAG (tmp, FLAG_APPLIED)) |
|
|
831 | break; |
|
|
832 | |
841 | if (!skill) |
833 | if (!tmp) |
|
|
834 | LOG (llevError, "Could not find applied weapon on %s\n", &op->name); |
|
|
835 | |
|
|
836 | pl->combat_ob = tmp; |
|
|
837 | } |
|
|
838 | |
|
|
839 | if (!pl->combat_ob) |
842 | { |
840 | { |
843 | /* See if the players chosen skill is a combat skill, and use |
841 | /* See if the players chosen skill is a combat skill, and use |
844 | * it if appropriate. |
842 | * it if appropriate. |
845 | */ |
843 | */ |
846 | if (op->chosen_skill && hth_skill_p (op->chosen_skill)) |
844 | if (op->chosen_skill && hth_skill_p (op->chosen_skill)) |
… | |
… | |
850 | skill = find_player_hth_skill (op); |
848 | skill = find_player_hth_skill (op); |
851 | |
849 | |
852 | if (!skill) |
850 | if (!skill) |
853 | new_draw_info (NDI_BLACK, 0, op, "You have no unarmed combat skills!"); |
851 | new_draw_info (NDI_BLACK, 0, op, "You have no unarmed combat skills!"); |
854 | } |
852 | } |
|
|
853 | |
|
|
854 | if (skill) |
|
|
855 | { |
|
|
856 | op->change_skill (0); |
|
|
857 | apply_special (op, skill, AP_APPLY); |
|
|
858 | } |
855 | } |
859 | } |
856 | |
860 | |
857 | if (skill) |
861 | if (!pl->combat_ob) |
858 | { |
862 | { |
859 | op->change_skill (0); |
863 | LOG (llevError, "Could not find anything to attack on %s\n", &op->name); |
860 | apply_special (op, skill, AP_APPLY); |
864 | return 0; |
861 | } |
865 | } |
862 | } |
866 | } |
863 | |
867 | |
864 | if (!pl->combat_ob) |
868 | if (!op->change_weapon (pl->combat_ob)) |
865 | { |
|
|
866 | LOG (llevError, "Could not find anything to attack on %s\n", &op->name); |
|
|
867 | return 0; |
869 | return 0; |
868 | } |
|
|
869 | } |
870 | } |
870 | |
|
|
871 | if (!op->change_weapon (pl->combat_ob)) |
|
|
872 | return 0; |
|
|
873 | |
871 | |
874 | /* lose invisiblity/hiding status for running attacks */ |
872 | /* lose invisiblity/hiding status for running attacks */ |
875 | if (pl->tmp_invis) |
873 | if (pl->tmp_invis) |
876 | { |
874 | { |
877 | pl->tmp_invis = 0; |
875 | pl->tmp_invis = 0; |
… | |
… | |
896 | return success; |
894 | return success; |
897 | } |
895 | } |
898 | |
896 | |
899 | /* skill_attack() - Core routine for use when we attack using a skills |
897 | /* skill_attack() - Core routine for use when we attack using a skills |
900 | * system. In essence, this code handles |
898 | * system. In essence, this code handles |
901 | * all skill-based attacks, ie hth, missile and melee weapons should be |
899 | * all skill-based attacks, i.e. hth, missile and melee weapons should be |
902 | * treated here. If an opponent is already supplied by move_player(), |
900 | * treated here. If an opponent is already supplied by move_player(), |
903 | * we move right onto do_skill_attack(), otherwise we find if an |
901 | * we move right onto do_skill_attack(), otherwise we find if an |
904 | * appropriate opponent exists. |
902 | * appropriate opponent exists. |
905 | * |
903 | * |
906 | * This is called by move_player() and attack_hth() |
904 | * This is called by move_player() and attack_hth() |