Coma Rework, Exp Calc Type, Fiber Lock Range (#8287)
- Coma item bonus is no longer an additional effect / status change, but instead replaces the attack damage with setting HP/SP to 1 * That means Coma attacks will never kill someone, even if the original attack would be lethal * When doing a Coma attack, the attack displays the original damage and this is also what counts towards the mob damage log - Coma is checked for every single event that applies damage, including reflect damage, and for Provoke / Self Provoke * Some Renewal-only effects couldn't be tested and were left unchanged (e.g. damage from White Imprison) - Coma now sets SP to 1 instead of 0 - bComaRace, bWeaponComaRace and bWeaponComaEle won't work on bosses, GVG and battlefield objects - bComaClass and bWeaponComaClass no longer work on GVG and battlefield objects, but can work on bosses if you specify Class_Boss or Class_All - Edge is now defined to only work on normal monster - The default exp_calc_type 0 no longer counts the first attacker twice and instead works like on official servers - Added a new exp_calc_type 2 that counts the first attacker twice as previously - The damage logged will now include overkill damage on exp_calc_type 0 and 2, but not count Coma damage (it will count the damage you would have originally dealt instead) - Fiber Lock now has a range of 9 instead of 7 - Fixes #8279
This commit is contained in:
parent
9e959f7fd6
commit
cad5cab976
@ -33,8 +33,7 @@ max_exp_gain_rate: 0
|
||||
// Method of calculating earned experience when defeating a monster:
|
||||
// 0 = uses damage given / total damage as damage ratio
|
||||
// 1 = uses damage given / max_hp as damage ratio
|
||||
// NOTE: Using type 1 disables the bonus where the first attacker gets
|
||||
// his share of the exp doubled when multiple people attack the mob.
|
||||
// 2 = 0 + first attacker counts twice
|
||||
exp_calc_type: 0
|
||||
|
||||
// Experience increase per attacker. That is, every additional attacker to the
|
||||
|
@ -11062,7 +11062,7 @@ Body:
|
||||
TargetType: Attack
|
||||
DamageFlags:
|
||||
NoDamage: true
|
||||
Range: 7
|
||||
Range: 9
|
||||
Hit: Single
|
||||
HitCount: 1
|
||||
ActiveInstance: 3
|
||||
|
@ -948,7 +948,7 @@ Body:
|
||||
Refineable: true
|
||||
Script: |
|
||||
bonus2 bAddEff,Eff_Curse,30;
|
||||
bonus2 bComaClass,Class_All,10;
|
||||
bonus2 bComaClass,Class_Normal,10;
|
||||
- Id: 1133
|
||||
AegisName: Fire_Brand
|
||||
Name: Fireblend
|
||||
|
@ -11312,7 +11312,7 @@ Body:
|
||||
TargetType: Attack
|
||||
DamageFlags:
|
||||
NoDamage: true
|
||||
Range: 7
|
||||
Range: 9
|
||||
Hit: Single
|
||||
HitCount: 1
|
||||
ActiveInstance: 3
|
||||
|
@ -34,6 +34,8 @@
|
||||
#include "pc_groups.hpp"
|
||||
#include "pet.hpp"
|
||||
|
||||
using namespace rathena;
|
||||
|
||||
struct Battle_Config battle_config;
|
||||
static struct eri *delay_damage_ers; //For battle delay damage structures.
|
||||
|
||||
@ -254,33 +256,42 @@ struct block_list* battle_getenemyarea(struct block_list *src, int x, int y, int
|
||||
return bl_list[rnd()%c];
|
||||
}
|
||||
|
||||
/*========================================== [Playtester]
|
||||
/**
|
||||
* Deals damage without delay, applies additional effects and triggers monster events
|
||||
* This function is called from battle_delay_damage or battle_delay_damage_sub
|
||||
* All other instances of battle damage should also go through this function (i.e. anything that displays a damage number)
|
||||
* Consider calling this function or battle_fix_damage instead status_fix_damage directly
|
||||
* @param src: Source of damage
|
||||
* @param target: Target of damage
|
||||
* @param damage: Damage to be dealt
|
||||
* @param delay: Damage delay
|
||||
* @param skill_lv: Level of skill used
|
||||
* @param skill_id: ID o skill used
|
||||
* @param skill_id: ID of skill used
|
||||
* @param dmg_lv: State of the attack (miss, etc.)
|
||||
* @param attack_type: Type of the attack (BF_NORMAL|BF_SKILL|BF_SHORT|BF_LONG|BF_WEAPON|BF_MAGIC|BF_MISC)
|
||||
* @param additional_effects: Whether additional effect should be applied
|
||||
* @param additional_effects: Whether additional effects should be applied (otherwise it's just damage+coma)
|
||||
* @param isspdamage: If the damage is done to SP
|
||||
* @param tick: Current tick
|
||||
*------------------------------------------*/
|
||||
void battle_damage(struct block_list *src, struct block_list *target, int64 damage, t_tick delay, uint16 skill_lv, uint16 skill_id, enum damage_lv dmg_lv, unsigned short attack_type, bool additional_effects, t_tick tick, bool isspdamage) {
|
||||
* @return HP+SP+AP (0 if HP/SP/AP remained unchanged)
|
||||
*/
|
||||
int battle_damage(struct block_list *src, struct block_list *target, int64 damage, t_tick delay, uint16 skill_lv, uint16 skill_id, enum damage_lv dmg_lv, unsigned short attack_type, bool additional_effects, t_tick tick, bool isspdamage) {
|
||||
int dmg_change;
|
||||
map_session_data* sd = nullptr;
|
||||
if (src)
|
||||
sd = BL_CAST(BL_PC, src);
|
||||
map_freeblock_lock();
|
||||
if (isspdamage)
|
||||
status_fix_spdamage(src, target, damage, delay, skill_id);
|
||||
dmg_change = status_fix_spdamage(src, target, damage, delay, skill_id);
|
||||
else if (sd && battle_check_coma(*sd, *target, (e_battle_flag)attack_type))
|
||||
dmg_change = status_damage(src, target, damage, 0, delay, 16, skill_id); // Coma attack
|
||||
else
|
||||
status_fix_damage(src, target, damage, delay, skill_id); // We have to separate here between reflect damage and others [icescope]
|
||||
dmg_change = status_fix_damage(src, target, damage, delay, skill_id);
|
||||
if (attack_type && !status_isdead(target) && additional_effects)
|
||||
skill_additional_effect(src, target, skill_id, skill_lv, attack_type, dmg_lv, tick);
|
||||
if (dmg_lv > ATK_BLOCK && attack_type)
|
||||
if (dmg_lv > ATK_BLOCK && attack_type && additional_effects)
|
||||
skill_counter_additional_effect(src, target, skill_id, skill_lv, attack_type, tick);
|
||||
// This is the last place where we have access to the actual damage type, so any monster events depending on type must be placed here
|
||||
if (target->type == BL_MOB) {
|
||||
if (target->type == BL_MOB && additional_effects) {
|
||||
mob_data *md = BL_CAST(BL_MOB, target);
|
||||
|
||||
if (md != nullptr) {
|
||||
@ -298,6 +309,7 @@ void battle_damage(struct block_list *src, struct block_list *target, int64 dama
|
||||
}
|
||||
}
|
||||
map_freeblock_unlock();
|
||||
return dmg_change;
|
||||
}
|
||||
|
||||
/// Damage Delayed Structure
|
||||
@ -331,9 +343,7 @@ TIMER_FUNC(battle_delay_damage_sub){
|
||||
//Deal damage
|
||||
battle_damage(src, target, dat->damage, dat->delay, dat->skill_lv, dat->skill_id, dat->dmg_lv, dat->attack_type, dat->additional_effects, tick, dat->isspdamage);
|
||||
} else if( !src && dat->skill_id == CR_REFLECTSHIELD ) { // it was monster reflected damage, and the monster died, we pass the damage to the character as expected
|
||||
map_freeblock_lock();
|
||||
status_fix_damage(target, target, dat->damage, dat->delay, dat->skill_id);
|
||||
map_freeblock_unlock();
|
||||
battle_fix_damage(target, target, dat->damage, dat->delay, dat->skill_id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6956,7 +6966,7 @@ static void battle_calc_weapon_final_atk_modifiers(struct Damage* wd, struct blo
|
||||
{
|
||||
ATK_RATER(wd->damage, 50)
|
||||
clif_skill_nodamage(target,target,ST_REJECTSWORD, tsc->getSCE(SC_REJECTSWORD)->val1,1);
|
||||
status_fix_damage(target,src,wd->damage,clif_damage(target,src,gettick(),0,0,wd->damage,0,DMG_NORMAL,0,false),ST_REJECTSWORD);
|
||||
battle_fix_damage(target,src,wd->damage,clif_damage(target,src,gettick(),0,0,wd->damage,0,DMG_NORMAL,0,false),ST_REJECTSWORD);
|
||||
if (status_isdead(target))
|
||||
return;
|
||||
if( --(tsc->getSCE(SC_REJECTSWORD)->val3) <= 0 )
|
||||
@ -6974,7 +6984,7 @@ static void battle_calc_weapon_final_atk_modifiers(struct Damage* wd, struct blo
|
||||
clif_skill_damage(target, src, gettick(), status_get_amotion(src), 0, rdamage,
|
||||
1, SR_CRESCENTELBOW_AUTOSPELL, tsc->getSCE(SC_CRESCENTELBOW)->val1, DMG_SINGLE); // This is how official does
|
||||
clif_damage(src, target, gettick(), status_get_amotion(src)+1000, 0, rdamage/10, 1, DMG_NORMAL, 0, false);
|
||||
status_damage(target, src, rdamage, 0, 0, 0, 0);
|
||||
battle_fix_damage(target, src, rdamage, 0, SR_CRESCENTELBOW);
|
||||
status_damage(src, target, rdamage/10, 0, 0, 1, 0);
|
||||
status_change_end(target, SC_CRESCENTELBOW);
|
||||
}
|
||||
@ -9515,6 +9525,36 @@ int64 battle_calc_return_damage(struct block_list* tbl, struct block_list *src,
|
||||
return cap_value(rdamage, 1, status_get_max_hp(tbl));
|
||||
}
|
||||
|
||||
/** Check for Coma damage
|
||||
* @param sd: Source player
|
||||
* @param bl: Target
|
||||
* @param attack_type: Attack type
|
||||
* @return True if Coma applies, false if Coma does not apply
|
||||
*/
|
||||
bool battle_check_coma(map_session_data& sd, struct block_list& target, e_battle_flag attack_type)
|
||||
{
|
||||
struct status_data* tstatus = status_get_status_data(&target);
|
||||
mob_data* dstmd = BL_CAST(BL_MOB, &target);
|
||||
|
||||
// Coma
|
||||
if (sd.special_state.bonus_coma && (!dstmd || (!util::vector_exists(status_get_race2(&dstmd->bl), RC2_GVG) && status_get_class(&dstmd->bl) != CLASS_BATTLEFIELD))) {
|
||||
int rate = 0;
|
||||
rate += sd.indexed_bonus.coma_class[tstatus->class_] + sd.indexed_bonus.coma_class[CLASS_ALL];
|
||||
if(!status_bl_has_mode(&target, MD_STATUSIMMUNE))
|
||||
rate += sd.indexed_bonus.coma_race[tstatus->race] + sd.indexed_bonus.coma_race[RC_ALL];
|
||||
if (attack_type&BF_WEAPON) {
|
||||
rate += sd.indexed_bonus.weapon_coma_class[tstatus->class_] + sd.indexed_bonus.weapon_coma_class[CLASS_ALL];
|
||||
if (!status_bl_has_mode(&target, MD_STATUSIMMUNE)) {
|
||||
rate += sd.indexed_bonus.weapon_coma_ele[tstatus->def_ele] + sd.indexed_bonus.weapon_coma_ele[ELE_ALL];
|
||||
rate += sd.indexed_bonus.weapon_coma_race[tstatus->race] + sd.indexed_bonus.weapon_coma_race[RC_ALL];
|
||||
}
|
||||
}
|
||||
if (rate > 0 && rnd_chance(rate, 10000))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate Vellum damage on a target
|
||||
* @param sd: Player with vanish item
|
||||
@ -9649,7 +9689,7 @@ int battle_damage_area(struct block_list *bl, va_list ap) {
|
||||
if( amotion )
|
||||
battle_delay_damage(tick, amotion,src,bl,0,CR_REFLECTSHIELD,0,damage,ATK_DEF,0,true,false);
|
||||
else
|
||||
status_fix_damage(src,bl,damage,0,LG_REFLECTDAMAGE);
|
||||
battle_fix_damage(src,bl,damage,0,LG_REFLECTDAMAGE);
|
||||
clif_damage(bl,bl,tick,amotion,dmotion,damage,1,DMG_ENDURE,0,false);
|
||||
skill_additional_effect(src, bl, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick);
|
||||
map_freeblock_unlock();
|
||||
@ -10016,7 +10056,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
|
||||
devotion_damage -= devotion_damage * d_sc->getSCE(SC_REBOUND_S)->val2 / 100;
|
||||
|
||||
clif_damage(d_bl, d_bl, gettick(), wd.amotion, wd.dmotion, devotion_damage, 1, DMG_NORMAL, 0, false);
|
||||
status_fix_damage(NULL, d_bl, devotion_damage, 0, CR_DEVOTION);
|
||||
battle_fix_damage(src, d_bl, devotion_damage, 0, CR_DEVOTION);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -10035,7 +10075,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
|
||||
|
||||
if (e_bl && !status_isdead(e_bl)) {
|
||||
clif_damage(e_bl, e_bl, tick, 0, 0, damage, wd.div_, DMG_NORMAL, 0, false);
|
||||
status_fix_damage(NULL, e_bl, damage, 0, EL_WATER_SCREEN);
|
||||
battle_fix_damage(src, e_bl, damage, 0, EL_WATER_SCREEN);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -11103,7 +11143,7 @@ static const struct _battle_data {
|
||||
{ "skill_steal_random_options", &battle_config.skill_steal_random_options, 0, 0, 1, },
|
||||
{ "motd_type", &battle_config.motd_type, 0, 0, 1, },
|
||||
{ "finding_ore_rate", &battle_config.finding_ore_rate, 100, 0, INT_MAX, },
|
||||
{ "exp_calc_type", &battle_config.exp_calc_type, 0, 0, 1, },
|
||||
{ "exp_calc_type", &battle_config.exp_calc_type, 0, 0, 2, },
|
||||
{ "exp_bonus_attacker", &battle_config.exp_bonus_attacker, 25, 0, INT_MAX, },
|
||||
{ "exp_bonus_max_attacker", &battle_config.exp_bonus_max_attacker, 12, 2, INT_MAX, },
|
||||
{ "min_skill_delay_limit", &battle_config.min_skill_delay_limit, 100, 10, INT_MAX, },
|
||||
|
@ -122,8 +122,11 @@ int64 battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int64
|
||||
int64 battle_calc_bg_damage(struct block_list *src,struct block_list *bl,int64 damage,uint16 skill_id,int flag);
|
||||
int64 battle_calc_pk_damage(block_list &src, block_list &bl, int64 damage, uint16 skill_id, int flag);
|
||||
|
||||
void battle_damage(struct block_list *src, struct block_list *target, int64 damage, t_tick delay, uint16 skill_lv, uint16 skill_id, enum damage_lv dmg_lv, unsigned short attack_type, bool additional_effects, t_tick tick, bool spdamage);
|
||||
int battle_damage(struct block_list *src, struct block_list *target, int64 damage, t_tick delay, uint16 skill_lv, uint16 skill_id, enum damage_lv dmg_lv, unsigned short attack_type, bool additional_effects, t_tick tick, bool spdamage);
|
||||
int battle_delay_damage (t_tick tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, uint16 skill_id, uint16 skill_lv, int64 damage, enum damage_lv dmg_lv, t_tick ddelay, bool additional_effects, bool spdamage);
|
||||
static int battle_fix_damage(struct block_list* src, struct block_list* target, int64 damage, t_tick walkdelay, uint16 skill_id) {
|
||||
return battle_damage(src, target, damage, walkdelay, 0, skill_id, ATK_DEF, BF_MISC, false, gettick(), false);
|
||||
}
|
||||
|
||||
int battle_calc_chorusbonus(map_session_data *sd);
|
||||
|
||||
@ -140,6 +143,7 @@ uint16 battle_getcurrentskill(struct block_list *bl);
|
||||
int battle_check_undead(int race,int element);
|
||||
int battle_check_target(struct block_list *src, struct block_list *target,int flag);
|
||||
bool battle_check_range(struct block_list *src,struct block_list *bl,int range);
|
||||
bool battle_check_coma(map_session_data& sd, struct block_list& target, e_battle_flag attack_type);
|
||||
|
||||
void battle_consume_ammo(map_session_data* sd, int skill, int lv);
|
||||
|
||||
|
@ -2631,8 +2631,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
|
||||
// determines if the monster was killed by mercenary damage only
|
||||
merckillonly = (bool)((dmgbltypes & BL_MER) && !(dmgbltypes & ~BL_MER));
|
||||
|
||||
if(!battle_config.exp_calc_type && count > 1) { //Apply first-attacker 200% exp share bonus
|
||||
//TODO: Determine if this should go before calculating the MVP player instead of after.
|
||||
if(battle_config.exp_calc_type == 2 && count > 1) { //Apply first-attacker 200% exp share bonus
|
||||
if (UINT_MAX - md->dmglog[0].dmg > md->tdmg) {
|
||||
md->tdmg += md->dmglog[0].dmg;
|
||||
md->dmglog[0].dmg *= 2;
|
||||
@ -2675,14 +2674,16 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
|
||||
|
||||
if (!tmpsd[i]) continue;
|
||||
|
||||
if (!battle_config.exp_calc_type && md->tdmg)
|
||||
//jAthena's exp formula based on total damage.
|
||||
per = (double)md->dmglog[i].dmg/(double)md->tdmg;
|
||||
else {
|
||||
//eAthena's exp formula based on max hp.
|
||||
per = (double)md->dmglog[i].dmg/(double)status->max_hp;
|
||||
if (per > 2) per = 2; // prevents unlimited exp gain
|
||||
if (battle_config.exp_calc_type == 1 || md->tdmg == 0) {
|
||||
// eAthena's exp formula based on max hp
|
||||
per = (double)md->dmglog[i].dmg / (double)status->max_hp;
|
||||
}
|
||||
else {
|
||||
// Aegis's exp formula based on total damage
|
||||
per = (double)md->dmglog[i].dmg / (double)md->tdmg;
|
||||
}
|
||||
// To prevent exploits
|
||||
if (per > 1) per = 1;
|
||||
|
||||
//Exclude rebirth tap from this calculation
|
||||
count -= md->state.rebirth;
|
||||
|
@ -2222,23 +2222,6 @@ int skill_additional_effect( struct block_list* src, struct block_list *bl, uint
|
||||
src = sd?&sd->bl:src;
|
||||
}
|
||||
|
||||
// Coma
|
||||
if (sd && sd->special_state.bonus_coma && (!md || util::vector_exists(status_get_race2(&md->bl), RC2_GVG) || status_get_class(&md->bl) != CLASS_BATTLEFIELD)) {
|
||||
int rate = 0;
|
||||
//! TODO: Filter the skills that shouldn't inflict coma bonus, to avoid some non-damage skills inflict coma. [Cydh]
|
||||
if (!skill_id || !skill_get_nk(skill_id, NK_NODAMAGE)) {
|
||||
rate += sd->indexed_bonus.coma_class[tstatus->class_] + sd->indexed_bonus.coma_class[CLASS_ALL];
|
||||
rate += sd->indexed_bonus.coma_race[tstatus->race] + sd->indexed_bonus.coma_race[RC_ALL];
|
||||
}
|
||||
if (attack_type&BF_WEAPON) {
|
||||
rate += sd->indexed_bonus.weapon_coma_ele[tstatus->def_ele] + sd->indexed_bonus.weapon_coma_ele[ELE_ALL];
|
||||
rate += sd->indexed_bonus.weapon_coma_race[tstatus->race] + sd->indexed_bonus.weapon_coma_race[RC_ALL];
|
||||
rate += sd->indexed_bonus.weapon_coma_class[tstatus->class_] + sd->indexed_bonus.weapon_coma_class[CLASS_ALL];
|
||||
}
|
||||
if (rate > 0)
|
||||
status_change_start(src,bl, SC_COMA, rate, 0, 0, src->id, 0, 0, SCSTART_NONE);
|
||||
}
|
||||
|
||||
if( attack_type&BF_WEAPON )
|
||||
{ // Breaking Equipment
|
||||
if( sd && battle_config.equip_self_break_rate )
|
||||
@ -3749,7 +3732,7 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
|
||||
nbl = battle_getenemyarea(bl,bl->x,bl->y,2,BL_CHAR,bl->id);
|
||||
if( nbl ){ // Only one target is chosen.
|
||||
damage = damage / 2; // Deflect half of the damage to a target nearby
|
||||
clif_skill_damage(bl, nbl, tick, status_get_amotion(src), 0, status_fix_damage(bl,nbl,damage,0,0), dmg.div_, OB_OBOROGENSOU_TRANSITION_ATK, -1, DMG_SINGLE);
|
||||
clif_skill_damage(bl, nbl, tick, status_get_amotion(src), 0, battle_fix_damage(bl,nbl,damage,0,0), dmg.div_, OB_OBOROGENSOU_TRANSITION_ATK, -1, DMG_SINGLE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3997,12 +3980,13 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
|
||||
|
||||
// Instant damage
|
||||
if( !dmg.amotion ) {
|
||||
//Deal damage before knockback to allow stuff like firewall+storm gust combo.
|
||||
if( (!tsc || (!tsc->getSCE(SC_DEVOTION) && skill_id != CR_REFLECTSHIELD && !tsc->getSCE(SC_WATER_SCREEN_OPTION))
|
||||
#ifndef RENEWAL
|
||||
|| skill_id == HW_GRAVITATION
|
||||
#endif
|
||||
|| skill_id == NPC_EVILLAND) && !shadow_flag )
|
||||
status_fix_damage(src,bl,damage,dmg.dmotion,skill_id); //Deal damage before knockback to allow stuff like firewall+storm gust combo.
|
||||
battle_damage(src, bl, damage, dmg.dmotion, skill_lv, skill_id, dmg.dmg_lv, dmg.flag, false, tick, false);
|
||||
if( !status_isdead(bl) && additional_effects )
|
||||
skill_additional_effect(src,bl,skill_id,skill_lv,dmg.flag,dmg.dmg_lv,tick);
|
||||
if( damage > 0 ) //Counter status effects [Skotlex]
|
||||
@ -4064,7 +4048,7 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
|
||||
|
||||
if (!rmdamage) {
|
||||
clif_damage(d_bl, d_bl, gettick(), 0, 0, devotion_damage, 0, DMG_NORMAL, 0, false);
|
||||
status_fix_damage(NULL, d_bl, devotion_damage, 0, 0);
|
||||
battle_fix_damage(src, d_bl, devotion_damage, 0, 0);
|
||||
} else {
|
||||
bool isDevotRdamage = false;
|
||||
|
||||
@ -4074,12 +4058,12 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
|
||||
// This check is only for magical skill.
|
||||
// For BF_WEAPON skills types track var rdamage and function battle_calc_return_damage
|
||||
clif_damage(bl, (!isDevotRdamage) ? bl : d_bl, gettick(), 0, 0, devotion_damage, 0, DMG_NORMAL, 0, false);
|
||||
status_fix_damage(bl, (!isDevotRdamage) ? bl : d_bl, devotion_damage, 0, 0);
|
||||
battle_fix_damage(bl, (!isDevotRdamage) ? bl : d_bl, devotion_damage, 0, 0);
|
||||
}
|
||||
} else {
|
||||
status_change_end(bl, SC_DEVOTION);
|
||||
if (!dmg.amotion)
|
||||
status_fix_damage(src, bl, damage, dmg.dmotion, 0);
|
||||
battle_fix_damage(src, bl, damage, dmg.dmotion, 0);
|
||||
}
|
||||
}
|
||||
if (tsc->getSCE(SC_WATER_SCREEN_OPTION)) {
|
||||
@ -4089,10 +4073,10 @@ int64 skill_attack (int attack_type, struct block_list* src, struct block_list *
|
||||
if (e_bl) {
|
||||
if (!rmdamage) {
|
||||
clif_skill_damage(e_bl, e_bl, gettick(), 0, 0, damage, dmg.div_, skill_id, -1, skill_get_hit(skill_id));
|
||||
status_fix_damage(NULL, e_bl, damage, 0, 0);
|
||||
battle_fix_damage(src, e_bl, damage, 0, 0);
|
||||
} else {
|
||||
clif_skill_damage(bl, bl, gettick(), 0, 0, damage, dmg.div_, skill_id, -1, skill_get_hit(skill_id));
|
||||
status_fix_damage(bl, bl, damage, 0, 0);
|
||||
battle_fix_damage(bl, bl, damage, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5021,7 +5005,7 @@ static int skill_tarotcard(struct block_list* src, struct block_list *target, ui
|
||||
}
|
||||
case 4: // THE CHARIOT - 1000 damage, random armor destroyed
|
||||
{
|
||||
status_fix_damage(src, target, 1000, 0, skill_id);
|
||||
battle_fix_damage(src, target, 1000, 0, skill_id);
|
||||
clif_damage(src, target, tick, 0, 0, 1000, 0, DMG_NORMAL, 0, false);
|
||||
if (!status_isdead(target))
|
||||
{
|
||||
@ -5075,7 +5059,7 @@ static int skill_tarotcard(struct block_list* src, struct block_list *target, ui
|
||||
}
|
||||
case 11: // THE DEVIL - 6666 damage, atk and matk halved, cursed
|
||||
{
|
||||
status_fix_damage(src, target, 6666, 0, skill_id);
|
||||
battle_fix_damage(src, target, 6666, 0, skill_id);
|
||||
clif_damage(src, target, tick, 0, 0, 6666, 0, DMG_NORMAL, 0, false);
|
||||
sc_start(src, target, SC_INCATKRATE, 100, -50, skill_get_time2(skill_id, skill_lv));
|
||||
sc_start(src, target, SC_INCMATKRATE, 100, -50, skill_get_time2(skill_id, skill_lv));
|
||||
@ -5084,7 +5068,7 @@ static int skill_tarotcard(struct block_list* src, struct block_list *target, ui
|
||||
}
|
||||
case 12: // THE TOWER - 4444 damage
|
||||
{
|
||||
status_fix_damage(src, target, 4444, 0, skill_id);
|
||||
battle_fix_damage(src, target, 4444, 0, skill_id);
|
||||
clif_damage(src, target, tick, 0, 0, 4444, 0, DMG_NORMAL, 0, false);
|
||||
break;
|
||||
}
|
||||
@ -8371,6 +8355,9 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
||||
dstmd->state.provoke_flag = src->id;
|
||||
mob_target(dstmd, src, skill_get_range2(src, skill_id, skill_lv, true));
|
||||
}
|
||||
// Provoke can cause Coma even though it's a nodamage skill
|
||||
if (sd && battle_check_coma(*sd, *bl, BF_MISC))
|
||||
status_change_start(src, bl, SC_COMA, 10000, skill_lv, 0, src->id, 0, 0, SCSTART_NONE);
|
||||
break;
|
||||
|
||||
case ML_DEVOTION:
|
||||
|
@ -1408,6 +1408,7 @@ int64 status_charge(struct block_list* bl, int64 hp, int64 sp)
|
||||
* flag&2: Fail if there is not enough to subtract
|
||||
* flag&4: Mob does not give EXP/Loot if killed
|
||||
* flag&8: Used to damage SP of a dead character
|
||||
* flag&16: Coma damage - Log it as normal damage, but actually set HP/SP to 1
|
||||
* @return hp+sp+ap
|
||||
* Note: HP/SP/AP are integer values, not percentages. Values should be
|
||||
* calculated either within function call or before
|
||||
@ -1527,10 +1528,25 @@ int status_damage(struct block_list *src,struct block_list *target,int64 dhp, in
|
||||
unit_skillcastcancel(target, 2);
|
||||
}
|
||||
|
||||
// We need to log the real damage on exp_calc_type 1
|
||||
if (battle_config.exp_calc_type == 1) {
|
||||
dhp = hp;
|
||||
// Coma real damage
|
||||
if (flag&16)
|
||||
dhp = status->hp - 1;
|
||||
}
|
||||
|
||||
status->hp-= hp;
|
||||
status->sp-= sp;
|
||||
status->ap-= ap;
|
||||
|
||||
// Coma
|
||||
if (flag&16) {
|
||||
status->hp = 1;
|
||||
status->sp = 1;
|
||||
if (!sp) sp = 1; // To make sure the status bar is updated
|
||||
}
|
||||
|
||||
if (sc && hp && status->hp) {
|
||||
if (sc->getSCE(SC_AUTOBERSERK) &&
|
||||
(!sc->getSCE(SC_PROVOKE) || !sc->getSCE(SC_PROVOKE)->val4) &&
|
||||
@ -1544,9 +1560,11 @@ int status_damage(struct block_list *src,struct block_list *target,int64 dhp, in
|
||||
status_change_end(target, SC_SATURDAYNIGHTFEVER);
|
||||
}
|
||||
|
||||
// Need to pass original HP damage for the mob damage log
|
||||
dhp = cap_value(dhp, INT_MIN, INT_MAX);
|
||||
switch (target->type) {
|
||||
case BL_PC: pc_damage((TBL_PC*)target,src,hp,sp,ap); break;
|
||||
case BL_MOB: mob_damage((TBL_MOB*)target, src, hp); break;
|
||||
case BL_MOB: mob_damage((TBL_MOB*)target, src, (int)dhp); break;
|
||||
case BL_HOM: hom_damage((TBL_HOM*)target); break;
|
||||
case BL_MER: mercenary_heal((TBL_MER*)target,hp,sp); break;
|
||||
case BL_ELEM: elemental_heal((TBL_ELEM*)target,hp,sp); break;
|
||||
@ -11226,7 +11244,7 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
||||
}
|
||||
|
||||
case SC_COMA: // Coma. Sends a char to 1HP. If val2, do not zap sp
|
||||
status_zap(bl, status->hp-1, val2?0:status->sp);
|
||||
status_zap(bl, status->hp-1, val2?0:status->sp-1);
|
||||
return 1;
|
||||
break;
|
||||
case SC_CLOSECONFINE2:
|
||||
|
Loading…
x
Reference in New Issue
Block a user