diff --git a/src/map/clif.c b/src/map/clif.c index 2e0479dc58..388930fbdc 100644 --- a/src/map/clif.c +++ b/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); } diff --git a/src/map/npc.c b/src/map/npc.c index 92d7c7c38e..49c9c5a945 100644 --- a/src/map/npc.c +++ b/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; + } } } diff --git a/src/map/pc.c b/src/map/pc.c index ea137e3c8f..21c26b9213 100755 --- a/src/map/pc.c +++ b/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;ifeel_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; } diff --git a/src/map/skill.c b/src/map/skill.c index 109ef307e5..4478f2603c 100755 --- a/src/map/skill.c +++ b/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) diff --git a/src/map/skill.h b/src/map/skill.h index e636ecbd58..a1dbd03161 100644 --- a/src/map/skill.h +++ b/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 **/ diff --git a/src/map/unit.c b/src/map/unit.c index abcac67559..f9bd899a23 100644 --- a/src/map/unit.c +++ b/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;