From 04a1173f7d4c0e1ffbace05d34d8b60dfd037a94 Mon Sep 17 00:00:00 2001 From: Playtester Date: Fri, 7 Nov 2014 23:28:54 +0100 Subject: [PATCH] Plant damage, Land Mine, minor fixes and improvements - Fixed up the damage code in regards of damage against plants (bugreport:9380) * Rewrote DAMAGE_DIV_FIX so that it rounds damage down when number of hits is negative (damage split on hits) * Created a function battle_apply_div_fix that does not only call DAMAGE_DIV_FIX but also makes sure that damage can only become 0 when the custom config setting skill_min_damage is not set for the current skill type * skill_min_damage is now 0 by default (official: all types can fail against plants as long as skills have negative number of hits), if set, all skills will deal as much damage as hits * Restructured and renamed function now known as "is_infinite_defense" that will work for all 3 damage types and returns if damage is infinite for the current situation, it will now also properly consider all "MD_IGNORE" modes * Fixed the order of processing of all 3 skill types in regards of plant damage: first all calculations are done, then plant damage is applied and then DAMAGE_DIV_FIX is applied * Sonic Blow and Rapid Shower are now skills with negative number of hits (i.e. they can't hit plants officially) * Traps can no longer ignore plant mode (only way to damage plant more is via status changes) * Final Strike is now able to hit plants (deals 1 HP damage) * When left-hand-wielding, you will now always deal 2 damage to plants per attack, regardless of whether double attack triggers or you don't even have a weapon in the right hand * There will no longer be backhand damage to plants (Katar) - Land Mine is now a single target skill, the trap still triggers in a 3x3 area, but will only hit the first target that touches it (issue:99) - Changed the "Don't return reflect damage" flag from 0x1000 to 0x1000000 as apparently the other flag was already used; updated function description so it's easier to see - Improved SC_SIGHTBLASTER structure slightly - Typo fixes and description improvements --- conf/battle/misc.conf | 2 +- conf/battle/skill.conf | 12 ++- db/pre-re/skill_cast_db.txt | 2 +- db/pre-re/skill_db.txt | 6 +- db/re/skill_cast_db.txt | 2 +- db/re/skill_db.txt | 6 +- src/map/battle.c | 150 ++++++++++++++++++------------------ src/map/skill.c | 17 ++-- src/map/status.c | 16 ++-- src/map/status.h | 4 +- src/map/unit.c | 2 +- 11 files changed, 113 insertions(+), 106 deletions(-) diff --git a/conf/battle/misc.conf b/conf/battle/misc.conf index 39001430fd1..9b1e668e047 100644 --- a/conf/battle/misc.conf +++ b/conf/battle/misc.conf @@ -93,7 +93,7 @@ duel_only_on_same_map: no // If a unit stops walking and is on a cell with more than stack limit // characters on it, it will walk to the closest free cell. // Custom - This variation will make every full cell to be considered a wall. -// NOTE: For this setting to take effect you have to use a server compiled +// NOTE: For the custom setting to take effect you have to use a server compiled // with Cell Stack Limit support (see src/map/map.h) official_cell_stack_limit: 1 custom_cell_stack_limit: 1 diff --git a/conf/battle/skill.conf b/conf/battle/skill.conf index 1a5a491bf8a..c0a3ceb2c94 100644 --- a/conf/battle/skill.conf +++ b/conf/battle/skill.conf @@ -89,10 +89,14 @@ clear_skills_on_warp: 15 //See db/skill_unit_db.txt for more info. defunit_not_enemy: no -// Do skills do at least 'hits' damage when they don't miss/are blocked? -//(for example, will firebolts always do "number of bolts" damage versus plants?) -//Values (add as appropriate): 1 for weapon-based attacks, 2 for magic attacks, 4 for misc attacks. -skill_min_damage: 6 +// Should skills always do at least 'hits' damage when they don't miss/are blocked? +// Many skills will have their damage multiplied by their number of hits (see skill_db), these will always deal 1 HP +// damage per hit, even against plants. But some skills are actually a single hit that is just displayed as multiple +// hits. For these skills, damage gets divided by number of hits and rounded down. That means that plants won't take +// any damage from them. Examples: Sonic Blow, Lord of Vermillion +// With this setting, you can change the official behavior and make these skills deal at least 1 HP damage per hit. +// Values: 1 for weapon-based attacks, 2 for magic attacks, 4 for misc attacks. +skill_min_damage: 0 // The delay rate of monk's combo (Note 2) combo_delay_rate: 100 diff --git a/db/pre-re/skill_cast_db.txt b/db/pre-re/skill_cast_db.txt index 5d661622c82..873ddaeea83 100644 --- a/db/pre-re/skill_cast_db.txt +++ b/db/pre-re/skill_cast_db.txt @@ -5,7 +5,7 @@ // // CastingTime: time to cast this skill, in milliseconds // AfterCastActDelay: "normal" delay, character cannot use skills, in milliseconds -// AfterCastWalkDleay: amount of time before character can move again, in milliseconds +// AfterCastWalkDelay: amount of time before character can move again, in milliseconds // Duration1/Duration2: usually the durations used by the skill, at special cases it is used to hold special data // Cool Down: amount of time until character can re-use this skill, in milliseconds // diff --git a/db/pre-re/skill_db.txt b/db/pre-re/skill_db.txt index 7294c8d3def..7721d2a348f 100644 --- a/db/pre-re/skill_db.txt +++ b/db/pre-re/skill_db.txt @@ -214,7 +214,7 @@ //**** // Hunter 115,3,6,2,0,0x1,0,5,1,no,0,0x80,0,misc,6:7:8:9:10,0x3000, HT_SKIDTRAP,Skid Trap -116,3,6,2,2,0x42,1,5,1,no,0,0x80,0,misc,0,0x3800, HT_LANDMINE,Land Mine +116,3,6,2,2,0x42,0,5,1,no,0,0x80,0,misc,0,0x3800, HT_LANDMINE,Land Mine 117,3,6,2,0,0x1,0,5,1,no,0,0x80,0,misc,0,0x3000, HT_ANKLESNARE,Ankle Snare 118,3,6,2,0,0x2,1,5,1,no,0,0x80,0,misc,0,0x3000, HT_SHOCKWAVE,Shockwave Trap 119,3,6,2,0,0x3,2,5,1,no,0,0x80,0,misc,0,0x3000, HT_SANDMAN,Sandman @@ -237,7 +237,7 @@ 133,0,0,0,0,0,0,5,0,no,0,0,0,weapon,0,0x0, AS_LEFT,Lefthand Mastery 134,0,0,0,0,0,0,10,0,no,0,0,0,weapon,0,0x0, AS_KATAR,Katar Mastery 135,0,6,4,0,0x1,0,10,1,no,0,0,0,weapon,0,0x60, AS_CLOAKING,Cloaking -136,1,8,1,-1,0,0,10,8,no,0,0,0,weapon,0,0x0, AS_SONICBLOW,Sonic Blow +136,1,8,1,-1,0,0,10,-8,no,0,0,0,weapon,0,0x0, AS_SONICBLOW,Sonic Blow 137,3:4:5:6:7,6,1,-1,0x2,1,5,1,no,0,0,0,weapon,0,0x4, AS_GRIMTOOTH,Grimtooth 138,1,6,16,5,0x1,0,10,1,no,0,0x400,0,weapon,0,0x0, AS_ENCHANTPOISON,Enchant Poison 139,0,6,4,0,0,0,10,1,no,0,0,0,weapon,0,0x0, AS_POISONREACT,Poison React @@ -733,7 +733,7 @@ 512,-9,6,1,-1,0,0,10,1,yes,0,0,0,weapon,0,0x0, GS_TRACKING,Tracking 513,-9,6,1,-1,0,0,5,1,no,0,0,0,weapon,0,0x0, GS_DISARM,Disarm 514,-9,6,1,-1,0x20,0,5,1,no,0,0,0,weapon,0,0x100, GS_PIERCINGSHOT,Piercing Shot -515,-9,8,1,-1,0,0,10,5,no,0,0,0,weapon,0,0x100, GS_RAPIDSHOWER,Rapid Shower +515,-9,8,1,-1,0,0,10,-5,no,0,0,0,weapon,0,0x100, GS_RAPIDSHOWER,Rapid Shower 516,0,8,4,-1,0x2,3,10,1,no,0,0,0,weapon,0,0x0, GS_DESPERADO,Desperado 517,0,6,4,-1,0x1,0,10,1,no,0,0,0,weapon,0,0x0, GS_GATLINGFEVER,Gatling Fever 518,2,6,1,-1,0,0,10,1,no,0,0,0,weapon,5,0x0, GS_DUST,Dust diff --git a/db/re/skill_cast_db.txt b/db/re/skill_cast_db.txt index 0140631a655..5e4fd7cb1a3 100644 --- a/db/re/skill_cast_db.txt +++ b/db/re/skill_cast_db.txt @@ -5,7 +5,7 @@ // // CastingTime: time to cast this skill, in milliseconds // AfterCastActDelay: "normal" delay, character cannot use skills, in milliseconds -// AfterCastWalkDleay: amount of time before character can move again, in milliseconds +// AfterCastWalkDelay: amount of time before character can move again, in milliseconds // Duration1/Duration2: usually the durations used by the skill, at special cases it is used to hold special data // Cool Down: amount of time until character can re-use this skill, in milliseconds // Fixed Casting Time: the skills fixed casting time (when 0, uses 20% of cast time and less than 0 means no fixed cast time) diff --git a/db/re/skill_db.txt b/db/re/skill_db.txt index 055f357733f..d9872d2fab9 100644 --- a/db/re/skill_db.txt +++ b/db/re/skill_db.txt @@ -214,7 +214,7 @@ //**** // Hunter 115,3,6,2,0,0x1,0,5,1,no,0,0x80,0,misc,6:7:8:9:10,0x3000, HT_SKIDTRAP,Skid Trap -116,3,6,2,2,0x42,1,5,1,no,0,0x80,0,misc,0,0x3800, HT_LANDMINE,Land Mine +116,3,6,2,2,0x42,0,5,1,no,0,0x80,0,misc,0,0x3800, HT_LANDMINE,Land Mine 117,3,6,2,0,0x1,0,5,1,no,0,0x80,0,misc,0,0x3000, HT_ANKLESNARE,Ankle Snare 118,3,6,2,0,0x2,1,5,1,no,0,0x80,0,misc,0,0x3000, HT_SHOCKWAVE,Shockwave Trap 119,3,6,2,0,0x3,2,5,1,no,0,0x80,0,misc,0,0x3000, HT_SANDMAN,Sandman @@ -237,7 +237,7 @@ 133,0,0,0,0,0,0,5,0,no,0,0,0,weapon,0,0x0, AS_LEFT,Lefthand Mastery 134,0,0,0,0,0,0,10,0,no,0,0,0,weapon,0,0x0, AS_KATAR,Katar Mastery 135,0,6,4,0,0x1,0,10,1,no,0,0,0,weapon,0,0x60, AS_CLOAKING,Cloaking -136,1,8,1,-1,0,0,10,8,no,0,0,0,weapon,0,0x0, AS_SONICBLOW,Sonic Blow +136,1,8,1,-1,0,0,10,-8,no,0,0,0,weapon,0,0x0, AS_SONICBLOW,Sonic Blow 137,3:4:5:6:7,6,1,-1,0x2,1,5,1,no,0,0,0,weapon,0,0x4, AS_GRIMTOOTH,Grimtooth 138,1,6,16,5,0x1,0,10,1,no,0,0x400,0,weapon,0,0x0, AS_ENCHANTPOISON,Enchant Poison 139,0,6,4,0,0,0,10,1,no,0,0,0,weapon,0,0x0, AS_POISONREACT,Poison React @@ -733,7 +733,7 @@ 512,-9,6,1,-1,0,0,10,1,yes,0,0,0,weapon,0,0x0, GS_TRACKING,Tracking 513,-9,6,1,-1,0,0,5,1,no,0,0,0,weapon,0,0x0, GS_DISARM,Disarm 514,-9,6,1,-1,0x20,0,5,1,no,0,0,0,weapon,0,0x100, GS_PIERCINGSHOT,Piercing Shot -515,-9,8,1,-1,0,0,10,5,no,0,0,0,weapon,0,0x100, GS_RAPIDSHOWER,Rapid Shower +515,-9,8,1,-1,0,0,10,-5,no,0,0,0,weapon,0,0x100, GS_RAPIDSHOWER,Rapid Shower 516,0,8,4,-1,0x2,3,10,1,no,0,0,0,weapon,0,0x0, GS_DESPERADO,Desperado 517,0,6,4,-1,0x1,0,10,1,no,0,0,0,weapon,0,0x0, GS_GATLINGFEVER,Gatling Fever 518,2,6,1,-1,0,0,10,1,no,0,0,0,weapon,5,0x0, GS_DUST,Dust diff --git a/src/map/battle.c b/src/map/battle.c index 75442cd2d09..9230e194bb4 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -2024,8 +2024,9 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * * Original coder Skoltex * Initial refactoring by Baalberith * Refined and optimized by helvetica + * flag - see e_battle_flag */ -static bool target_has_infinite_defense(struct block_list *target, int skill_id) +static bool is_infinite_defense(struct block_list *target, int flag) { struct status_data *tstatus = status_get_status_data(target); @@ -2035,11 +2036,17 @@ static bool target_has_infinite_defense(struct block_list *target, int skill_id) if (su && su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD)) return true; } - return (tstatus->mode&MD_PLANT && skill_id != RA_CLUSTERBOMB -#ifdef RENEWAL - && skill_id != HT_FREEZINGTRAP && skill_id != HT_CLAYMORETRAP -#endif - ); + + if(tstatus->mode&MD_IGNOREMELEE && (flag&(BF_WEAPON|BF_SHORT)) == (BF_WEAPON|BF_SHORT) ) + return true; + if(tstatus->mode&MD_IGNOREMAGIC && flag&(BF_MAGIC) ) + return true; + if(tstatus->mode&MD_IGNORERANGED && (flag&(BF_WEAPON|BF_LONG)) == (BF_WEAPON|BF_LONG) ) + return true; + if(tstatus->mode&MD_IGNOREMISC && flag&(BF_MISC) ) + return true; + + return (tstatus->mode&MD_PLANT); } /*======================== @@ -3035,9 +3042,29 @@ struct Damage battle_calc_skill_base_damage(struct Damage wd, struct block_list } //For quick div adjustment. -#define DAMAGE_DIV_FIX(dmg, div) { if (div > 1) (dmg)*=div; else if (div < 0) (div)*=-1; } +#define DAMAGE_DIV_FIX(dmg, div) { if (div < 0) { (div)*=-1; (dmg)/=div; } (dmg)*=div; } #define DAMAGE_DIV_FIX2(dmg, div) { if (div > 1) (dmg)*=div; } #define DAMAGE_DIV_FIX_RENEWAL(wd, div) { DAMAGE_DIV_FIX2(wd.statusAtk, div); DAMAGE_DIV_FIX2(wd.weaponAtk, div); DAMAGE_DIV_FIX2(wd.equipAtk, div); DAMAGE_DIV_FIX2(wd.masteryAtk, div); } +/*================================================= + * Applies DAMAGE_DIV_FIX and checks for min damage + *------------------------------------------------- + * Credits: + * Original coder Playtester + */ +static struct Damage battle_apply_div_fix(struct Damage d) +{ + if(d.damage) { + DAMAGE_DIV_FIX(d.damage, d.div_); + //Min damage + if((battle_config.skill_min_damage&d.flag) && d.damage < d.div_) + d.damage = d.div_; + } else if (d.div_ < 0) { + d.div_ *= -1; + } + + return d; +} + /*======================================= * Check for and calculate multi attacks *--------------------------------------- @@ -3235,7 +3262,7 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s skillratio += 30*skill_lv; break; case AS_SONICBLOW: - skillratio += -50+5*skill_lv; + skillratio += 300+40*skill_lv; break; case TF_SPRINKLESAND: skillratio += 30; @@ -3431,7 +3458,7 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s skillratio += 20*skill_lv; break; case GS_RAPIDSHOWER: - skillratio += 10*skill_lv; + skillratio += 400+50*skill_lv; break; case GS_DESPERADO: skillratio += 50*(skill_lv-1); @@ -4492,6 +4519,7 @@ struct Damage battle_calc_attack_post_defense(struct Damage wd, struct block_lis */ struct Damage battle_calc_attack_plant(struct Damage wd, struct block_list *src,struct block_list *target, uint16 skill_id, uint16 skill_lv) { + struct map_session_data *sd = BL_CAST(BL_PC, src); struct status_data *tstatus = status_get_status_data(target); bool attack_hits = is_attack_hitting(wd, src, target, skill_id, skill_lv, false); int right_element = battle_get_weapon_element(wd, src, target, skill_id, skill_lv, EQI_HAND_R, false); @@ -4500,11 +4528,14 @@ struct Damage battle_calc_attack_plant(struct Damage wd, struct block_list *src, //Plants receive 1 damage when hit if( attack_hits || wd.damage > 0 ) - wd.damage = wd.div_; // In some cases, right hand no need to have a weapon to increase damage - if( is_attack_left_handed(src, skill_id) && (attack_hits || wd.damage2 > 0) ) - wd.damage2 = wd.div_; - if (is_attack_right_handed(src, skill_id) && is_attack_left_handed(src, skill_id)) // force left hand to 1 damage while dual wielding [helvetica] - wd.damage2 = 1; + wd.damage = 1; //In some cases, right hand no need to have a weapon to deal a damage + if( is_attack_left_handed(src, skill_id) && (attack_hits || wd.damage2 > 0) ) { + if(sd->status.weapon == W_KATAR) + wd.damage2 = 0; //No backhand damage against plants + else { + wd.damage2 = 1; //Deal 1 HP damage as long as there is a weapon in the left hand + } + } if( attack_hits && class_ == MOBID_EMPERIUM ) { if(target && map_flag_gvg2(target->m) && !battle_can_hit_gvg_target(src,target,skill_id,(skill_id)?BF_SKILL:0)) { @@ -4521,8 +4552,15 @@ struct Damage battle_calc_attack_plant(struct Damage wd, struct block_list *src, return wd; } - //if( !(battle_config.skill_min_damage&1) ) - //Do not return if you are supposed to deal greater damage to plants than 1. [Skotlex] + //For plants we don't continue with the weapon attack code, so we have to apply DAMAGE_DIV_FIX here + wd = battle_apply_div_fix(wd); + + //If there is left hand damage, total damage can never exceed 2, even on multiple hits + if(wd.damage > 1 && wd.damage2 > 0) { + wd.damage = 1; + wd.damage2 = 1; + } + return wd; } @@ -4948,7 +4986,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl // check if we're landing a hit if(!is_attack_hitting(wd, src, target, skill_id, skill_lv, true)) wd.dmg_lv = ATK_FLEE; - else if(!target_has_infinite_defense(target, skill_id)) { //no need for math against plants + else if(!is_infinite_defense(target, wd.flag)) { //no need for math against plants int ratio, i = 0; wd = battle_calc_skill_base_damage(wd, src, target, skill_id, skill_lv); // base skill damage @@ -5010,18 +5048,6 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl wd = battle_calc_attack_post_defense(wd, src, target, skill_id, skill_lv); } - } else if(wd.div_ < 0) //Since the attack missed. - wd.div_ *= -1; - - //WS_CARTTERMINATION never be missed because of flee, deals damage from BS_WEAPONRESEARCH [Cydh] - //NOTE: Idk the official behavior, if this damage can be reflected/adjusted or not - if (sd && skill_id == WS_CARTTERMINATION && wd.dmg_lv == ATK_FLEE && pc_checkskill(sd,BS_WEAPONRESEARCH)) { - wd.dmg_lv = ATK_DEF; - if(target_has_infinite_defense(target, skill_id)) - return battle_calc_attack_plant(wd, src, target, skill_id, skill_lv); - wd.damage = pc_checkskill(sd,BS_WEAPONRESEARCH) * 2; - wd.damage2 = 0; - return wd; } #ifdef RENEWAL @@ -5185,12 +5211,13 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl // perform multihit calculations DAMAGE_DIV_FIX_RENEWAL(wd, wd.div_); #endif - DAMAGE_DIV_FIX(wd.damage, wd.div_); - // only do 1 dmg to plant, no need to calculate rest - if(target_has_infinite_defense(target, skill_id)) + if(is_infinite_defense(target, wd.flag)) return battle_calc_attack_plant(wd, src, target, skill_id, skill_lv); + //Apply DAMAGE_DIV_FIX and check for min damage + wd = battle_apply_div_fix(wd); + wd = battle_calc_attack_left_right_hands(wd, src, target, skill_id, skill_lv); switch (skill_id) { @@ -5308,13 +5335,9 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list //Skill Range Criteria ad.flag |= battle_range_type(src, target, skill_id, skill_lv); - flag.infdef=(tstatus->mode&MD_PLANT?1:0); - if( target->type == BL_SKILL) { - TBL_SKILL *su = (TBL_SKILL*)target; - if( su && su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD) ) - flag.infdef = 1; - } + //Infinite defense (plant mode) + flag.infdef = is_infinite_defense(target, ad.flag)?1:0; switch(skill_id) { @@ -5329,10 +5352,6 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list break; } - if(!flag.infdef && ( - (tstatus->mode&MD_IGNOREMAGIC && ad.flag&(BF_MAGIC) ) //magic - )) flag.infdef = 1; - if (!flag.infdef) //No need to do the math for plants { unsigned int skillratio = 100; //Skill dmg modifiers. @@ -5950,14 +5969,12 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list } #ifndef RENEWAL - ad.damage += battle_calc_cardfix(BF_MAGIC, src, target, nk, s_ele, 0, ad.damage, 0, ad.flag); + ad.damage += battle_calc_cardfix(BF_MAGIC, src, target, nk, s_ele, 0, ad.damage, 0, ad.flag); #endif - } - - DAMAGE_DIV_FIX(ad.damage, ad.div_); + } //Hint: Against plants damage will still be 1 at this point - if (flag.infdef && ad.damage) - ad.damage = ad.damage>0?1:-1; + //Apply DAMAGE_DIV_FIX and check for min damage + ad = battle_apply_div_fix(ad); switch(skill_id) { // These skills will do a GVG fix later #ifdef RENEWAL @@ -6258,8 +6275,6 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_id, skill_get_name(skill_id)); } - DAMAGE_DIV_FIX(md.damage, md.div_); - if (!(nk&NK_IGNORE_FLEE)) { struct status_change *sc = status_get_sc(target); @@ -6309,34 +6324,18 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * if (sd && (i = pc_skillatk_bonus(sd, skill_id))) md.damage += (int64)md.damage*i/100; + if(!(nk&NK_NO_ELEFIX)) + md.damage=battle_attr_fix(src, target, md.damage, s_ele, tstatus->def_ele, tstatus->ele_lv); + + //Plant damage if(md.damage < 0) md.damage = 0; - else if(md.damage && tstatus->mode&MD_PLANT) { - switch(skill_id){ - case NJ_ISSEN: // Final Strike will MISS on "plant"-type mobs [helvetica] - md.damage = 0; - md.dmg_lv = ATK_FLEE; - break; - case HT_LANDMINE: - case MA_LANDMINE: - case HT_BLASTMINE: - case HT_CLAYMORETRAP: - case RA_CLUSTERBOMB: -#ifdef RENEWAL - break; -#endif - default: - md.damage = 1; - } - } else if( target->type == BL_SKILL ) { - TBL_SKILL *su = (TBL_SKILL*)target; - - if( su && su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD) ) - md.damage = 1; + else if(md.damage && is_infinite_defense(target, md.flag)) { + md.damage = 1; } - if(!(nk&NK_NO_ELEFIX)) - md.damage=battle_attr_fix(src, target, md.damage, s_ele, tstatus->def_ele, tstatus->ele_lv); + //Apply DAMAGE_DIV_FIX and check for min damage + md = battle_apply_div_fix(md); md.damage=battle_calc_damage(src,target,&md,md.damage,skill_id,skill_lv); if( map_flag_gvg2(target->m) ) @@ -6370,9 +6369,6 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * md.damage += (int64)md.damage * skill_damage / 100; #endif - if(tstatus->mode&MD_IGNOREMISC && md.flag&(BF_MISC) ) //misc @TODO optimize me - md.damage = md.damage2 = 1; - battle_do_reflect(BF_MISC,&md, src, target, skill_id, skill_lv); //WIP [lighta] return md; diff --git a/src/map/skill.c b/src/map/skill.c index f9b6297209d..7f63af77f0b 100755 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -2832,10 +2832,10 @@ void skill_attack_blow(struct block_list *src, struct block_list *dsrc, struct b * flag&0xFFF is passed to the underlying battle_calc_attack for processing * (usually holds number of targets, or just 1 for simple splash attacks) * - * flag&0x1000 - Return 0 if damage was reflected - * - * Values from enum e_skill_display - * Values from enum e_battle_check_target + * flag&0xF000 - Values from enum e_skill_display + * flag&0x3F0000 - Values from enum e_battle_check_target + * + * flag&0x1000000 - Return 0 if damage was reflected *-------------------------------------------------------------------------*/ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 skill_id, uint16 skill_lv, unsigned int tick, int flag) { @@ -3289,7 +3289,7 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list * map_freeblock_unlock(); - if ((flag&0x1000) && rmdamage == 1) + if ((flag&0x1000000) && rmdamage == 1) return 0; //Should return 0 when damage was reflected return damage; @@ -12876,6 +12876,12 @@ int skill_unit_onplace_timer(struct skill_unit *unit, struct block_list *bl, uns status_change_start(ss, bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),SCSTART_NONE); break; + case UNT_LANDMINE: + //Land Mine only hits single target + skill_attack(skill_get_type(sg->skill_id),ss,&unit->bl,bl,sg->skill_id,sg->skill_lv,tick,0); + sg->unit_id = UNT_USED_TRAPS; //Changed ID so it does not invoke a for each in area again. + sg->limit = 1500; + break; case UNT_MAGENTATRAP: case UNT_COBALTTRAP: case UNT_MAIZETRAP: @@ -12887,7 +12893,6 @@ int skill_unit_onplace_timer(struct skill_unit *unit, struct block_list *bl, uns case UNT_CLUSTERBOMB: if( bl->id == ss->id )// it won't trigger on caster break; - case UNT_LANDMINE: case UNT_BLASTMINE: case UNT_SHOCKWAVE: case UNT_SANDMAN: diff --git a/src/map/status.c b/src/map/status.c index b3700835804..6380d63886a 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -499,7 +499,7 @@ void initChangeTables(void) add_sc( NPC_MAGICMIRROR , SC_MAGICMIRROR ); set_sc( NPC_SLOWCAST , SC_SLOWCAST , SI_SLOWCAST , SCB_NONE ); set_sc( NPC_CRITICALWOUND , SC_CRITICALWOUND , SI_CRITICALWOUND , SCB_NONE ); - set_sc( NPC_STONESKIN , SC_ARMORCHANGE , SI_BLANK , SCB_DEF|SCB_MDEF ); + set_sc( NPC_STONESKIN , SC_ARMORCHANGE , SI_BLANK , SCB_NONE ); add_sc( NPC_ANTIMAGIC , SC_ARMORCHANGE ); add_sc( NPC_WIDECURSE , SC_CURSE ); add_sc( NPC_WIDESTUN , SC_STUN ); @@ -12208,12 +12208,14 @@ int status_change_timer_sub(struct block_list* bl, va_list ap) status_check_skilluse(src, bl, WZ_SIGHTBLASTER, 2)) { struct skill_unit *su = (struct skill_unit *)bl; - if (sce && skill_attack(BF_MAGIC,src,src,bl,WZ_SIGHTBLASTER,sce->val1,tick,0x1000) - && (!su || !su->group || !(skill_get_inf2(su->group->skill_id)&INF2_TRAP))) { // The hit is not counted if it's against a trap - sce->val2 = 0; // This signals it to end. - } else if((bl->type&BL_SKILL) && sce->val4%2 == 0) { - //Remove trap immunity temporarily so it triggers if you still stand on it - sce->val4++; + if (sce) { + if (skill_attack(BF_MAGIC,src,src,bl,WZ_SIGHTBLASTER,sce->val1,tick,0x1000000) + && (!su || !su->group || !(skill_get_inf2(su->group->skill_id)&INF2_TRAP))) { // The hit is not counted if it's against a trap + sce->val2 = 0; // This signals it to end. + } else if((bl->type&BL_SKILL) && sce->val4%2 == 0) { + //Remove trap immunity temporarily so it triggers if you still stand on it + sce->val4++; + } } } break; diff --git a/src/map/status.h b/src/map/status.h index 7e2fcc916f5..9f174633041 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -1557,9 +1557,9 @@ enum e_mode { MD_CHANGETARGET_CHASE = 0x002000, MD_TARGETWEAK = 0x004000, MD_RANDOMTARGET = 0x008000, - MD_IGNOREMELEE = 0x010000, //! TODO: Unused yet + MD_IGNOREMELEE = 0x010000, MD_IGNOREMAGIC = 0x020000, - MD_IGNORERANGED = 0x040000, //! TODO: Unused yet + MD_IGNORERANGED = 0x040000, MD_MVP = 0x080000, MD_IGNOREMISC = 0x100000, MD_KNOCKBACK_IMMUNE = 0x200000, diff --git a/src/map/unit.c b/src/map/unit.c index 0984dacde62..fdd0bf99529 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -586,7 +586,7 @@ int unit_delay_walktobl_timer(int tid, unsigned int tick, int id, intptr_t data) * &1: Easy walk (fail if CELL_CHKNOPASS is in direct path) * &2: Force walking (override can_move) * &4: Delay walking for can_move - * &8: Search for an unoccupied cell and cancel if none available + * &8: Search for an unoccupied cell and cancel if none available * @return 1: Success 0: Fail or unit_walktoxy_sub() */ int unit_walktoxy( struct block_list *bl, short x, short y, unsigned char flag)