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
This commit is contained in:
parent
c10c05ab61
commit
04a1173f7d
@ -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
|
// 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.
|
// characters on it, it will walk to the closest free cell.
|
||||||
// Custom - This variation will make every full cell to be considered a wall.
|
// 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)
|
// with Cell Stack Limit support (see src/map/map.h)
|
||||||
official_cell_stack_limit: 1
|
official_cell_stack_limit: 1
|
||||||
custom_cell_stack_limit: 1
|
custom_cell_stack_limit: 1
|
||||||
|
@ -89,10 +89,14 @@ clear_skills_on_warp: 15
|
|||||||
//See db/skill_unit_db.txt for more info.
|
//See db/skill_unit_db.txt for more info.
|
||||||
defunit_not_enemy: no
|
defunit_not_enemy: no
|
||||||
|
|
||||||
// Do skills do at least 'hits' damage when they don't miss/are blocked?
|
// Should skills always do at least 'hits' damage when they don't miss/are blocked?
|
||||||
//(for example, will firebolts always do "number of bolts" damage versus plants?)
|
// Many skills will have their damage multiplied by their number of hits (see skill_db), these will always deal 1 HP
|
||||||
//Values (add as appropriate): 1 for weapon-based attacks, 2 for magic attacks, 4 for misc attacks.
|
// damage per hit, even against plants. But some skills are actually a single hit that is just displayed as multiple
|
||||||
skill_min_damage: 6
|
// 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)
|
// The delay rate of monk's combo (Note 2)
|
||||||
combo_delay_rate: 100
|
combo_delay_rate: 100
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
//
|
//
|
||||||
// CastingTime: time to cast this skill, in milliseconds
|
// CastingTime: time to cast this skill, in milliseconds
|
||||||
// AfterCastActDelay: "normal" delay, character cannot use skills, 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
|
// 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
|
// Cool Down: amount of time until character can re-use this skill, in milliseconds
|
||||||
//
|
//
|
||||||
|
@ -214,7 +214,7 @@
|
|||||||
//****
|
//****
|
||||||
// Hunter
|
// 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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
518,2,6,1,-1,0,0,10,1,no,0,0,0,weapon,5,0x0, GS_DUST,Dust
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
//
|
//
|
||||||
// CastingTime: time to cast this skill, in milliseconds
|
// CastingTime: time to cast this skill, in milliseconds
|
||||||
// AfterCastActDelay: "normal" delay, character cannot use skills, 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
|
// 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
|
// 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)
|
// Fixed Casting Time: the skills fixed casting time (when 0, uses 20% of cast time and less than 0 means no fixed cast time)
|
||||||
|
@ -214,7 +214,7 @@
|
|||||||
//****
|
//****
|
||||||
// Hunter
|
// 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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
518,2,6,1,-1,0,0,10,1,no,0,0,0,weapon,5,0x0, GS_DUST,Dust
|
||||||
|
152
src/map/battle.c
152
src/map/battle.c
@ -2024,8 +2024,9 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
|
|||||||
* Original coder Skoltex
|
* Original coder Skoltex
|
||||||
* Initial refactoring by Baalberith
|
* Initial refactoring by Baalberith
|
||||||
* Refined and optimized by helvetica
|
* 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);
|
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))
|
if (su && su->group && (su->group->skill_id == WM_REVERBERATION || su->group->skill_id == WM_POEMOFNETHERWORLD))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return (tstatus->mode&MD_PLANT && skill_id != RA_CLUSTERBOMB
|
|
||||||
#ifdef RENEWAL
|
if(tstatus->mode&MD_IGNOREMELEE && (flag&(BF_WEAPON|BF_SHORT)) == (BF_WEAPON|BF_SHORT) )
|
||||||
&& skill_id != HT_FREEZINGTRAP && skill_id != HT_CLAYMORETRAP
|
return true;
|
||||||
#endif
|
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.
|
//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_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); }
|
#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
|
* 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;
|
skillratio += 30*skill_lv;
|
||||||
break;
|
break;
|
||||||
case AS_SONICBLOW:
|
case AS_SONICBLOW:
|
||||||
skillratio += -50+5*skill_lv;
|
skillratio += 300+40*skill_lv;
|
||||||
break;
|
break;
|
||||||
case TF_SPRINKLESAND:
|
case TF_SPRINKLESAND:
|
||||||
skillratio += 30;
|
skillratio += 30;
|
||||||
@ -3431,7 +3458,7 @@ static int battle_calc_attack_skill_ratio(struct Damage wd, struct block_list *s
|
|||||||
skillratio += 20*skill_lv;
|
skillratio += 20*skill_lv;
|
||||||
break;
|
break;
|
||||||
case GS_RAPIDSHOWER:
|
case GS_RAPIDSHOWER:
|
||||||
skillratio += 10*skill_lv;
|
skillratio += 400+50*skill_lv;
|
||||||
break;
|
break;
|
||||||
case GS_DESPERADO:
|
case GS_DESPERADO:
|
||||||
skillratio += 50*(skill_lv-1);
|
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 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);
|
struct status_data *tstatus = status_get_status_data(target);
|
||||||
bool attack_hits = is_attack_hitting(wd, src, target, skill_id, skill_lv, false);
|
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);
|
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
|
//Plants receive 1 damage when hit
|
||||||
if( attack_hits || wd.damage > 0 )
|
if( attack_hits || wd.damage > 0 )
|
||||||
wd.damage = wd.div_; // In some cases, right hand no need to have a weapon to increase damage
|
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( is_attack_left_handed(src, skill_id) && (attack_hits || wd.damage2 > 0) ) {
|
||||||
wd.damage2 = wd.div_;
|
if(sd->status.weapon == W_KATAR)
|
||||||
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 = 0; //No backhand damage against plants
|
||||||
wd.damage2 = 1;
|
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( 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)) {
|
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;
|
return wd;
|
||||||
}
|
}
|
||||||
|
|
||||||
//if( !(battle_config.skill_min_damage&1) )
|
//For plants we don't continue with the weapon attack code, so we have to apply DAMAGE_DIV_FIX here
|
||||||
//Do not return if you are supposed to deal greater damage to plants than 1. [Skotlex]
|
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;
|
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
|
// check if we're landing a hit
|
||||||
if(!is_attack_hitting(wd, src, target, skill_id, skill_lv, true))
|
if(!is_attack_hitting(wd, src, target, skill_id, skill_lv, true))
|
||||||
wd.dmg_lv = ATK_FLEE;
|
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;
|
int ratio, i = 0;
|
||||||
|
|
||||||
wd = battle_calc_skill_base_damage(wd, src, target, skill_id, skill_lv); // base skill damage
|
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);
|
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
|
#ifdef RENEWAL
|
||||||
@ -5185,12 +5211,13 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src, struct bl
|
|||||||
// perform multihit calculations
|
// perform multihit calculations
|
||||||
DAMAGE_DIV_FIX_RENEWAL(wd, wd.div_);
|
DAMAGE_DIV_FIX_RENEWAL(wd, wd.div_);
|
||||||
#endif
|
#endif
|
||||||
DAMAGE_DIV_FIX(wd.damage, wd.div_);
|
|
||||||
|
|
||||||
// only do 1 dmg to plant, no need to calculate rest
|
// 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);
|
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);
|
wd = battle_calc_attack_left_right_hands(wd, src, target, skill_id, skill_lv);
|
||||||
|
|
||||||
switch (skill_id) {
|
switch (skill_id) {
|
||||||
@ -5308,13 +5335,9 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
|
|||||||
|
|
||||||
//Skill Range Criteria
|
//Skill Range Criteria
|
||||||
ad.flag |= battle_range_type(src, target, skill_id, skill_lv);
|
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) )
|
//Infinite defense (plant mode)
|
||||||
flag.infdef = 1;
|
flag.infdef = is_infinite_defense(target, ad.flag)?1:0;
|
||||||
}
|
|
||||||
|
|
||||||
switch(skill_id)
|
switch(skill_id)
|
||||||
{
|
{
|
||||||
@ -5329,10 +5352,6 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
|
|||||||
break;
|
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
|
if (!flag.infdef) //No need to do the math for plants
|
||||||
{
|
{
|
||||||
unsigned int skillratio = 100; //Skill dmg modifiers.
|
unsigned int skillratio = 100; //Skill dmg modifiers.
|
||||||
@ -5952,12 +5971,10 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
|
|||||||
#ifndef RENEWAL
|
#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
|
#endif
|
||||||
}
|
} //Hint: Against plants damage will still be 1 at this point
|
||||||
|
|
||||||
DAMAGE_DIV_FIX(ad.damage, ad.div_);
|
//Apply DAMAGE_DIV_FIX and check for min damage
|
||||||
|
ad = battle_apply_div_fix(ad);
|
||||||
if (flag.infdef && ad.damage)
|
|
||||||
ad.damage = ad.damage>0?1:-1;
|
|
||||||
|
|
||||||
switch(skill_id) { // These skills will do a GVG fix later
|
switch(skill_id) { // These skills will do a GVG fix later
|
||||||
#ifdef RENEWAL
|
#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));
|
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))
|
if (!(nk&NK_IGNORE_FLEE))
|
||||||
{
|
{
|
||||||
struct status_change *sc = status_get_sc(target);
|
struct status_change *sc = status_get_sc(target);
|
||||||
@ -6309,35 +6324,19 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
|
|||||||
if (sd && (i = pc_skillatk_bonus(sd, skill_id)))
|
if (sd && (i = pc_skillatk_bonus(sd, skill_id)))
|
||||||
md.damage += (int64)md.damage*i/100;
|
md.damage += (int64)md.damage*i/100;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!(nk&NK_NO_ELEFIX))
|
if(!(nk&NK_NO_ELEFIX))
|
||||||
md.damage=battle_attr_fix(src, target, md.damage, s_ele, tstatus->def_ele, tstatus->ele_lv);
|
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 && is_infinite_defense(target, md.flag)) {
|
||||||
|
md.damage = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//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);
|
md.damage=battle_calc_damage(src,target,&md,md.damage,skill_id,skill_lv);
|
||||||
if( map_flag_gvg2(target->m) )
|
if( map_flag_gvg2(target->m) )
|
||||||
md.damage=battle_calc_gvg_damage(src,target,md.damage,skill_id,md.flag);
|
md.damage=battle_calc_gvg_damage(src,target,md.damage,skill_id,md.flag);
|
||||||
@ -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;
|
md.damage += (int64)md.damage * skill_damage / 100;
|
||||||
#endif
|
#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]
|
battle_do_reflect(BF_MISC,&md, src, target, skill_id, skill_lv); //WIP [lighta]
|
||||||
|
|
||||||
return md;
|
return md;
|
||||||
|
@ -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
|
* flag&0xFFF is passed to the underlying battle_calc_attack for processing
|
||||||
* (usually holds number of targets, or just 1 for simple splash attacks)
|
* (usually holds number of targets, or just 1 for simple splash attacks)
|
||||||
*
|
*
|
||||||
* flag&0x1000 - Return 0 if damage was reflected
|
* flag&0xF000 - Values from enum e_skill_display
|
||||||
|
* flag&0x3F0000 - Values from enum e_battle_check_target
|
||||||
*
|
*
|
||||||
* Values from enum e_skill_display
|
* flag&0x1000000 - Return 0 if damage was reflected
|
||||||
* Values from enum e_battle_check_target
|
|
||||||
*-------------------------------------------------------------------------*/
|
*-------------------------------------------------------------------------*/
|
||||||
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)
|
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();
|
map_freeblock_unlock();
|
||||||
|
|
||||||
if ((flag&0x1000) && rmdamage == 1)
|
if ((flag&0x1000000) && rmdamage == 1)
|
||||||
return 0; //Should return 0 when damage was reflected
|
return 0; //Should return 0 when damage was reflected
|
||||||
|
|
||||||
return damage;
|
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);
|
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;
|
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_MAGENTATRAP:
|
||||||
case UNT_COBALTTRAP:
|
case UNT_COBALTTRAP:
|
||||||
case UNT_MAIZETRAP:
|
case UNT_MAIZETRAP:
|
||||||
@ -12887,7 +12893,6 @@ int skill_unit_onplace_timer(struct skill_unit *unit, struct block_list *bl, uns
|
|||||||
case UNT_CLUSTERBOMB:
|
case UNT_CLUSTERBOMB:
|
||||||
if( bl->id == ss->id )// it won't trigger on caster
|
if( bl->id == ss->id )// it won't trigger on caster
|
||||||
break;
|
break;
|
||||||
case UNT_LANDMINE:
|
|
||||||
case UNT_BLASTMINE:
|
case UNT_BLASTMINE:
|
||||||
case UNT_SHOCKWAVE:
|
case UNT_SHOCKWAVE:
|
||||||
case UNT_SANDMAN:
|
case UNT_SANDMAN:
|
||||||
|
@ -499,7 +499,7 @@ void initChangeTables(void)
|
|||||||
add_sc( NPC_MAGICMIRROR , SC_MAGICMIRROR );
|
add_sc( NPC_MAGICMIRROR , SC_MAGICMIRROR );
|
||||||
set_sc( NPC_SLOWCAST , SC_SLOWCAST , SI_SLOWCAST , SCB_NONE );
|
set_sc( NPC_SLOWCAST , SC_SLOWCAST , SI_SLOWCAST , SCB_NONE );
|
||||||
set_sc( NPC_CRITICALWOUND , SC_CRITICALWOUND , SI_CRITICALWOUND , 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_ANTIMAGIC , SC_ARMORCHANGE );
|
||||||
add_sc( NPC_WIDECURSE , SC_CURSE );
|
add_sc( NPC_WIDECURSE , SC_CURSE );
|
||||||
add_sc( NPC_WIDESTUN , SC_STUN );
|
add_sc( NPC_WIDESTUN , SC_STUN );
|
||||||
@ -12208,7 +12208,8 @@ int status_change_timer_sub(struct block_list* bl, va_list ap)
|
|||||||
status_check_skilluse(src, bl, WZ_SIGHTBLASTER, 2))
|
status_check_skilluse(src, bl, WZ_SIGHTBLASTER, 2))
|
||||||
{
|
{
|
||||||
struct skill_unit *su = (struct skill_unit *)bl;
|
struct skill_unit *su = (struct skill_unit *)bl;
|
||||||
if (sce && skill_attack(BF_MAGIC,src,src,bl,WZ_SIGHTBLASTER,sce->val1,tick,0x1000)
|
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
|
&& (!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.
|
sce->val2 = 0; // This signals it to end.
|
||||||
} else if((bl->type&BL_SKILL) && sce->val4%2 == 0) {
|
} else if((bl->type&BL_SKILL) && sce->val4%2 == 0) {
|
||||||
@ -12216,6 +12217,7 @@ int status_change_timer_sub(struct block_list* bl, va_list ap)
|
|||||||
sce->val4++;
|
sce->val4++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SC_TINDER_BREAKER:
|
case SC_TINDER_BREAKER:
|
||||||
case SC_CLOSECONFINE:{
|
case SC_CLOSECONFINE:{
|
||||||
|
@ -1557,9 +1557,9 @@ enum e_mode {
|
|||||||
MD_CHANGETARGET_CHASE = 0x002000,
|
MD_CHANGETARGET_CHASE = 0x002000,
|
||||||
MD_TARGETWEAK = 0x004000,
|
MD_TARGETWEAK = 0x004000,
|
||||||
MD_RANDOMTARGET = 0x008000,
|
MD_RANDOMTARGET = 0x008000,
|
||||||
MD_IGNOREMELEE = 0x010000, //! TODO: Unused yet
|
MD_IGNOREMELEE = 0x010000,
|
||||||
MD_IGNOREMAGIC = 0x020000,
|
MD_IGNOREMAGIC = 0x020000,
|
||||||
MD_IGNORERANGED = 0x040000, //! TODO: Unused yet
|
MD_IGNORERANGED = 0x040000,
|
||||||
MD_MVP = 0x080000,
|
MD_MVP = 0x080000,
|
||||||
MD_IGNOREMISC = 0x100000,
|
MD_IGNOREMISC = 0x100000,
|
||||||
MD_KNOCKBACK_IMMUNE = 0x200000,
|
MD_KNOCKBACK_IMMUNE = 0x200000,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user