summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog-Trunk.txt5
-rw-r--r--src/map/pc.c134
-rw-r--r--src/map/pc.h4
3 files changed, 79 insertions, 64 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt
index d17914f97..8e6348e4e 100644
--- a/Changelog-Trunk.txt
+++ b/Changelog-Trunk.txt
@@ -5,6 +5,11 @@ IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK. EV
GOES INTO TRUNK AND WILL BE MERGED INTO STABLE BY VALARIS AND WIZPUTER. -- VALARIS
2006/03/08
+ * Rewrote pc_jobchange to be sane by using the map internal codes instead
+ of a mesh of complicated nested comparisons. [Skotlex]
+ * pc_authok will now change you to a novice if your class isn't identified
+ as a valid one. BACK UP before updating, because.. well, just in case you
+ start seeing novices filling up your city. [Skotlex]
* Mobs will now chase you even if you hit them from outside their range of
view. [Skotlex]
* Fixed item disappearing from the floor when you attempted to pick it up
diff --git a/src/map/pc.c b/src/map/pc.c
index 86e1e0e62..c65f9c7af 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -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;
}
diff --git a/src/map/pc.h b/src/map/pc.h
index 78830b6d9..a1b82dd15 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -198,8 +198,8 @@ struct pc_base_job{
struct pc_base_job pc_calc_base_job(int b_class);//転生や養子職の元の職業を返す
int pc_calc_base_job2(int b_class); // Celest
-unsigned short pc_jobid2mapid(unsigned short b_class); // Skotlex
-unsigned short pc_mapid2jobid(unsigned short class_, int sex); // Skotlex
+int pc_jobid2mapid(unsigned short b_class); // Skotlex
+int pc_mapid2jobid(unsigned short class_, int sex); // Skotlex
char * job_name(int class_);