summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog.txt1
-rw-r--r--conf-tmpl/atcommand_athena.conf3
-rw-r--r--src/map/atcommand.c86
-rw-r--r--src/map/atcommand.h1
-rw-r--r--src/map/pc.c97
-rw-r--r--src/map/pc.h4
-rw-r--r--src/map/skill.c2
-rw-r--r--src/map/skill.h2
8 files changed, 147 insertions, 49 deletions
diff --git a/Changelog.txt b/Changelog.txt
index e930d9f2a..b89769f76 100644
--- a/Changelog.txt
+++ b/Changelog.txt
@@ -1,5 +1,6 @@
Date Added
11/25
+ * Added @skilltree to help GM's answer skill tree questions [MouseJstr]
* Update Spider Web; I believe you cannot use it on yourself now. [Codemaster]
* Added Ore Discovery, and base code for Slim Pitcher and Preservation [celest]
diff --git a/conf-tmpl/atcommand_athena.conf b/conf-tmpl/atcommand_athena.conf
index ae6f0204b..f215d2db2 100644
--- a/conf-tmpl/atcommand_athena.conf
+++ b/conf-tmpl/atcommand_athena.conf
@@ -284,6 +284,9 @@ skillid: 40
// use a skill by id
useskill: 40
+// What skills are required to get this skill
+skilltree: 40
+
// make another player killable
charkillable: 40
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index b2830d41c..4020b82e3 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -230,6 +230,8 @@ ATCOMMAND_FUNC(sound); // [Valaris]
ATCOMMAND_FUNC(refreshonline); // [Valaris]
#endif /* TXT_ONLY */
+ATCOMMAND_FUNC(skilltree); // by MouseJstr
+
/*==========================================
*AtCommandInfo atcommand_info[]構造体の定義
*------------------------------------------
@@ -480,6 +482,7 @@ static AtCommandInfo atcommand_info[] = {
{ AtCommand_RefreshOnline, "@refreshonline", 99, atcommand_refreshonline }, // [Valaris]
#endif /* TXT_ONLY */
+ { AtCommand_SkillTree, "@skilltree", 40, atcommand_skilltree }, // [MouseJstr]
// add new commands before this line
{ AtCommand_Unknown, NULL, 1, NULL }
@@ -7142,6 +7145,7 @@ atcommand_skillid(const int fd, struct map_session_data* sd,
}
return 0;
}
+
/*==========================================
* @useskill by [MouseJstr]
*
@@ -7177,6 +7181,88 @@ atcommand_useskill(const int fd, struct map_session_data* sd,
return 0;
}
+
+/*==========================================
+ * @skilltree by [MouseJstr]
+ *
+ * prints the skill tree for a player required to get to a skill
+ *------------------------------------------
+ */
+int
+atcommand_skilltree(const int fd, struct map_session_data* sd,
+ const char* command, const char* message)
+{
+ struct map_session_data *pl_sd = NULL;
+ int skillnum, skillidx = -1;
+ int meets = 1, j, c=0, s=0;
+ struct pc_base_job s_class;
+ char target[255], *tbl;
+ char output[255];
+
+ if (!message || !*message)
+ return -1;
+
+ if(sscanf(message, "%d %[^\r\n]", &skillnum, target) != 2) {
+ clif_displaymessage(fd, "Usage: @skilltree <skillnum> <target>");
+ return -1;
+ }
+ if((pl_sd=map_nick2sd(target)) == NULL)
+ return -1;
+
+ s_class = pc_calc_base_job(pl_sd->status.class);
+ c = s_class.job;
+ s = s_class.upper;
+
+ c = pc_calc_skilltree_normalize_job(c, pl_sd);
+
+ tbl = job_name(c);
+
+ sprintf(output, "Player is using %s %s skill tree (%d basic points)",
+ s_class.upper ? "upper" : "lower",
+ tbl, pc_checkskill(pl_sd, 1));
+ clif_displaymessage(fd, output);
+
+ for (j = 0; j < MAX_SKILL; j++) {
+ if (skill_tree[s][c][j].id == skillnum) {
+ skillidx = j;
+ break;
+ }
+ }
+
+ if (skillidx == -1) {
+ sprintf(output, "I do not believe the player can use that skill");
+ clif_displaymessage(fd, output);
+ return 0;
+ }
+
+ struct skill_tree_entry *ent = &skill_tree[s][c][skillidx];
+
+ for(j=0;j<5;j++)
+ if( ent->need[j].id &&
+ pc_checkskill(sd,ent->need[j].id) < ent->need[j].lv)
+ {
+ int idx = 0;
+ char *desc;
+ while (skill_names[idx].id != 0 && skill_names[idx].id != ent->need[j].id)
+ idx++;
+ if (skill_names[idx].id == 0)
+ desc = "Unknown skill";
+ else
+ desc = skill_names[idx].desc;
+ sprintf(output, "player requires level %d of skill %s",
+ ent->need[j].lv, desc);
+ clif_displaymessage(fd, output);
+ meets = 0;
+ }
+
+ if (meets == 1) {
+ sprintf(output, "I believe the player meets all the requirements for that skill");
+ clif_displaymessage(fd, output);
+ }
+
+ return 0;
+}
+
/*==========================================
* It is made to rain.
*------------------------------------------
diff --git a/src/map/atcommand.h b/src/map/atcommand.h
index ee715bc4d..caaad51cc 100644
--- a/src/map/atcommand.h
+++ b/src/map/atcommand.h
@@ -214,6 +214,7 @@ enum AtCommandType {
AtCommand_RefreshOnline, // [Valaris]
// SQL-only commands end
#endif
+ AtCommand_SkillTree, // by MouseJstr
// end
AtCommand_Unknown,
diff --git a/src/map/pc.c b/src/map/pc.c
index 2d0f14385..a4503b2c1 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -913,6 +913,56 @@ int pc_calc_skilltree(struct map_session_data *sd)
//s = (s_class.upper==1) ? 1 : 0 ; //?生以外は通常のスキル?
s = s_class.upper;
+ c = pc_calc_skilltree_normalize_job(c, sd);
+
+ for(i=0;i<MAX_SKILL;i++){
+ if (sd->status.skill[i].flag != 13) sd->status.skill[i].id=0;
+ if (sd->status.skill[i].flag && sd->status.skill[i].flag != 13){ // cardスキルなら、
+ sd->status.skill[i].lv=(sd->status.skill[i].flag==1)?0:sd->status.skill[i].flag-2; // 本?のlvに
+ sd->status.skill[i].flag=0; // flagは0にしておく
+ }
+ }
+
+ if (battle_config.gm_allskill > 0 && pc_isGM(sd) >= battle_config.gm_allskill){
+ // 全てのスキル
+ for(i=1;i<158;i++)
+ sd->status.skill[i].id=i;
+ for(i=210;i<291;i++)
+ sd->status.skill[i].id=i;
+ for(i=304;i<337;i++){
+ if(i==331) continue;
+ sd->status.skill[i].id=i;
+ }
+ if(battle_config.enable_upper_class){ //confで無?でなければ?み?む
+ for(i=355;i<MAX_SKILL;i++)
+ sd->status.skill[i].id=i;
+ }
+ }else{
+ // 通常の計算
+ do{
+ flag=0;
+ for(i=0;(id=skill_tree[s][c][i].id)>0;i++){
+ int j,f=1;
+ if(!battle_config.skillfree) {
+ for(j=0;j<5;j++) {
+ if( skill_tree[s][c][i].need[j].id &&
+ pc_checkskill(sd,skill_tree[s][c][i].need[j].id) < skill_tree[s][c][i].need[j].lv)
+ f=0;
+ }
+ }
+ if(f && sd->status.skill[id].id==0 ){
+ sd->status.skill[id].id=id;
+ flag=1;
+ }
+ }
+ }while(flag);
+ }
+// if(battle_config.etc_log)
+// printf("calc skill_tree\n");
+ return 0;
+}
+
+int pc_calc_skilltree_normalize_job(int c, struct map_session_data *sd) {
//if((battle_config.skillup_limit) && ((c >= 0 && c < 23) || (c >= 4001 && c < 4023) || (c >= 4023 && c < 4045))) {
if (battle_config.skillup_limit && c >= 0 && c < 23) {
int skill_point = pc_calc_skillpoint(sd);
@@ -1000,52 +1050,7 @@ int pc_calc_skilltree(struct map_session_data *sd)
}
}
}
-
- for(i=0;i<MAX_SKILL;i++){
- if (sd->status.skill[i].flag != 13) sd->status.skill[i].id=0;
- if (sd->status.skill[i].flag && sd->status.skill[i].flag != 13){ // cardスキルなら、
- sd->status.skill[i].lv=(sd->status.skill[i].flag==1)?0:sd->status.skill[i].flag-2; // 本?のlvに
- sd->status.skill[i].flag=0; // flagは0にしておく
- }
- }
-
- if (battle_config.gm_allskill > 0 && pc_isGM(sd) >= battle_config.gm_allskill){
- // 全てのスキル
- for(i=1;i<158;i++)
- sd->status.skill[i].id=i;
- for(i=210;i<291;i++)
- sd->status.skill[i].id=i;
- for(i=304;i<337;i++){
- if(i==331) continue;
- sd->status.skill[i].id=i;
- }
- if(battle_config.enable_upper_class){ //confで無?でなければ?み?む
- for(i=355;i<MAX_SKILL;i++)
- sd->status.skill[i].id=i;
- }
- }else{
- // 通常の計算
- do{
- flag=0;
- for(i=0;(id=skill_tree[s][c][i].id)>0;i++){
- int j,f=1;
- if(!battle_config.skillfree) {
- for(j=0;j<5;j++) {
- if( skill_tree[s][c][i].need[j].id &&
- pc_checkskill(sd,skill_tree[s][c][i].need[j].id) < skill_tree[s][c][i].need[j].lv)
- f=0;
- }
- }
- if(f && sd->status.skill[id].id==0 ){
- sd->status.skill[id].id=id;
- flag=1;
- }
- }
- }while(flag);
- }
-// if(battle_config.etc_log)
-// printf("calc skill_tree\n");
- return 0;
+ return c;
}
/*==========================================
diff --git a/src/map/pc.h b/src/map/pc.h
index 0a7026815..7861fb43c 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -44,6 +44,8 @@ int pc_checkskill(struct map_session_data *sd,int skill_id);
int pc_checkallowskill(struct map_session_data *sd);
int pc_checkequip(struct map_session_data *sd,int pos);
+int pc_calc_skilltree_normalize_job(int c, struct map_session_data *sd);
+
int pc_checkoverhp(struct map_session_data*);
int pc_checkoversp(struct map_session_data*);
@@ -170,7 +172,7 @@ struct pc_base_job pc_calc_base_job(int b_class);//転生や養子職の元の職業を返す
int pc_calc_base_job2(int b_class); // Celest
int pc_calc_upper(int b_class);
-struct {
+struct skill_tree_entry {
int id;
int max;
struct {
diff --git a/src/map/skill.c b/src/map/skill.c
index 932542365..7f000f4b4 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -264,7 +264,7 @@ int SkillStatusChangeTable[]={ /* skill.hのenumのSC_***とあわせること */
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
};
-struct skill_name_db skill_names[] = {
+const struct skill_name_db skill_names[] = {
{ AC_CHARGEARROW, "CHARGEARROW", "Charge_Arrow" } ,
{ AC_CONCENTRATION, "CONCENTRATION", "Improve_Concentration" } ,
{ AC_DOUBLE, "DOUBLE", "Double_Strafe" } ,
diff --git a/src/map/skill.h b/src/map/skill.h
index 9e5db0f59..2a7c17652 100644
--- a/src/map/skill.h
+++ b/src/map/skill.h
@@ -31,7 +31,7 @@ struct skill_name_db {
char *name; // search strings
char *desc; // description that shows up for search's
};
-extern struct skill_name_db skill_names[];
+extern const struct skill_name_db skill_names[];
// アイテム作成デ?タベ?ス
struct skill_produce_db {