1 | /* |
1 | /* |
2 | * static char *rcsid_skill_util_c = |
2 | * static char *rcsid_skill_util_c = |
3 | * "$Id: skill_util.C,v 1.6 2006/08/30 06:06:27 root Exp $"; |
3 | * "$Id: skill_util.C,v 1.7 2006/09/03 00:18:42 root Exp $"; |
4 | */ |
4 | */ |
5 | /* |
5 | /* |
6 | CrossFire, A Multiplayer game for X-windows |
6 | CrossFire, A Multiplayer game for X-windows |
7 | |
7 | |
8 | Copryight (C) 2002 Mark Wedel & Crossfire Development Team |
8 | Copryight (C) 2002 Mark Wedel & Crossfire Development Team |
… | |
… | |
53 | #include <spells.h> |
53 | #include <spells.h> |
54 | |
54 | |
55 | static int attack_hth(object *pl, int dir, const char *string, object *skill); |
55 | static int attack_hth(object *pl, int dir, const char *string, object *skill); |
56 | static int attack_melee_weapon(object *op, int dir, const char *string, object *skill); |
56 | static int attack_melee_weapon(object *op, int dir, const char *string, object *skill); |
57 | |
57 | |
58 | const char *skill_names[NUM_SKILLS]; |
58 | shstr skill_names[NUM_SKILLS]; |
59 | |
59 | |
60 | /* init_skills basically just sets up the skill_names table |
60 | /* init_skills basically just sets up the skill_names table |
61 | * above. The index into the array is set up by the |
61 | * above. The index into the array is set up by the |
62 | * subtypes. |
62 | * subtypes. |
63 | */ |
63 | */ |
64 | void init_skills(void) { |
64 | void init_skills(void) { |
65 | int i; |
65 | int i; |
66 | archetype *at; |
66 | archetype *at; |
67 | |
|
|
68 | for (i=0; i<NUM_SKILLS; i++) |
|
|
69 | skill_names[i] = NULL; |
|
|
70 | |
67 | |
71 | for(at = first_archetype;at!=NULL;at=at->next) { |
68 | for(at = first_archetype;at!=NULL;at=at->next) { |
72 | if (at->clone.type == SKILL) { |
69 | if (at->clone.type == SKILL) { |
73 | if (skill_names[at->clone.subtype] != NULL) { |
70 | if (skill_names[at->clone.subtype] != NULL) { |
74 | LOG(llevError, "init_skills: multiple skill using same subtype %d, %s, %s\n", |
71 | LOG(llevError, "init_skills: multiple skill using same subtype %d, %s, %s\n", |
75 | at->clone.subtype, skill_names[at->clone.subtype], at->clone.skill); |
72 | at->clone.subtype, &skill_names[at->clone.subtype], &at->clone.skill); |
76 | } else { |
73 | } else { |
77 | skill_names[at->clone.subtype] = add_refcount(at->clone.skill); |
74 | skill_names[at->clone.subtype] = at->clone.skill; |
78 | } |
75 | } |
79 | } |
76 | } |
80 | } |
77 | } |
81 | |
78 | |
82 | /* This isn't really an error if there is no skill subtype set, but |
79 | /* This isn't really an error if there is no skill subtype set, but |
… | |
… | |
102 | for (tmp=op->inv; tmp; tmp=tmp->below) { |
99 | for (tmp=op->inv; tmp; tmp=tmp->below) { |
103 | if (tmp->type == SKILL) { |
100 | if (tmp->type == SKILL) { |
104 | /* This is really a warning, hence no else below */ |
101 | /* This is really a warning, hence no else below */ |
105 | if (op->contr->last_skill_ob[tmp->subtype] && op->contr->last_skill_ob[tmp->subtype] != tmp) { |
102 | if (op->contr->last_skill_ob[tmp->subtype] && op->contr->last_skill_ob[tmp->subtype] != tmp) { |
106 | LOG(llevError,"Multiple skills with the same subtype? %s, %s\n", |
103 | LOG(llevError,"Multiple skills with the same subtype? %s, %s\n", |
107 | op->contr->last_skill_ob[tmp->subtype]->skill, tmp->skill); |
104 | &op->contr->last_skill_ob[tmp->subtype]->skill, &tmp->skill); |
108 | } |
105 | } |
109 | if (tmp->subtype >= NUM_SKILLS) { |
106 | if (tmp->subtype >= NUM_SKILLS) { |
110 | LOG(llevError,"Invalid subtype number %d (range 0-%d)\n", |
107 | LOG(llevError,"Invalid subtype number %d (range 0-%d)\n", |
111 | tmp->subtype, NUM_SKILLS); |
108 | tmp->subtype, NUM_SKILLS); |
112 | } else { |
109 | } else { |
… | |
… | |
601 | int |
598 | int |
602 | learn_skill (object *pl, object *scroll) { |
599 | learn_skill (object *pl, object *scroll) { |
603 | object *tmp; |
600 | object *tmp; |
604 | |
601 | |
605 | if (!scroll->skill) { |
602 | if (!scroll->skill) { |
606 | LOG(llevError,"skill scroll %s does not have skill pointer set.\n", scroll->name); |
603 | LOG(llevError,"skill scroll %s does not have skill pointer set.\n", &scroll->name); |
607 | return 2; |
604 | return 2; |
608 | } |
605 | } |
609 | |
606 | |
610 | /* can't use find_skill_by_name because we want skills the player knows |
607 | /* can't use find_skill_by_name because we want skills the player knows |
611 | * but can't use natively. |
608 | * but can't use natively. |
… | |
… | |
628 | |
625 | |
629 | if (!tmp) |
626 | if (!tmp) |
630 | tmp = give_skill_by_name(pl, scroll->skill); |
627 | tmp = give_skill_by_name(pl, scroll->skill); |
631 | |
628 | |
632 | if (!tmp) { |
629 | if (!tmp) { |
633 | LOG(llevError,"skill scroll %s does not have valid skill name (%s).\n", scroll->name, scroll->skill); |
630 | LOG(llevError,"skill scroll %s does not have valid skill name (%s).\n", &scroll->name, &scroll->skill); |
634 | return 2; |
631 | return 2; |
635 | } |
632 | } |
636 | |
633 | |
637 | SET_FLAG(tmp, FLAG_CAN_USE_SKILL); |
634 | SET_FLAG(tmp, FLAG_CAN_USE_SKILL); |
638 | link_player_skills(pl); |
635 | link_player_skills(pl); |
… | |
… | |
681 | |
678 | |
682 | for (tmp=op->inv; tmp!=NULL; tmp=tmp->below) { |
679 | for (tmp=op->inv; tmp!=NULL; tmp=tmp->below) { |
683 | if (tmp->type == SKILL) { |
680 | if (tmp->type == SKILL) { |
684 | if ( search && strstr(tmp->name,search)==NULL ) continue; |
681 | if ( search && strstr(tmp->name,search)==NULL ) continue; |
685 | /* Basically want to fill this out to 40 spaces with periods */ |
682 | /* Basically want to fill this out to 40 spaces with periods */ |
686 | sprintf(buf,"%s%s", tmp->name, periods); |
683 | sprintf(buf,"%s%s", &tmp->name, periods); |
687 | buf[40] = 0; |
684 | buf[40] = 0; |
688 | |
685 | |
689 | if (settings.permanent_exp_ratio) { |
686 | if (settings.permanent_exp_ratio) { |
690 | #ifdef WIN32 |
|
|
691 | sprintf(skills[num_skills_found++],"%slvl:%3d (xp:%I64d/%I64d/%d%%)", |
|
|
692 | buf,tmp->level, |
|
|
693 | tmp->stats.exp, |
|
|
694 | level_exp(tmp->level+1, op->expmul), |
|
|
695 | clipped_percent(tmp->perm_exp,tmp->stats.exp)); |
|
|
696 | #else |
|
|
697 | sprintf(skills[num_skills_found++],"%slvl:%3d (xp:%lld/%lld/%d%%)", |
687 | sprintf(skills[num_skills_found++],"%slvl:%3d (xp:%lld/%lld/%d%%)", |
698 | buf,tmp->level, |
688 | buf,tmp->level, |
699 | tmp->stats.exp, |
689 | (long long)tmp->stats.exp, |
700 | level_exp(tmp->level+1, op->expmul), |
690 | (long long)level_exp(tmp->level+1, op->expmul), |
701 | clipped_percent(tmp->perm_exp,tmp->stats.exp)); |
691 | clipped_percent(tmp->perm_exp,tmp->stats.exp)); |
702 | #endif |
|
|
703 | } else { |
692 | } else { |
704 | #ifdef WIN32 |
|
|
705 | sprintf(skills[num_skills_found++], "%slvl:%3d (xp:%I64d/%I64d)", |
|
|
706 | buf,tmp->level, |
|
|
707 | tmp->stats.exp, |
|
|
708 | level_exp(tmp->level+1, op->expmul)); |
|
|
709 | #else |
|
|
710 | sprintf(skills[num_skills_found++], "%slvl:%3d (xp:%lld/%lld)", |
693 | sprintf(skills[num_skills_found++], "%slvl:%3d (xp:%lld/%lld)", |
711 | buf,tmp->level, |
694 | buf,tmp->level, |
712 | tmp->stats.exp, |
695 | (long long)tmp->stats.exp, |
713 | level_exp(tmp->level+1, op->expmul)); |
696 | (long long)level_exp(tmp->level+1, op->expmul)); |
714 | #endif |
|
|
715 | } |
697 | } |
716 | /* I don't know why some characters get a bunch of skills, but |
698 | /* I don't know why some characters get a bunch of skills, but |
717 | * it sometimes happens (maybe a leftover from bugier earlier code |
699 | * it sometimes happens (maybe a leftover from bugier earlier code |
718 | * and those character are still about). In any case, lets handle |
700 | * and those character are still about). In any case, lets handle |
719 | * it so it doesn't crash the server - otherwise, one character may |
701 | * it so it doesn't crash the server - otherwise, one character may |
… | |
… | |
891 | } |
873 | } |
892 | } |
874 | } |
893 | if (skill != op->chosen_skill) { |
875 | if (skill != op->chosen_skill) { |
894 | /* now try to ready the new skill */ |
876 | /* now try to ready the new skill */ |
895 | if(!change_skill(op,skill,0)) { /* oh oh, trouble! */ |
877 | if(!change_skill(op,skill,0)) { /* oh oh, trouble! */ |
896 | new_draw_info_format(NDI_UNIQUE, 0, tmp, "Couldn't change to skill %s", skill->name); |
878 | new_draw_info_format(NDI_UNIQUE, 0, tmp, "Couldn't change to skill %s", &skill->name); |
897 | return 0; |
879 | return 0; |
898 | } |
880 | } |
899 | } |
881 | } |
900 | } else { |
882 | } else { |
901 | /* Seen some crashes below where current_weapon is not set, |
883 | /* Seen some crashes below where current_weapon is not set, |
… | |
… | |
904 | */ |
886 | */ |
905 | if (!op->current_weapon) { |
887 | if (!op->current_weapon) { |
906 | object *tmp; |
888 | object *tmp; |
907 | |
889 | |
908 | LOG(llevError,"Player %s does not have current weapon set but flag_ready_weapon is set\n", |
890 | LOG(llevError,"Player %s does not have current weapon set but flag_ready_weapon is set\n", |
909 | op->name); |
891 | &op->name); |
910 | for (tmp=op->inv; tmp; tmp=tmp->below) |
892 | for (tmp=op->inv; tmp; tmp=tmp->below) |
911 | if (tmp->type == WEAPON && QUERY_FLAG(tmp, FLAG_APPLIED)) break; |
893 | if (tmp->type == WEAPON && QUERY_FLAG(tmp, FLAG_APPLIED)) break; |
912 | |
894 | |
913 | if (!tmp) { |
895 | if (!tmp) { |
914 | LOG(llevError,"Could not find applied weapon on %s\n", |
896 | LOG(llevError,"Could not find applied weapon on %s\n", |
915 | op->name); |
897 | &op->name); |
916 | op->current_weapon=NULL; |
898 | op->current_weapon=NULL; |
917 | return 0; |
899 | return 0; |
918 | } else { |
900 | } else { |
919 | op->current_weapon = tmp; |
901 | op->current_weapon = tmp; |
920 | } |
902 | } |