Browse Source

-pc_jobid2mapid and pc_mapid2jobid now return int, and will return -1 when the class couldn't be deciphered.
- pc_authok will change you to notice if your current class is invalid.
- rewrote pc_jobchange to be much more simple and less of a hassle by using pc_jobid2mapid and pc_mapid2jobid as necessary.


git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@5520 54d463be-8e91-2dee-dedb-b68131a5f0ec

skotlex 19 năm trước cách đây
mục cha
commit
3eb48e92a4
3 tập tin đã thay đổi với 79 bổ sung64 xóa
  1. 5 0
      Changelog-Trunk.txt
  2. 72 62
      src/map/pc.c
  3. 2 2
      src/map/pc.h

+ 5 - 0
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

+ 72 - 62
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;
 }

+ 2 - 2
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_);