|
@@ -672,8 +672,14 @@ int pc_authok(struct map_session_data *sd, int login_id2, time_t connect_until_t
|
|
|
}
|
|
|
|
|
|
//Set the map-server used job id. [Skotlex]
|
|
|
- sd->class_ = pc_jobid2mapid((unsigned short) sd->status.class_);
|
|
|
-
|
|
|
+ i = pc_jobid2mapid(sd->status.class_);
|
|
|
+ if (i == -1) { //Invalid class?
|
|
|
+ if (battle_config.error_log)
|
|
|
+ ShowError("pc_authok: Invalid class %d for player %s (%d:%d). Class was changed to novice.\n", sd->status.class_, sd->status.name, sd->status.account_id, sd->status.char_id);
|
|
|
+ sd->status.class_ = JOB_NOVICE;
|
|
|
+ sd->class_ = MAPID_NOVICE;
|
|
|
+ } else
|
|
|
+ sd->class_ = i;
|
|
|
//Initializations to null/0 unneeded since map_session_data was filled with 0 upon allocation.
|
|
|
// 基本的な初期化
|
|
|
sd->state.connect_new = 1;
|
|
@@ -976,9 +982,14 @@ int pc_calc_skilltree(struct map_session_data *sd)
|
|
|
int c=0;
|
|
|
|
|
|
nullpo_retr(0, sd);
|
|
|
-
|
|
|
- c = pc_mapid2jobid(pc_calc_skilltree_normalize_job(sd), sd->status.sex);
|
|
|
-
|
|
|
+ i = pc_calc_skilltree_normalize_job(sd);
|
|
|
+ c = pc_mapid2jobid(i, sd->status.sex);
|
|
|
+ if (c == -1) { //Unable to normalize job??
|
|
|
+ if (battle_config.error_log)
|
|
|
+ ShowError("pc_calc_skilltree: Unable to normalize job %d for character %s (%d:%d)\n", i, sd->status.name, sd->status.account_id, sd->status.char_id);
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+
|
|
|
for(i=0;i<MAX_SKILL;i++){
|
|
|
if (sd->status.skill[i].flag != 13) //Don't touch plagiarized skills
|
|
|
sd->status.skill[i].id=0; //First clear skills.
|
|
@@ -3900,7 +3911,7 @@ int pc_calc_base_job2 (int b_class)
|
|
|
* to the map server's 'makes sense' system. [Skotlex]
|
|
|
*------------------------------------------
|
|
|
*/
|
|
|
-unsigned short pc_jobid2mapid(unsigned short b_class)
|
|
|
+int pc_jobid2mapid(unsigned short b_class)
|
|
|
{
|
|
|
int class_ = 0;
|
|
|
if (b_class >= JOB_BABY && b_class <= JOB_SUPER_BABY)
|
|
@@ -3986,13 +3997,13 @@ unsigned short pc_jobid2mapid(unsigned short b_class)
|
|
|
break;
|
|
|
default:
|
|
|
ShowError("pc_jobid2mapid: Unrecognized job %d!\n", b_class);
|
|
|
- return 0;
|
|
|
+ return -1;
|
|
|
}
|
|
|
return class_;
|
|
|
}
|
|
|
|
|
|
//Reverts the map-style class id to the client-style one.
|
|
|
-unsigned short pc_mapid2jobid(unsigned short class_, int sex) {
|
|
|
+int pc_mapid2jobid(unsigned short class_, int sex) {
|
|
|
switch(class_) {
|
|
|
case MAPID_NOVICE:
|
|
|
return JOB_NOVICE;
|
|
@@ -4136,7 +4147,7 @@ unsigned short pc_mapid2jobid(unsigned short class_, int sex) {
|
|
|
return JOB_BABY_ROGUE;
|
|
|
default:
|
|
|
ShowError("pc_mapid2jobid: Unrecognized job %d!\n", class_);
|
|
|
- return 0;
|
|
|
+ return -1;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -6022,61 +6033,47 @@ int pc_percentheal(struct map_session_data *sd,int hp,int sp)
|
|
|
*/
|
|
|
int pc_jobchange(struct map_session_data *sd,int job, int upper)
|
|
|
{
|
|
|
- int i;
|
|
|
- int b_class = 0;
|
|
|
- //?生や養子の場合の元の職業を算出する
|
|
|
- struct pc_base_job s_class = pc_calc_base_job(sd->status.class_);
|
|
|
+ int i, fame_flag=0;
|
|
|
+ int b_class;
|
|
|
|
|
|
nullpo_retr(0, sd);
|
|
|
|
|
|
if (job < 0)
|
|
|
return 1;
|
|
|
- if (upper < 0 || upper > 2) //現在?生かどうかを判?する
|
|
|
- upper = s_class.upper;
|
|
|
-
|
|
|
- b_class = job; //通常職ならjobそのまんま
|
|
|
- if (job < JOB_SUPER_NOVICE) {
|
|
|
- if (upper == 1)
|
|
|
- b_class += JOB_NOVICE_HIGH;
|
|
|
- else if (upper == 2) //養子に結婚はないけどどうせ次で蹴られるからいいや
|
|
|
- b_class += JOB_BABY;
|
|
|
- } else if (job == JOB_SUPER_NOVICE) {
|
|
|
- if (upper == 1) //?生にスパノビは存在しないのでお?り
|
|
|
- return 1;
|
|
|
- else if (upper == 2)
|
|
|
- b_class = JOB_SUPER_BABY;
|
|
|
- } else if (job == JOB_GUNSLINGER || job == JOB_NINJA) {
|
|
|
- if (upper > 0)
|
|
|
- return 1;
|
|
|
- } else if (job < JOB_SUPER_BABY-JOB_NOVICE_HIGH+JOB_SUPER_NOVICE+2) {
|
|
|
- // Min is SuperNovice +1 -> Becomes Novice High [Skotlex]
|
|
|
- // Max is SuperBaby-NoviceHigh+1 -> Becomes Super Baby
|
|
|
- b_class += JOB_NOVICE_HIGH - JOB_SUPER_NOVICE -1;
|
|
|
- } else if (job >= JOB_TAEKWON && job <= JOB_SOUL_LINKER) {
|
|
|
- if (upper > 0)
|
|
|
- return 1;
|
|
|
- } else if (job < JOB_NOVICE_HIGH || job > JOB_SOUL_LINKER) //Invalid value
|
|
|
- return 1;
|
|
|
-
|
|
|
- job = pc_calc_base_job2 (b_class); // check base class [celest]
|
|
|
|
|
|
- if((sd->status.sex == 0 && job == JOB_BARD) || (sd->status.sex == 1 && job == JOB_DANCER))
|
|
|
+ //Normalize job.
|
|
|
+ b_class = pc_jobid2mapid(job);
|
|
|
+ if (b_class == -1)
|
|
|
return 1;
|
|
|
-
|
|
|
+ switch (upper) {
|
|
|
+ case 1:
|
|
|
+ b_class|= JOBL_UPPER;
|
|
|
+ break;
|
|
|
+ case 2:
|
|
|
+ b_class|= JOBL_BABY;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ //This will automatically adjust bard/dancer classes to the correct gender
|
|
|
+ //That is, if you try to jobchange into dancer, it will turn you to bard.
|
|
|
+ job = pc_mapid2jobid(b_class, sd->status.sex);
|
|
|
+ if (job == -1)
|
|
|
+ return 1;
|
|
|
+
|
|
|
+ if ((unsigned short)b_class == sd->class_)
|
|
|
+ return 1; //Nothing to change.
|
|
|
// check if we are changing from 1st to 2nd job
|
|
|
- if ((job >= JOB_KNIGHT && job <= JOB_CRUSADER2) || (job >= JOB_STAR_GLADIATOR && job <= JOB_SOUL_LINKER)) {
|
|
|
- if ((s_class.job > JOB_NOVICE && s_class.job < JOB_KNIGHT) || s_class.job == JOB_TAEKWON)
|
|
|
+ if (b_class&JOBL_2) {
|
|
|
+ if (!(sd->class_&JOBL_2))
|
|
|
sd->change_level = sd->status.job_level;
|
|
|
- else
|
|
|
- sd->change_level = 40;
|
|
|
+ else if (!sd->change_level)
|
|
|
+ sd->change_level = 40; //Assume 40?
|
|
|
}
|
|
|
- else
|
|
|
- sd->change_level = 0;
|
|
|
|
|
|
pc_setglobalreg (sd, "jobchange_level", sd->change_level);
|
|
|
|
|
|
- sd->status.class_ = sd->view_class = b_class;
|
|
|
- sd->class_ = pc_jobid2mapid(sd->status.class_);
|
|
|
+ sd->status.class_ = sd->view_class = job;
|
|
|
+ fame_flag = pc_istop10fame(sd->status.char_id,sd->class_&MAPID_UPPERMASK);
|
|
|
+ sd->class_ = (unsigned short)b_class;
|
|
|
sd->status.job_level=1;
|
|
|
sd->status.job_exp=0;
|
|
|
clif_updatestatus(sd,SP_JOBLEVEL);
|
|
@@ -6093,25 +6090,38 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
|
|
|
|
|
|
if(battle_config.save_clothcolor &&
|
|
|
sd->status.clothes_color > 0 &&
|
|
|
- ((sd->view_class != JOB_WEDDING && sd->view_class !=JOB_XMAS) || (sd->view_class==JOB_WEDDING && !battle_config.wedding_ignorepalette) ||
|
|
|
- (sd->view_class==JOB_XMAS && !battle_config.xmas_ignorepalette)))
|
|
|
+ ((sd->view_class != JOB_WEDDING && sd->view_class !=JOB_XMAS) ||
|
|
|
+ (sd->view_class==JOB_WEDDING && !battle_config.wedding_ignorepalette) ||
|
|
|
+ (sd->view_class==JOB_XMAS && !battle_config.xmas_ignorepalette)))
|
|
|
clif_changelook(&sd->bl,LOOK_CLOTHES_COLOR,sd->status.clothes_color);
|
|
|
- if(battle_config.muting_players && sd->status.manner < 0 && battle_config.manner_system)
|
|
|
+
|
|
|
+ if(battle_config.muting_players && sd->status.manner < 0 && battle_config.manner_system)
|
|
|
clif_changestatus(&sd->bl,SP_MANNER,sd->status.manner);
|
|
|
|
|
|
- if(pc_isriding(sd)) { // remove peco status if changing into invalid class [Valaris]
|
|
|
- if(!(pc_checkskill(sd,KN_RIDING)))
|
|
|
- pc_setoption(sd,sd->sc.option&~OPTION_RIDING);
|
|
|
- else
|
|
|
- pc_setriding(sd);
|
|
|
- }
|
|
|
+
|
|
|
+ if(pc_isriding(sd)) //Remove Peco Status to prevent display <> class problems.
|
|
|
+ pc_setoption(sd,sd->sc.option&~OPTION_RIDING);
|
|
|
|
|
|
status_calc_pc(sd,0);
|
|
|
pc_checkallowskill(sd);
|
|
|
pc_equiplookall(sd);
|
|
|
clif_equiplist(sd);
|
|
|
- chrif_save(sd,0); //Why are we saving it?
|
|
|
- chrif_reqfamelist();
|
|
|
+
|
|
|
+ //if you were previously famous, not anymore.
|
|
|
+ if (fame_flag) {
|
|
|
+ chrif_save(sd,0);
|
|
|
+ chrif_reqfamelist();
|
|
|
+ } else if (sd->status.fame > 0) {
|
|
|
+ //It may be that now they are famous?
|
|
|
+ switch (sd->class_&MAPID_UPPERMASK) {
|
|
|
+ case MAPID_BLACKSMITH:
|
|
|
+ case MAPID_ALCHEMIST:
|
|
|
+ case MAPID_TAEKWON:
|
|
|
+ chrif_save(sd,0);
|
|
|
+ chrif_reqfamelist();
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
return 0;
|
|
|
}
|