Explorar o código

* Fixed bugreport:8471, http://rathena.org/board/tracker/issue-8471-star-gladiators-feeling-randomising-map/
* Follow up f4eb33e, 5a2849d

Signed-off-by: Cydh Ramdh <house.bad@gmail.com>

Cydh Ramdh %!s(int64=11) %!d(string=hai) anos
pai
achega
a32d3a6e76
Modificáronse 6 ficheiros con 93 adicións e 49 borrados
  1. 1 1
      src/map/clif.c
  2. 12 10
      src/map/npc.c
  3. 3 3
      src/map/pc.c
  4. 73 31
      src/map/skill.c
  5. 2 2
      src/map/skill.h
  6. 2 2
      src/map/unit.c

+ 1 - 1
src/map/clif.c

@@ -8994,7 +8994,7 @@ void clif_feel_info(struct map_session_data* sd, unsigned char feel_level, unsig
 {
 	char mapname[MAP_NAME_LENGTH_EXT];
 
-	mapindex_getmapname_ext(mapindex_id2name(sd->feel_map[feel_level].index), mapname);
+	mapindex_getmapname_ext(map[sd->feel_map[feel_level].m].name, mapname);
 	clif_starskill(sd, mapname, 0, feel_level, type ? 1 : 0);
 }
 

+ 12 - 10
src/map/npc.c

@@ -122,16 +122,18 @@ struct view_data* npc_get_viewdata(int class_)
 int npc_isnear_sub(struct block_list* bl, va_list args) {
     struct npc_data *nd = (struct npc_data*)bl;
 	int skill_id = va_arg(args, int);
-	uint16 idx = -1;
-
-	//Check the NPC type if is used by INF2_NO_NEARNPC (skill_id is not null) [Cydh]
-	if (skill_id && (idx = skill_get_index(skill_id)) && skill_db[idx].unit_nonearnpc_type) {
-		while (1) {
-			if (skill_db[idx].unit_nonearnpc_type&1 && nd->subtype == WARP) break;
-			if (skill_db[idx].unit_nonearnpc_type&2 && nd->subtype == SHOP) break;
-			if (skill_db[idx].unit_nonearnpc_type&4 && nd->subtype == SCRIPT) break;
-			if (skill_db[idx].unit_nonearnpc_type&8 && nd->subtype == TOMB) break;
-				return 0;
+
+	if (skill_id > 0) { //If skill_id > 0 that means is used for INF2_NO_NEARNPC [Cydh]
+		int16 idx = skill_get_index(skill_id);
+
+		if (idx >= 0 && skill_db[idx].unit_nonearnpc_type) {
+			while (1) {
+				if (skill_db[idx].unit_nonearnpc_type&1 && nd->subtype == WARP) break;
+				if (skill_db[idx].unit_nonearnpc_type&2 && nd->subtype == SHOP) break;
+				if (skill_db[idx].unit_nonearnpc_type&4 && nd->subtype == SCRIPT) break;
+				if (skill_db[idx].unit_nonearnpc_type&8 && nd->subtype == TOMB) break;
+					return 0;
+			}
 		}
 	}
 

+ 3 - 3
src/map/pc.c

@@ -1231,7 +1231,7 @@ int pc_reg_received(struct map_session_data *sd)
 	//SG map and mob read [Komurka]
 	for(i=0;i<MAX_PC_FEELHATE;i++) //for now - someone need to make reading from txt/sql
 	{
-		uint8 j;
+		uint16 j;
 		if ((j = pc_readglobalreg(sd,sg_info[i].feel_var))!=0) {
 			sd->feel_map[i].index = j;
 			sd->feel_map[i].m = map_mapindex2mapid(j);
@@ -1254,10 +1254,10 @@ int pc_reg_received(struct map_session_data *sd)
 	}
 	if ((i = pc_checkskill(sd,SC_REPRODUCE)) > 0) {
 		sd->reproduceskill_idx = skill_get_index(pc_readglobalreg(sd,SKILL_VAR_REPRODUCE));
-		if( sd->reproduceskill_idx >= 0) {
+		if (sd->reproduceskill_idx >= 0) {
 			sd->status.skill[sd->reproduceskill_idx].id = pc_readglobalreg(sd,SKILL_VAR_REPRODUCE);
 			sd->status.skill[sd->reproduceskill_idx].lv = pc_readglobalreg(sd,SKILL_VAR_REPRODUCE_LV);
-			if( i < sd->status.skill[sd->reproduceskill_idx].lv)
+			if (i < sd->status.skill[sd->reproduceskill_idx].lv)
 				sd->status.skill[sd->reproduceskill_idx].lv = i;
 			sd->status.skill[sd->reproduceskill_idx].flag = SKILL_FLAG_PLAGIARIZED;
 		}

+ 73 - 31
src/map/skill.c

@@ -450,7 +450,7 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 sk
 * @param sd: Player who will copy the skill
 * @param skill_id: Target skill
 * @return 0 - Cannot be copied; 1 - Can be copied by Plagiarism 2 - Can be copied by Reproduce
-* @author Aru -for previous check; Jobbie for class restriction idea; Cydh expands the copyable skill
+* @author Aru - for previous check; Jobbie for class restriction idea; Cydh expands the copyable skill
 */
 static char skill_isCopyable(struct map_session_data *sd, uint16 skill_id) {
 	int idx = skill_get_index(skill_id);
@@ -484,8 +484,13 @@ static char skill_isCopyable(struct map_session_data *sd, uint16 skill_id) {
 	return 0;
 }
 
-// [MouseJstr] - skill ok to cast? and when?
-//done before check_condition_begin, requirement
+/** Check if the skill is ok to cast and when.
+* Done before check_condition_begin, requirement
+* @param skill_id: Skill ID that casted
+* @param sd: Player who casted
+* @return true: Skill cannot be used, false: otherwise
+* @author [MouseJstr]
+*/
 bool skill_isNotOk(uint16 skill_id, struct map_session_data *sd)
 {
 	int16 idx,m;
@@ -641,6 +646,12 @@ bool skill_isNotOk(uint16 skill_id, struct map_session_data *sd)
 	return (map[m].flag.noskill);
 }
 
+/** Check if the homunculus skill is ok to be processed
+* After checking from Homunculus side, also check the master condition
+* @param skill_id: Skill ID that casted
+* @param hd: Homunculus who casted
+* @return true: Skill cannot be used, false: otherwise
+*/
 bool skill_isNotOk_hom(uint16 skill_id, struct homun_data *hd)
 {
 	uint16 idx = skill_get_index(skill_id);
@@ -660,33 +671,39 @@ bool skill_isNotOk_hom(uint16 skill_id, struct homun_data *hd)
 			if(hd->homunculus.hunger <= 1) return true;
 			break;
 		case MH_GOLDENE_FERSE: //cant be used with angriff
-			if(hd->sc.data[SC_ANGRIFFS_MODUS]) return true;
+			if(&hd->sc && hd->sc.data[SC_ANGRIFFS_MODUS]) return true;
 			break;
 		case MH_ANGRIFFS_MODUS:
-			if(hd->sc.data[SC_GOLDENE_FERSE]) return true;
+			if(&hd->sc && hd->sc.data[SC_GOLDENE_FERSE]) return true;
 			break;
 		case MH_TINDER_BREAKER: //must be in grappling mode
-			if(!(hd->sc.data[SC_STYLE_CHANGE] && hd->sc.data[SC_STYLE_CHANGE]->val1 == MH_MD_GRAPPLING)
+			if(!&hd->sc
+				|| !(hd->sc.data[SC_STYLE_CHANGE] && hd->sc.data[SC_STYLE_CHANGE]->val1 == MH_MD_GRAPPLING)
 				|| !hd->homunculus.spiritball) return true;
 			break;
 		case MH_SONIC_CRAW: //must be in fighting mode
-			if(!(hd->sc.data[SC_STYLE_CHANGE] && hd->sc.data[SC_STYLE_CHANGE]->val1 == MH_MD_FIGHTING)
+			if(!&hd->sc
+				|| !(hd->sc.data[SC_STYLE_CHANGE] && hd->sc.data[SC_STYLE_CHANGE]->val1 == MH_MD_FIGHTING)
 				|| !hd->homunculus.spiritball) return true;
 			break;
 		case MH_SILVERVEIN_RUSH:
-			if(!(hd->sc.data[SC_COMBO] && hd->sc.data[SC_COMBO]->val1 == MH_SONIC_CRAW)
+			if(!&hd->sc
+				|| !(hd->sc.data[SC_COMBO] && hd->sc.data[SC_COMBO]->val1 == MH_SONIC_CRAW)
 				|| hd->homunculus.spiritball < 2) return true;
 			break;
 		case MH_MIDNIGHT_FRENZY:
-			if(!(hd->sc.data[SC_COMBO] && hd->sc.data[SC_COMBO]->val1 == MH_SILVERVEIN_RUSH)
+			if(!&hd->sc
+				|| !(hd->sc.data[SC_COMBO] && hd->sc.data[SC_COMBO]->val1 == MH_SILVERVEIN_RUSH)
 				|| !hd->homunculus.spiritball) return true;
 			break;
 		case MH_CBC:
-			if(!(hd->sc.data[SC_COMBO] && hd->sc.data[SC_COMBO]->val1 == MH_TINDER_BREAKER)
+			if(!&hd->sc
+				|| !(hd->sc.data[SC_COMBO] && hd->sc.data[SC_COMBO]->val1 == MH_TINDER_BREAKER)
 				|| hd->homunculus.spiritball < 2) return true;
 			break;
 		case MH_EQC:
-			if(!(hd->sc.data[SC_COMBO] && hd->sc.data[SC_COMBO]->val1 == MH_CBC)
+			if(!&hd->sc
+				|| !(hd->sc.data[SC_COMBO] && hd->sc.data[SC_COMBO]->val1 == MH_CBC)
 				|| hd->homunculus.spiritball < 3) return true;
 			break;
 	}
@@ -695,6 +712,12 @@ bool skill_isNotOk_hom(uint16 skill_id, struct homun_data *hd)
 	return skill_isNotOk(skill_id, hd->master);
 }
 
+/** Check if the mercenary skill is ok to be processed
+* After checking from Homunculus side, also check the master condition
+* @param skill_id: Skill ID that casted
+* @param md: Mercenary who casted
+* @return true: Skill cannot be used, false: otherwise
+*/
 bool skill_isNotOk_mercenary(uint16 skill_id, struct mercenary_data *md)
 {
 	uint16 idx = skill_get_index(skill_id);
@@ -708,9 +731,16 @@ bool skill_isNotOk_mercenary(uint16 skill_id, struct mercenary_data *md)
 	return skill_isNotOk(skill_id, md->master);
 }
 
-/// Check if the skill can be casted near NPC or not [Cydh]
-/// NOTE: 'target' may be NULL if the skill is targetting ground/area
-bool skill_isNotOk_npcRange(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int pos_x, int pos_y) {
+/** Check if the skill can be casted near NPC or not
+* @param src Object who casted
+* @param skill_id Skill ID that casted
+* @param skill_lv Skill Lv
+* @param pos_x Position x of the target
+* @param pos_y Position y of the target
+* @return true: Skill cannot be used, false: otherwise
+* @author [Cydh]
+*/
+bool skill_isNotOk_npcRange(struct block_list *src, uint16 skill_id, uint16 skill_lv, int pos_x, int pos_y) {
 	int inf;
 
 	if (!src || skill_get_index(skill_id) < 0)
@@ -726,10 +756,8 @@ bool skill_isNotOk_npcRange(struct block_list *src, struct block_list *target, u
 		pos_y = src->y;
 	}
 
-	if (pos_x <= 0 || pos_y <= 0) {
-		pos_x = src->x;
-		pos_y = src->y;
-	}
+	if (pos_x <= 0) pos_x = src->x;
+	if (pos_y <= 0) pos_y = src->y;
 
 	return skill_check_unit_range2(src,pos_x,pos_y,skill_id,skill_lv,true);
 }
@@ -2526,8 +2554,7 @@ static void skill_do_copy(struct block_list* src,struct block_list *bl, uint16 s
 						tsd->status.skill[tsd->cloneskill_idx].flag = SKILL_FLAG_PERMANENT;
 					}
 
-					if ((lv = pc_checkskill(tsd,RG_PLAGIARISM)) < skill_lv)
-						skill_lv = lv;
+					lv = min(skill_lv,pc_checkskill(tsd,RG_PLAGIARISM)); //Copied level never be > player's RG_PLAGIARISM level
 
 					tsd->cloneskill_idx = idx;
 					pc_setglobalreg(tsd,SKILL_VAR_PLAGIARISM,skill_id);
@@ -2547,6 +2574,12 @@ static void skill_do_copy(struct block_list* src,struct block_list *bl, uint16 s
 						tsd->status.skill[tsd->reproduceskill_idx].flag = SKILL_FLAG_PERMANENT;
 					}
 
+					//Level dependent and limitation.
+					if (src->type == BL_PC) //If player, max skill level is skill_get_max(skill_id)
+						lv = min(lv,skill_get_max(skill_id));
+					else //Monster might used skill level > allowed player max skill lv. Ex. Drake with Waterball lv. 10
+						lv = min(lv,skill_lv);
+
 					tsd->reproduceskill_idx = idx;
 					pc_setglobalreg(tsd,SKILL_VAR_REPRODUCE,skill_id);
 					pc_setglobalreg(tsd,SKILL_VAR_REPRODUCE_LV,lv);
@@ -2582,7 +2615,8 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
 	struct map_session_data *sd, *tsd;
 	int64 damage;
 	int8 rmdamage=0;//magic reflected
-	int type, shadow_flag = 0;
+	int type;
+	bool shadow_flag = false;
 	bool additional_effects = true;
 
 	if(skill_id > 0 && !skill_lv) return 0;
@@ -3194,7 +3228,15 @@ static int skill_check_unit_range2_sub (struct block_list *bl, va_list ap)
 	return 1;
 }
 
-//NOTE: 'isNearNPC' is used to check is the skill near NPC or not, if yes will use npc_isnear and range calculation [Cydh]
+/** Used to check range condition of the casted skill. Used if the skill has UF_NOFOOTSET or INF2_NO_NEARNPC
+* @param bl Object that casted skill
+* @param x Position x of the target
+* @param y Position y of the target
+* @param skill_id The casted skill
+* @param skill_lv The skill Lv
+* @param isNearNPC 'true' means, check the range between target and nearer NPC by using npc_isnear and range calculation [Cydh]
+* @return 0: No object (BL_CHAR or BL_PC) within the range. If 'isNearNPC' the target oject is BL_NPC
+*/
 static int skill_check_unit_range2 (struct block_list *bl, int x, int y, uint16 skill_id, uint16 skill_lv, bool isNearNPC)
 {
 	int range = 0, type;
@@ -5472,7 +5514,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
 				abra_skill_id = skill_abra_db[i].skill_id;
 				abra_skill_lv = min(skill_lv, skill_get_max(abra_skill_id));
 			} while (abra_skill_id == 0 ||
-				rnd()%10000 >= skill_abra_db[i].per[abra_skill_lv]
+				rnd()%10000 >= skill_abra_db[i].per[max(skill_lv-1,0)]
 			);
 
 			clif_skill_nodamage (src, bl, skill_id, skill_lv, 1);
@@ -16079,15 +16121,15 @@ bool skill_check_cloaking(struct block_list *bl, struct status_change_entry *sce
 * @param bl: Target
 * @param damage: Damage amount
 * @param hit
-* @return val
+* @return true - in Shadow Form state; false - otherwise
 */
-char skill_check_shadowform(struct block_list *bl, int64 damage, int hit) {
+bool skill_check_shadowform(struct block_list *bl, int64 damage, int hit) {
 	struct status_change *sc;
 
-	nullpo_retr(0, bl);
+	nullpo_retr(false,bl);
 
 	if (!damage)
-		return 0;
+		return false;
 
 	sc = status_get_sc(bl);
 
@@ -16096,14 +16138,14 @@ char skill_check_shadowform(struct block_list *bl, int64 damage, int hit) {
 
 		if( !src || src->m != bl->m ) { 
 			status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER);
-			return 0;
+			return false;
 		}
 
 		if( src && (status_isdead(src) || !battle_check_target(bl,src,BCT_ENEMY)) ) {
 			if( src->type == BL_PC )
 				((TBL_PC*)src)->shadowform_id = 0;
 			status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER);
-			return 0;
+			return false;
 		}
 
 		status_damage(bl, src, damage, 0, clif_damage(src, src, gettick(), 500, 500, damage, hit, (hit > 1 ? 8 : 0), 0), 0);
@@ -16112,9 +16154,9 @@ char skill_check_shadowform(struct block_list *bl, int64 damage, int hit) {
 			if( src->type == BL_PC )
 				((TBL_PC*)src)->shadowform_id = 0;
 		}
-		return 1;
+		return true;
 	}
-	return 0;
+	return false;
 }
 
 bool skill_check_camouflage(struct block_list *bl, struct status_change_entry *sce)

+ 2 - 2
src/map/skill.h

@@ -417,7 +417,7 @@ bool skill_isNotOk(uint16 skill_id, struct map_session_data *sd);
 bool skill_isNotOk_hom(uint16 skill_id, struct homun_data *hd);
 bool skill_isNotOk_mercenary(uint16 skill_id, struct mercenary_data *md);
 
-bool skill_isNotOk_npcRange(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int pos_x, int pos_y);
+bool skill_isNotOk_npcRange(struct block_list *src, uint16 skill_id, uint16 skill_lv, int pos_x, int pos_y);
 
 int skill_chastle_mob_changetarget(struct block_list *bl,va_list ap);
 
@@ -1966,7 +1966,7 @@ struct s_skill_magicmushroom_db {
 };
 extern struct s_skill_magicmushroom_db skill_magicmushroom_db[MAX_SKILL_MAGICMUSHROOM_DB];
 int skill_maelstrom_suction(struct block_list *bl, va_list ap);
-char skill_check_shadowform(struct block_list *bl, int64 damage, int hit);
+bool skill_check_shadowform(struct block_list *bl, int64 damage, int hit);
 /**
  * Ranger
  **/

+ 2 - 2
src/map/unit.c

@@ -1357,7 +1357,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
 		return 0;
 
 	// Fail if the targetted skill is near NPC [Cydh]
-	if(skill_get_inf2(skill_id)&INF2_NO_NEARNPC && skill_isNotOk_npcRange(src,target,skill_id,skill_lv,target->x,target->y)) {
+	if(skill_get_inf2(skill_id)&INF2_NO_NEARNPC && skill_isNotOk_npcRange(src,skill_id,skill_lv,target->x,target->y)) {
 		if (sd)
 			clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
 		return 0;
@@ -1674,7 +1674,7 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui
 		return 0;
 
 	// Fail if the targetted skill is near NPC [Cydh]
-	if(skill_get_inf2(skill_id)&INF2_NO_NEARNPC && skill_isNotOk_npcRange(src,NULL,skill_id,skill_lv,skill_x,skill_y)) {
+	if(skill_get_inf2(skill_id)&INF2_NO_NEARNPC && skill_isNotOk_npcRange(src,skill_id,skill_lv,skill_x,skill_y)) {
 		if (sd)
 			clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
 		return 0;