[root@server ~]# cd /home/rAthena
[root@server rAthena]# gdb map-server core.2543
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-100.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/rAthena/map-server...done.
[New LWP 2543]
Core was generated by `./map-server'.
Program terminated with signal 11, Segmentation fault.
#0 0x000000000042a512 in battle_calc_cardfix (attack_type=1, src=0x4bf2060,
target=<optimized out>, nk=<optimized out>, rh_ele=<optimized out>,
lh_ele=<optimized out>, damage=3167, left=0, flag=529) at battle.c:595
595 cardfix = cardfix * (100 + sd->magic_add race[tstatus->race] + sd->magic_addrace[RC_ALL] + sd->magic_addrace2[t_race2]) / 100;
(gdb) bt full
#0 0x000000000042a512 in battle_calc_cardfix (attack_type=1, src=0x4bf2060,
target=<optimized out>, nk=<optimized out>, rh_ele=<optimized out>,
lh_ele=<optimized out>, damage=3167, left=0, flag=529) at battle.c:595
sd = 0x4bf2060
tsd = <optimized out>
cardfix = <optimized out>
s_class = 4013
t_class = 4008
s_race2 = RC2_NONE
t_race2 = <optimized out>
s_defele = ELE_NEUTRAL
sstatus = 0x4bf24e4
tstatus = 0x4a2fae4
original_damage = 3167
i = <optimized out>
#1 0x00000000004372c7 in initialize_weapon_data (wflag=3167,
skill_lv=<optimized out>, skill_id=0, target=0x4a2f660, src=0x4bf2060)
at battle.c:5143
sstatus = 0x4a2f600
sc = 0x190
tstatus = 0x4a2fae4
sd = <optimized out>
wd = {damage = <optimized out>, damage2 = <optimized out>,
---Type <return> to continue, or q <return> to quit---return
type = DMG_NORMAL, div_ = <optimized out>,
amotion = <optimized out>, dmotion = <optimized out>,
blewcount = <optimized out>, flag = <optimized out>,
miscflag = <optimized out>, dmg_lv = <optimized out>,
isspdamage = <optimized out>}
#2 battle_calc_weapon_attack (src=0x4bf2060, target=0x4a2f660,
skill_id=<optimized out>, skill_lv=<optimized out>, wflag=3167)
at battle.c:5266
sd = <optimized out>
tsd = <optimized out>
wd = {damage = 3167, damage2 = 830, type = DMG_NORMAL, div_ = 1,
amotion = 30, dmotion = 400, blewcount = 0, flag = 529,
miscflag = 0, dmg_lv = ATK_DEF, isspdamage = 0 '\000'}
sc = 0x211
tstatus = 0x211
right_element = <optimized out>
left_element = <optimized out>
infdef = 0 '\000'
__FUNCTION__.21951 = "battle_calc_weapon_attack"
#3 0x000000000043c5b8 in battle_weapon_attack (src=0x7fff64e71ff0,
target=0x4a2f660, tick=<optimized out>, flag=<optimized out>)
at battle.c:7092
index = -31585
---Type <return> to continue, or q <return> to quit---return
sd = 0x4bf2060
tsd = <optimized out>
sstatus = <optimized out>
tstatus = <optimized out>
sc = 0x4bf2540
tsc = 0x4a2fb40
damage = <optimized out>
skillv = <optimized out>
wd = {damage = 0, damage2 = 0, type = DMG_SIT_DOWN, div_ = 0,
amotion = 659864132, dmotion = 13, blewcount = 14, flag = 15,
miscflag = 659864132, dmg_lv = 32757, isspdamage = -126 '\202'}
vanish_damage = 0 '\000'
__FUNCTION__.22341 = "battle_weapon_attack"
#4 0x00000000000e427d in ?? ()
No symbol table info available.
#5 0x0000000004bf2060 in ?? ()
No symbol table info available.
#6 0x0000000004a2f660 in ?? ()
No symbol table info available.
#7 0x0000000004bf2080 in ?? ()
No symbol table info available.
#8 0x0000000004bf2060 in ?? ()
No symbol table info available.
---Type <return> to continue, or q <return> to quit---return
#9 0x0000000000000417 in ?? ()
No symbol table info available.
#10 0x00000000000e427d in ?? ()
No symbol table info available.
#11 0x0000000004bf2060 in ?? ()
No symbol table info available.
#12 0x0000000004a2f660 in ?? ()
No symbol table info available.
#13 0x0000000004bf2080 in ?? ()
No symbol table info available.
#14 0x000000000055236a in unit_attack (
src=0x4e395e <skill_check_condition_mercenary+158>, target_id=0,
continuous=77788768) at unit.c:2210
target = 0x4bf2060
ud = 0x4bf2060
range = <optimized out>
#15 0x000000000000022d in ?? ()
No symbol table info available.
#16 0x0000000004298560 in ?? ()
No symbol table info available.
#17 0x00007ff52628113c in ?? ()
No symbol table info available.
#18 0x00000000000e5b94 in ?? ()
---Type <return> to continue, or q <return> to quit---return
No symbol table info available.
#19 0x00000000005ad7ba in get_uptime () at timer.c:405
No locals.
#20 0x000e427e00000416 in ?? ()
No symbol table info available.
#21 0x00000000028256f0 in ?? ()
No symbol table info available.
#22 0x00007fff64e722a8 in ?? ()
No symbol table info available.
#23 0x00000000028256f0 in ?? ()
No symbol table info available.
#24 0x0000000000000002 in ?? ()
No symbol table info available.
#25 0x0000000000000001 in ?? ()
No symbol table info available.
#26 0x0000000000000000 in ?? ()
No symbol table info available.
(gdb)
battle.c
int battle_calc_cardfix(int attack_type,struct block_list *src,struct block_list *target,int nk,int rh_ele,int lh_ele,int64 damage,int left,int flag){struct map_session_data *sd,///< Attacker session data if BL_PC*tsd;///< Target session data if BL_PCshort cardfix =1000;enum e_classAE s_class,///< Attacker class
t_class;///< Target classenum e_race2 s_race2,/// Attacker Race2
t_race2;///< Target Race2enum e_element s_defele;///< Attacker Element (not a weapon or skill element!)struct status_data *sstatus,///< Attacker status data*tstatus;///< Target status dataint64 original_damage;int i;if(!damage )return0;
original_damage = damage;
sd = BL_CAST(BL_PC, src);
tsd = BL_CAST(BL_PC, target);
t_class =(enum e_classAE)status_get_class(target);
s_class =(enum e_classAE)status_get_class(src);
sstatus = status_get_status_data(src);
tstatus = status_get_status_data(target);
s_race2 = status_get_race2(src);
t_race2 = status_get_race2(target);
s_defele =(tsd)?(enum e_element)status_get_element(src): ELE_NONE;//Official servers apply the cardfix value on a base of 1000 and round down the reduction/increase#define APPLY_CARDFIX(damage, fix){(damage)=(damage)-(int64)(((damage)*(1000-(fix)))/1000);}switch( attack_type ){case BF_MAGIC:// Affected by attacker ATK bonusesif( sd &&!(nk&NK_NO_CARDFIX_ATK)){
cardfix = cardfix *(100+ sd->magic_addrace[tstatus->race]+ sd->magic_addrace[RC_ALL]+ sd->magic_addrace2[t_race2])/100;if(!(nk&NK_NO_ELEFIX)){// Affected by Element modifier bonuses
cardfix = cardfix *(100+ sd->magic_addele[tstatus->def_ele]+ sd->magic_addele[ELE_ALL]+
sd->magic_addele_script[tstatus->def_ele]+ sd->magic_addele_script[ELE_ALL])/100;
cardfix = cardfix *(100+ sd->magic_atk_ele[rh_ele]+ sd->magic_atk_ele[ELE_ALL])/100;}
cardfix = cardfix *(100+ sd->magic_addsize[tstatus->size]+ sd->magic_addsize[SZ_ALL])/100;
cardfix = cardfix *(100+ sd->magic_addclass[tstatus->class_]+ sd->magic_addclass[CLASS_ALL])/100;for( i =0; i < ARRAYLENGTH(sd->add_mdmg)&& sd->add_mdmg[i].rate; i++){if( sd->add_mdmg[i].class_ == t_class ){
cardfix = cardfix *(100+ sd->add_mdmg[i].rate)/100;break;}}
APPLY_CARDFIX(damage, cardfix);}// Affected by target DEF bonusesif( tsd &&!(nk&NK_NO_CARDFIX_DEF)){
cardfix =1000;// reset var for targetif(!(nk&NK_NO_ELEFIX)){// Affected by Element modifier bonusesint ele_fix = tsd->subele[rh_ele]+ tsd->subele[ELE_ALL]+ tsd->subele_script[rh_ele]+ tsd->subele_script[ELE_ALL];for( i =0; ARRAYLENGTH(tsd->subele2)> i && tsd->subele2[i].rate !=0; i++){if( tsd->subele2[i].ele != rh_ele )continue;if(!(((tsd->subele2[i].flag)&flag)&BF_WEAPONMASK &&((tsd->subele2[i].flag)&flag)&BF_RANGEMASK &&((tsd->subele2[i].flag)&flag)&BF_SKILLMASK))continue;
ele_fix += tsd->subele2[i].rate;}if(s_defele != ELE_NONE)
ele_fix += tsd->subdefele[s_defele]+ tsd->subdefele[ELE_ALL];
cardfix = cardfix *(100- ele_fix)/100;}
cardfix = cardfix *(100- tsd->subsize[sstatus->size]- tsd->subsize[SZ_ALL])/100;
cardfix = cardfix *(100- tsd->subrace2[s_race2])/100;
cardfix = cardfix *(100- tsd->subrace[sstatus->race]- tsd->subrace[RC_ALL])/100;
cardfix = cardfix *(100- tsd->subclass[sstatus->class_]- tsd->subclass[CLASS_ALL])/100;for( i =0; i < ARRAYLENGTH(tsd->add_mdef)&& tsd->add_mdef[i].rate; i++){if( tsd->add_mdef[i].class_ == s_class ){
cardfix = cardfix *(100- tsd->add_mdef[i].rate)/100;break;}}#ifndef RENEWAL
//It was discovered that ranged defense also counts vs magic! [Skotlex]if( flag&BF_SHORT )
cardfix = cardfix *(100- tsd->bonus.near_attack_def_rate)/100;else
cardfix = cardfix *(100- tsd->bonus.long_attack_def_rate)/100;#endif
cardfix = cardfix *(100- tsd->bonus.magic_def_rate)/100;if( tsd->sc.data[SC_MDEF_RATE])
cardfix = cardfix *(100- tsd->sc.data[SC_MDEF_RATE]->val1)/100;
APPLY_CARDFIX(damage, cardfix);}break;case BF_WEAPON:// Affected by attacker ATK bonusesif( sd &&!(nk&NK_NO_CARDFIX_ATK)&&(left&2)){short cardfix_ =1000;if( sd->state.arrow_atk ){// Ranged attack
cardfix = cardfix *(100+ sd->right_weapon.addrace[tstatus->race]+ sd->arrow_addrace[tstatus->race]+
sd->right_weapon.addrace[RC_ALL]+ sd->arrow_addrace[RC_ALL])/100;if(!(nk&NK_NO_ELEFIX)){// Affected by Element modifier bonusesint ele_fix = sd->right_weapon.addele[tstatus->def_ele]+ sd->arrow_addele[tstatus->def_ele]+
sd->right_weapon.addele[ELE_ALL]+ sd->arrow_addele[ELE_ALL];for( i =0; ARRAYLENGTH(sd->right_weapon.addele2)> i && sd->right_weapon.addele2[i].rate !=0; i++){if( sd->right_weapon.addele2[i].ele != tstatus->def_ele )continue;if(!(((sd->right_weapon.addele2[i].flag)&flag)&BF_WEAPONMASK &&((sd->right_weapon.addele2[i].flag)&flag)&BF_RANGEMASK &&((sd->right_weapon.addele2[i].flag)&flag)&BF_SKILLMASK))continue;
ele_fix += sd->right_weapon.addele2[i].rate;}
cardfix = cardfix *(100+ ele_fix)/100;}
cardfix = cardfix *(100+ sd->right_weapon.addsize[tstatus->size]+ sd->arrow_addsize[tstatus->size]+
sd->right_weapon.addsize[SZ_ALL]+ sd->arrow_addsize[SZ_ALL])/100;
cardfix = cardfix *(100+ sd->right_weapon.addrace2[t_race2])/100;
cardfix = cardfix *(100+ sd->right_weapon.addclass[tstatus->class_]+ sd->arrow_addclass[tstatus->class_]+
sd->right_weapon.addclass[CLASS_ALL]+ sd->arrow_addclass[CLASS_ALL])/100;}else{// Melee attackint skill =0;// Calculates each right & left hand weapon bonuses separatedlyif(!battle_config.left_cardfix_to_right ){// Right-handed weapon
cardfix = cardfix *(100+ sd->right_weapon.addrace[tstatus->race]+ sd->right_weapon.addrace[RC_ALL])/100;if(!(nk&NK_NO_ELEFIX)){// Affected by Element modifier bonusesint ele_fix = sd->right_weapon.addele[tstatus->def_ele]+ sd->right_weapon.addele[ELE_ALL];for( i =0; ARRAYLENGTH(sd->right_weapon.addele2)> i && sd->right_weapon.addele2[i].rate !=0; i++){if( sd->right_weapon.addele2[i].ele != tstatus->def_ele )continue;if(!(((sd->right_weapon.addele2[i].flag)&flag)&BF_WEAPONMASK &&((sd->right_weapon.addele2[i].flag)&flag)&BF_RANGEMASK &&((sd->right_weapon.addele2[i].flag)&flag)&BF_SKILLMASK))continue;
ele_fix += sd->right_weapon.addele2[i].rate;}
cardfix = cardfix *(100+ ele_fix)/100;}
cardfix = cardfix *(100+ sd->right_weapon.addsize[tstatus->size]+ sd->right_weapon.addsize[SZ_ALL])/100;
cardfix = cardfix *(100+ sd->right_weapon.addrace2[t_race2])/100;
cardfix = cardfix *(100+ sd->right_weapon.addclass[tstatus->class_]+ sd->right_weapon.addclass[CLASS_ALL])/100;if( left&1){// Left-handed weapon
cardfix_ = cardfix_ *(100+ sd->left_weapon.addrace[tstatus->race]+ sd->left_weapon.addrace[RC_ALL])/100;if(!(nk&NK_NO_ELEFIX)){// Affected by Element modifier bonusesint ele_fix_lh = sd->left_weapon.addele[tstatus->def_ele]+ sd->left_weapon.addele[ELE_ALL];for( i =0; ARRAYLENGTH(sd->left_weapon.addele2)> i && sd->left_weapon.addele2[i].rate !=0; i++){if( sd->left_weapon.addele2[i].ele != tstatus->def_ele )continue;if(!(((sd->left_weapon.addele2[i].flag)&flag)&BF_WEAPONMASK &&((sd->left_weapon.addele2[i].flag)&flag)&BF_RANGEMASK &&((sd->left_weapon.addele2[i].flag)&flag)&BF_SKILLMASK))continue;
ele_fix_lh += sd->left_weapon.addele2[i].rate;}
cardfix_ = cardfix_ *(100+ ele_fix_lh)/100;}
cardfix_ = cardfix_ *(100+ sd->left_weapon.addsize[tstatus->size]+ sd->left_weapon.addsize[SZ_ALL])/100;
cardfix_ = cardfix_ *(100+ sd->left_weapon.addrace2[t_race2])/100;
cardfix_ = cardfix_ *(100+ sd->left_weapon.addclass[tstatus->class_]+ sd->left_weapon.addclass[CLASS_ALL])/100;}}// Calculates right & left hand weapon as unityelse{//! CHECKME: If 'left_cardfix_to_right' is yes, doesn't need to check NK_NO_ELEFIX?//if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonusesint ele_fix = sd->right_weapon.addele[tstatus->def_ele]+ sd->left_weapon.addele[tstatus->def_ele]+ sd->right_weapon.addele[ELE_ALL]+ sd->left_weapon.addele[ELE_ALL];for( i =0; ARRAYLENGTH(sd->right_weapon.addele2)> i && sd->right_weapon.addele2[i].rate !=0; i++){if( sd->right_weapon.addele2[i].ele != tstatus->def_ele )continue;if(!(((sd->right_weapon.addele2[i].flag)&flag)&BF_WEAPONMASK &&((sd->right_weapon.addele2[i].flag)&flag)&BF_RANGEMASK &&((sd->right_weapon.addele2[i].flag)&flag)&BF_SKILLMASK))continue;
ele_fix += sd->right_weapon.addele2[i].rate;}for( i =0; ARRAYLENGTH(sd->left_weapon.addele2)> i && sd->left_weapon.addele2[i].rate !=0; i++){if( sd->left_weapon.addele2[i].ele != tstatus->def_ele )continue;if(!(((sd->left_weapon.addele2[i].flag)&flag)&BF_WEAPONMASK &&((sd->left_weapon.addele2[i].flag)&flag)&BF_RANGEMASK &&((sd->left_weapon.addele2[i].flag)&flag)&BF_SKILLMASK))continue;
ele_fix += sd->left_weapon.addele2[i].rate;}
cardfix = cardfix *(100+ ele_fix)/100;//}
cardfix = cardfix *(100+ sd->right_weapon.addrace[tstatus->race]+ sd->left_weapon.addrace[tstatus->race]+
sd->right_weapon.addrace[RC_ALL]+ sd->left_weapon.addrace[RC_ALL])/100;
cardfix = cardfix *(100+ sd->right_weapon.addsize[tstatus->size]+ sd->left_weapon.addsize[tstatus->size]+
sd->right_weapon.addsize[SZ_ALL]+ sd->left_weapon.addsize[SZ_ALL])/100;
cardfix = cardfix *(100+ sd->right_weapon.addrace2[t_race2]+ sd->left_weapon.addrace2[t_race2])/100;
cardfix = cardfix *(100+ sd->right_weapon.addclass[tstatus->class_]+ sd->left_weapon.addclass[tstatus->class_]+
sd->right_weapon.addclass[CLASS_ALL]+ sd->left_weapon.addclass[CLASS_ALL])/100;}if( sd->status.weapon == W_KATAR &&(skill = pc_checkskill(sd,ASC_KATAR))>0)// Adv. Katar Mastery functions similar to a +%ATK card on official [helvetica]
cardfix = cardfix *(100+(10+2* skill))/100;}//! CHECKME: These right & left hand weapon ignores 'left_cardfix_to_right'?for( i =0; i < ARRAYLENGTH(sd->right_weapon.add_dmg)&& sd->right_weapon.add_dmg[i].rate; i++){if( sd->right_weapon.add_dmg[i].class_ == t_class ){
cardfix = cardfix *(100+ sd->right_weapon.add_dmg[i].rate)/100;break;}}if( left&1){for( i =0; i < ARRAYLENGTH(sd->left_weapon.add_dmg)&& sd->left_weapon.add_dmg[i].rate; i++){if( sd->left_weapon.add_dmg[i].class_ == t_class ){
cardfix_ = cardfix_ *(100+ sd->left_weapon.add_dmg[i].rate)/100;break;}}}#ifndef RENEWAL
if( flag&BF_LONG )
cardfix = cardfix *(100+ sd->bonus.long_attack_atk_rate)/100;#endifif(left&1){
APPLY_CARDFIX(damage, cardfix_);}else{
APPLY_CARDFIX(damage, cardfix);}}// Affected by target DEF bonuseselseif( tsd &&!(nk&NK_NO_CARDFIX_DEF)&&!(left&2)){if(!(nk&NK_NO_ELEFIX)){// Affected by Element modifier bonusesint ele_fix = tsd->subele[rh_ele]+ tsd->subele[ELE_ALL]+ tsd->subele_script[rh_ele]+ tsd->subele_script[ELE_ALL];for( i =0; ARRAYLENGTH(tsd->subele2)> i && tsd->subele2[i].rate !=0; i++){if( tsd->subele2[i].ele != rh_ele )continue;if(!(((tsd->subele2[i].flag)&flag)&BF_WEAPONMASK &&((tsd->subele2[i].flag)&flag)&BF_RANGEMASK &&((tsd->subele2[i].flag)&flag)&BF_SKILLMASK))continue;
ele_fix += tsd->subele2[i].rate;}
cardfix = cardfix *(100- ele_fix)/100;if( left&1&& lh_ele != rh_ele ){int ele_fix_lh = tsd->subele[lh_ele]+ tsd->subele[ELE_ALL]+ tsd->subele_script[lh_ele]+ tsd->subele_script[ELE_ALL];for( i =0; ARRAYLENGTH(tsd->subele2)> i && tsd->subele2[i].rate !=0; i++){if( tsd->subele2[i].ele != lh_ele )continue;if(!(((tsd->subele2[i].flag)&flag)&BF_WEAPONMASK &&((tsd->subele2[i].flag)&flag)&BF_RANGEMASK &&((tsd->subele2[i].flag)&flag)&BF_SKILLMASK))continue;
ele_fix_lh += tsd->subele2[i].rate;}
cardfix = cardfix *(100- ele_fix_lh)/100;}
cardfix = cardfix *(100- tsd->subdefele[s_defele]- tsd->subdefele[ELE_ALL])/100;}
cardfix = cardfix *(100- tsd->subsize[sstatus->size]- tsd->subsize[SZ_ALL])/100;
cardfix = cardfix *(100- tsd->subrace2[s_race2])/100;
cardfix = cardfix *(100- tsd->subrace[sstatus->race]- tsd->subrace[RC_ALL])/100;
cardfix = cardfix *(100- tsd->subclass[sstatus->class_]- tsd->subclass[CLASS_ALL])/100;for( i =0; i < ARRAYLENGTH(tsd->add_def)&& tsd->add_def[i].rate; i++){if( tsd->add_def[i].class_ == s_class ){
cardfix = cardfix *(100- tsd->add_def[i].rate)/100;break;}}if( flag&BF_SHORT )
cardfix = cardfix *(100- tsd->bonus.near_attack_def_rate)/100;else// BF_LONG (there's no other choice)
cardfix = cardfix *(100- tsd->bonus.long_attack_def_rate)/100;if( tsd->sc.data[SC_DEF_RATE])
cardfix = cardfix *(100- tsd->sc.data[SC_DEF_RATE]->val1)/100;
APPLY_CARDFIX(damage, cardfix);}break;case BF_MISC:// Affected by target DEF bonusesif( tsd &&!(nk&NK_NO_CARDFIX_DEF)){if(!(nk&NK_NO_ELEFIX)){// Affected by Element modifier bonusesint ele_fix = tsd->subele[rh_ele]+ tsd->subele[ELE_ALL]+ tsd->subele_script[rh_ele]+ tsd->subele_script[ELE_ALL];for( i =0; ARRAYLENGTH(tsd->subele2)> i && tsd->subele2[i].rate !=0; i++){if( tsd->subele2[i].ele != rh_ele )continue;if(!(((tsd->subele2[i].flag)&flag)&BF_WEAPONMASK &&((tsd->subele2[i].flag)&flag)&BF_RANGEMASK &&((tsd->subele2[i].flag)&flag)&BF_SKILLMASK))continue;
ele_fix += tsd->subele2[i].rate;}if(s_defele != ELE_NONE)
ele_fix += tsd->subdefele[s_defele]+ tsd->subdefele[ELE_ALL];
cardfix = cardfix *(100- ele_fix)/100;}
cardfix = cardfix *(100- tsd->subsize[sstatus->size]- tsd->subsize[SZ_ALL])/100;
cardfix = cardfix *(100- tsd->subrace2[s_race2])/100;
cardfix = cardfix *(100- tsd->subrace[sstatus->race]- tsd->subrace[RC_ALL])/100;
cardfix = cardfix *(100- tsd->subclass[sstatus->class_]- tsd->subclass[CLASS_ALL])/100;
cardfix = cardfix *(100- tsd->bonus.misc_def_rate)/100;if( flag&BF_SHORT )
cardfix = cardfix *(100- tsd->bonus.near_attack_def_rate)/100;else// BF_LONG (there's no other choice)
cardfix = cardfix *(100- tsd->bonus.long_attack_def_rate)/100;
APPLY_CARDFIX(damage, cardfix);}break;}#undef APPLY_CARDFIX
return(int)cap_value(damage - original_damage, INT_MIN, INT_MAX);}......staticstructDamage initialize_weapon_data(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int wflag){struct status_data *sstatus = status_get_status_data(src);struct status_data *tstatus = status_get_status_data(target);struct status_change *sc = status_get_sc(src);struct map_session_data *sd = BL_CAST(BL_PC, src);structDamage wd;
wd.type = DMG_NORMAL;//Normal attack
wd.div_ = skill_id?skill_get_num(skill_id,skill_lv):1;
wd.amotion =(skill_id && skill_get_inf(skill_id)&INF_GROUND_SKILL)?0:sstatus->amotion;//Amotion should be 0 for ground skills.// counter attack DOES obey ASPD delay on official, uncomment if you want the old (bad) behavior [helvetica]/*if(skill_id == KN_AUTOCOUNTER)
wd.amotion >>= 1; */
wd.dmotion = tstatus->dmotion;
wd.blewcount =skill_get_blewcount(skill_id,skill_lv);
wd.miscflag = wflag;
wd.flag = BF_WEAPON;//Initial Flag
wd.flag |=(skill_id||wd.miscflag)?BF_SKILL:BF_NORMAL;// Baphomet card's splash damage is counted as a skill. [Inkfish]
wd.damage = wd.damage2 =#ifdef RENEWAL
wd.statusAtk = wd.statusAtk2 = wd.equipAtk = wd.equipAtk2 = wd.weaponAtk = wd.weaponAtk2 = wd.masteryAtk = wd.masteryAtk2 =#endif0;
wd.dmg_lv=ATK_DEF;//This assumption simplifies the assignation laterif(sd)
wd.blewcount += battle_blewcount_bonus(sd, skill_id);if(skill_id){
wd.flag |= battle_range_type(src, target, skill_id, skill_lv);switch(skill_id){case MH_SONIC_CRAW:{
TBL_HOM *hd = BL_CAST(BL_HOM,src);
wd.div_ = hd->homunculus.spiritball;}break;case MO_FINGEROFFENSIVE:if(sd){if(battle_config.finger_offensive_type)
wd.div_ =1;else
wd.div_ = sd->spiritball_old;}break;case KN_PIERCE:case ML_PIERCE:
wd.div_=(wd.div_>0?tstatus->size+1:-(tstatus->size+1));break;case TF_DOUBLE://For NPC used skill.case GS_CHAINACTION:
wd.type = DMG_MULTI_HIT;break;case GS_GROUNDDRIFT:
wd.amotion = sstatus->amotion;//Fall throughcase KN_SPEARSTAB:case KN_BOWLINGBASH:case MS_BOWLINGBASH:case MO_BALKYOUNG:case TK_TURNKICK:
wd.blewcount =0;break;case KN_AUTOCOUNTER:
wd.flag =(wd.flag&~BF_SKILLMASK)|BF_NORMAL;break;case LK_SPIRALPIERCE:if(!sd) wd.flag =(wd.flag&~(BF_RANGEMASK|BF_WEAPONMASK))|BF_LONG|BF_MISC;break;// The number of hits is set to 3 by default for use in Inspiration status.// When in Banding, the number of hits is equal to the number of Royal Guards in Banding.case LG_HESPERUSLIT:if( sc && sc->data[SC_BANDING]&& sc->data[SC_BANDING]->val2 >3)
wd.div_ = sc->data[SC_BANDING]->val2;break;}}else{
wd.flag |= is_skill_using_arrow(src, skill_id)?BF_LONG:BF_SHORT;}return wd;}......staticstructDamage battle_calc_weapon_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int wflag){struct map_session_data *sd,*tsd;structDamage wd;struct status_change *sc = status_get_sc(src);struct status_change *tsc = status_get_sc(target);struct status_data *tstatus = status_get_status_data(target);int right_element, left_element;bool infdef =false;
memset(&wd,0,sizeof(wd));if(src == NULL || target == NULL){
nullpo_info(NLP_MARK);return wd;}
wd = initialize_weapon_data(src, target, skill_id, skill_lv, wflag);
right_element = battle_get_weapon_element(wd, src, target, skill_id, skill_lv, EQI_HAND_R,false);
left_element = battle_get_weapon_element(wd, src, target, skill_id, skill_lv, EQI_HAND_L,false);if(sc &&!sc->count)
sc = NULL;//Skip checking as there are no status changes active.if(tsc &&!tsc->count)
tsc = NULL;//Skip checking as there are no status changes active.
sd = BL_CAST(BL_PC, src);
tsd = BL_CAST(BL_PC, target);//Check for Lucky Dodgeif((!skill_id || skill_id == PA_SACRIFICE)&& tstatus->flee2 && rnd()%1000< tstatus->flee2){
wd.type = DMG_LUCY_DODGE;
wd.dmg_lv = ATK_LUCKY;if(wd.div_ <0)
wd.div_ *=-1;return wd;}// on official check for multi hit first so we can override crit on double attack [helvetica]
wd = battle_calc_multi_attack(wd, src, target, skill_id, skill_lv);// crit check is next since crits always hit on official [helvetica]if(is_attack_critical(wd, src, target, skill_id, skill_lv,true))
wd.type = DMG_CRITICAL;// check if we're landing a hitif(!is_attack_hitting(wd, src, target, skill_id, skill_lv,true))
wd.dmg_lv = ATK_FLEE;elseif(!(infdef = is_infinite_defense(target, wd.flag))){//no need for math against plantsint64 ratio =0;int i =0;
wd = battle_calc_skill_base_damage(wd, src, target, skill_id, skill_lv);// base skill damage
ratio = battle_calc_attack_skill_ratio(wd, src, target, skill_id, skill_lv);// skill level ratios
ATK_RATE(wd.damage, wd.damage2, ratio);
RE_ALLATK_RATE(wd, ratio);
ratio = battle_calc_skill_constant_addition(wd, src, target, skill_id, skill_lv);// other skill bonuses
ATK_ADD(wd.damage, wd.damage2, ratio);
RE_ALLATK_ADD(wd, ratio);#ifdef RENEWAL
if(skill_id == HW_MAGICCRASHER){// Add weapon attack for MATK onto Magic Crasherstruct status_data *sstatus = status_get_status_data(src);if(sstatus->matk_max > sstatus->matk_min){
ATK_ADD(wd.weaponAtk, wd.weaponAtk2, sstatus->matk_min+rnd()%(sstatus->matk_max-sstatus->matk_min));}else
ATK_ADD(wd.weaponAtk, wd.weaponAtk2, sstatus->matk_min);}#endif// add any miscellaneous player ATK bonusesif( sd && skill_id &&(i = pc_skillatk_bonus(sd, skill_id))){
ATK_ADDRATE(wd.damage, wd.damage2, i);
RE_ALLATK_ADDRATE(wd, i);}if(tsd &&(i = pc_sub_skillatk_bonus(tsd, skill_id))){
ATK_ADDRATE(wd.damage, wd.damage2,-i);
RE_ALLATK_ADDRATE(wd,-i);}#ifdef RENEWAL
// In Renewal we only cardfix to the weapon and equip ATK//Card Fix for attacker (sd), 2 is added to the "left" flag meaning "attacker cards only"
wd.weaponAtk += battle_calc_cardfix(BF_WEAPON, src, target, battle_skill_get_damage_properties(skill_id, wd.miscflag), right_element, left_element, wd.weaponAtk,2, wd.flag);
wd.equipAtk += battle_calc_cardfix(BF_WEAPON, src, target, battle_skill_get_damage_properties(skill_id, wd.miscflag), right_element, left_element, wd.equipAtk,2, wd.flag);if(is_attack_left_handed(src, skill_id)){
wd.weaponAtk2 += battle_calc_cardfix(BF_WEAPON, src, target, battle_skill_get_damage_properties(skill_id, wd.miscflag), right_element, left_element, wd.weaponAtk2,3, wd.flag);
wd.equipAtk2 += battle_calc_cardfix(BF_WEAPON, src, target, battle_skill_get_damage_properties(skill_id, wd.miscflag), right_element, left_element, wd.equipAtk2,3, wd.flag);}// final attack bonuses that aren't affected by cards
wd = battle_attack_sc_bonus(wd, src, target, skill_id, skill_lv);if(sd){//monsters, homuns and pets have their damage computed directly
wd.damage = wd.statusAtk + wd.weaponAtk + wd.equipAtk + wd.masteryAtk;
wd.damage2 = wd.statusAtk2 + wd.weaponAtk2 + wd.equipAtk2 + wd.masteryAtk2;if(wd.flag&BF_LONG &&(skill_id != RA_WUGBITE && skill_id != RA_WUGSTRIKE))//Long damage rate addition doesn't use weapon + equip attack
ATK_ADDRATE(wd.damage, wd.damage2, sd->bonus.long_attack_atk_rate);}#else// final attack bonuses that aren't affected by cards
wd = battle_attack_sc_bonus(wd, src, target, skill_id, skill_lv);#endifif(wd.damage + wd.damage2){//Check if attack ignores DEFif(!attack_ignores_def(wd, src, target, skill_id, skill_lv, EQI_HAND_L)||!attack_ignores_def(wd, src, target, skill_id, skill_lv, EQI_HAND_R))
wd = battle_calc_defense_reduction(wd, src, target, skill_id, skill_lv);
wd = battle_calc_attack_post_defense(wd, src, target, skill_id, skill_lv);}}#ifdef RENEWAL
if(!sd)// monsters only have a single ATK for element, in pre-renewal we also apply element to entire ATK on players [helvetica]#endif
wd = battle_calc_element_damage(wd, src, target, skill_id, skill_lv);if(skill_id == CR_GRANDCROSS || skill_id == NPC_GRANDDARKNESS)return wd;//Enough, rest is not needed.#ifdef RENEWAL
if(is_attack_critical(wd, src, target, skill_id, skill_lv,false)){if(sd){//Check for player so we don't crash out, monsters don't have bonus crit rates [helvetica]
wd.damage =(int)floor((float)((wd.damage *140)/100*(100+ sd->bonus.crit_atk_rate))/100);if(is_attack_left_handed(src, skill_id))
wd.damage2 =(int)floor((float)((wd.damage2 *140)/100*(100+ sd->bonus.crit_atk_rate))/100);}else
wd.damage =(int)floor((float)(wd.damage *140)/100);}#endif#ifndef RENEWAL
if(skill_id == NJ_KUNAI){short nk = battle_skill_get_damage_properties(skill_id, wd.miscflag);
ATK_ADD(wd.damage, wd.damage2,90);
nk |= NK_IGNORE_DEF;}#endifswitch(skill_id){case TK_DOWNKICK:case TK_STORMKICK:case TK_TURNKICK:case TK_COUNTER:if(sd && sd->weapontype1 == W_FIST && sd->weapontype2 == W_FIST)
ATK_ADD(wd.damage, wd.damage2,10* pc_checkskill(sd, TK_RUN));break;case SR_TIGERCANNON:// (Tiger Cannon skill level x 240) + (Target Base Level x 40)if(wd.miscflag&8){
ATK_ADD(wd.damage, wd.damage2, skill_lv *500+ status_get_lv(target)*40);}else
ATK_ADD(wd.damage, wd.damage2, skill_lv *240+ status_get_lv(target)*40);break;case SR_GATEOFHELL:{struct status_data *sstatus = status_get_status_data(src);
ATK_ADD(wd.damage, wd.damage2, sstatus->max_hp - status_get_hp(src));if(sc && sc->data[SC_COMBO]&& sc->data[SC_COMBO]->val1 == SR_FALLENEMPIRE){
ATK_ADD(wd.damage, wd.damage2,(sstatus->max_sp *(1+ skill_lv *2/10))+40* status_get_lv(src));}else
ATK_ADD(wd.damage, wd.damage2,(sstatus->sp *(1+ skill_lv *2/10))+10* status_get_lv(src));}break;}if(sd){#ifndef RENEWAL
uint16 skill;if((skill = pc_checkskill(sd, BS_WEAPONRESEARCH))>0)
ATK_ADD(wd.damage, wd.damage2, skill *2);if(skill_id == TF_POISON)
ATK_ADD(wd.damage, wd.damage2,15* skill_lv);if(skill_id == GS_GROUNDDRIFT)
ATK_ADD(wd.damage, wd.damage2,50* skill_lv);if(skill_id != CR_SHIELDBOOMERANG)//Only Shield boomerang doesn't takes the Star Crumbs bonus.
ATK_ADD2(wd.damage, wd.damage2,((wd.div_ <1)?1: wd.div_)* sd->right_weapon.star,((wd.div_ <1)?1: wd.div_)* sd->left_weapon.star);if(skill_id != MC_CARTREVOLUTION && pc_checkskill(sd, BS_HILTBINDING)>0)
ATK_ADD(wd.damage, wd.damage2,4);if(skill_id == MO_FINGEROFFENSIVE){//The finger offensive spheres on moment of attack do count. [Skotlex]
ATK_ADD(wd.damage, wd.damage2,((wd.div_ <1)?1: wd.div_)* sd->spiritball_old *3);}else
ATK_ADD(wd.damage, wd.damage2,((wd.div_ <1)?1: wd.div_)* sd->spiritball *3);#endifif( skill_id == CR_SHIELDBOOMERANG || skill_id == PA_SHIELDCHAIN ){//Refine bonus applies after cards and elements.short index = sd->equip_index[EQI_HAND_L];if( index >=0&& sd->inventory_data[index]&& sd->inventory_data[index]->type == IT_ARMOR )
ATK_ADD(wd.damage, wd.damage2,10*sd->inventory.u.items_inventory[index].refine);}#ifndef RENEWAL
//Card Fix for attacker (sd), 2 is added to the "left" flag meaning "attacker cards only"switch(skill_id){case RK_DRAGONBREATH:case RK_DRAGONBREATH_WATER:if(wd.flag&BF_LONG){//Add check here, because we want to apply the same behavior in pre-renewal [exneval]
wd.damage = wd.damage *(100+ sd->bonus.long_attack_atk_rate)/100;if(is_attack_left_handed(src, skill_id))
wd.damage2 = wd.damage2 *(100+ sd->bonus.long_attack_atk_rate)/100;}break;default:
wd.damage += battle_calc_cardfix(BF_WEAPON, src, target, battle_skill_get_damage_properties(skill_id, wd.miscflag), right_element, left_element, wd.damage,2, wd.flag);if( is_attack_left_handed(src, skill_id ))
wd.damage2 += battle_calc_cardfix(BF_WEAPON, src, target, battle_skill_get_damage_properties(skill_id, wd.miscflag), right_element, left_element, wd.damage2,3, wd.flag);break;}#endif}if(tsd){// Card Fix for target (tsd), 2 is not added to the "left" flag meaning "target cards only"switch(skill_id){#ifdef RENEWAL
case NJ_ISSEN:case GS_MAGICALBULLET:case ASC_BREAKER:case CR_ACIDDEMONSTRATION:case GN_FIRE_EXPANSION_ACID:#endifcase SO_VARETYR_SPEAR:break;//These skills will do a card fix laterdefault:
wd.damage += battle_calc_cardfix(BF_WEAPON, src, target, battle_skill_get_damage_properties(skill_id, wd.miscflag), right_element, left_element, wd.damage,0, wd.flag);if(is_attack_left_handed(src, skill_id))
wd.damage2 += battle_calc_cardfix(BF_WEAPON, src, target, battle_skill_get_damage_properties(skill_id, wd.miscflag), right_element, left_element, wd.damage2,1, wd.flag);break;}}#ifdef RENEWAL
// forced to neutral skills [helvetica]// skills forced to neutral gain benefits from weapon element// but final damage is considered "neutral" and resistances are applied againswitch(skill_id){case MC_CARTREVOLUTION:case MO_INVESTIGATE:case CR_ACIDDEMONSTRATION:case SR_GATEOFHELL:case GN_FIRE_EXPANSION_ACID:case KO_BAKURETSU:// Forced to neutral element
wd.damage = battle_attr_fix(src, target, wd.damage, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);break;case CR_SHIELDBOOMERANG:case LK_SPIRALPIERCE:case ML_SPIRALPIERCE:case PA_SHIELDCHAIN:case PA_SACRIFICE:case RK_DRAGONBREATH:case RK_DRAGONBREATH_WATER:case NC_SELFDESTRUCTION:case KO_HAPPOKUNAI:{int64 tmp = wd.damage;if(sd){if(skill_id == PA_SHIELDCHAIN){
wd.damage = battle_attr_fix(src, target, wd.damage, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);if(wd.damage >0){
wd.damage = battle_attr_fix(src, target, tmp, right_element, tstatus->def_ele, tstatus->ele_lv);if(!wd.damage)
wd.damage = battle_attr_fix(src, target, tmp, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);}}elseif(skill_id == KO_HAPPOKUNAI){
wd.damage = battle_attr_fix(src, target, wd.damage,(sd->bonus.arrow_ele)? sd->bonus.arrow_ele : ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);if(wd.damage >0){
wd.damage = battle_attr_fix(src, target, tmp, right_element, tstatus->def_ele, tstatus->ele_lv);if(!wd.damage)
wd.damage = battle_attr_fix(src, target, tmp,(sd->bonus.arrow_ele)? sd->bonus.arrow_ele : ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);}}else
wd.damage = battle_attr_fix(src, target, wd.damage, right_element, tstatus->def_ele, tstatus->ele_lv);}}break;case GN_CARTCANNON:// Cart Cannon gets forced to element of cannon ball (neutral or holy/shadow/ghost)
wd.damage = battle_attr_fix(src, target, wd.damage,(sd && sd->bonus.arrow_ele)? sd->bonus.arrow_ele : ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);break;}// perform multihit calculations
DAMAGE_DIV_FIX_RENEWAL(wd, wd.div_);#endif// only do 1 dmg to plant, no need to calculate restif(infdef)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, skill_id);
wd = battle_calc_attack_left_right_hands(wd, src, target, skill_id, skill_lv);switch(skill_id){#ifdef RENEWAL
case NJ_ISSEN:case GS_MAGICALBULLET:case ASC_BREAKER:case CR_ACIDDEMONSTRATION:case GN_FIRE_EXPANSION_ACID:#endifcase SO_VARETYR_SPEAR:return wd;//These skills will do a GVG fix laterdefault:
wd = battle_calc_attack_gvg_bg(wd, src, target, skill_id, skill_lv);break;}
wd = battle_calc_weapon_final_atk_modifiers(wd, src, target, skill_id, skill_lv);
battle_absorb_damage(target,&wd);
battle_do_reflect(BF_WEAPON,&wd, src, target, skill_id, skill_lv);//WIP [lighta]return wd;}......enum damage_lv battle_weapon_attack(struct block_list* src,struct block_list* target,unsignedint tick,int flag){struct map_session_data *sd = NULL,*tsd = NULL;struct status_data *sstatus,*tstatus;struct status_change *sc,*tsc;int64 damage;int skillv;structDamage wd;bool vanish_damage =false;
nullpo_retr(ATK_NONE, src);
nullpo_retr(ATK_NONE, target);if(src->prev == NULL || target->prev == NULL)return ATK_NONE;
sd = BL_CAST(BL_PC, src);
tsd = BL_CAST(BL_PC, target);
sstatus = status_get_status_data(src);
tstatus = status_get_status_data(target);
sc = status_get_sc(src);
tsc = status_get_sc(target);if(sc &&!sc->count)//Avoid sc checks when there's none to check for. [Skotlex]
sc = NULL;if(tsc &&!tsc->count)
tsc = NULL;if(sd){
sd->state.arrow_atk =(sd->status.weapon == W_BOW ||(sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE));if(sd->state.arrow_atk){short index = sd->equip_index[EQI_AMMO];if(index <0){if(sd->weapontype1 > W_KATAR && sd->weapontype1 < W_HUUMA)
clif_skill_fail(sd,0,USESKILL_FAIL_NEED_MORE_BULLET,0);else
clif_arrow_fail(sd,0);return ATK_NONE;}//Ammo check by Ishizu-chanif(sd->inventory_data[index]){switch(sd->status.weapon){case W_BOW:if(sd->inventory_data[index]->look != A_ARROW){
clif_arrow_fail(sd,0);return ATK_NONE;}break;case W_REVOLVER:case W_RIFLE:case W_GATLING:case W_SHOTGUN:if(sd->inventory_data[index]->look != A_BULLET){
clif_skill_fail(sd,0,USESKILL_FAIL_NEED_MORE_BULLET,0);return ATK_NONE;}break;case W_GRENADE:if(sd->inventory_data[index]->look != A_GRENADE){
clif_skill_fail(sd,0,USESKILL_FAIL_NEED_MORE_BULLET,0);return ATK_NONE;}break;}}}}if(sc && sc->count){if(sc->data[SC_CLOAKING]&&!(sc->data[SC_CLOAKING]->val4 &2))
status_change_end(src, SC_CLOAKING, INVALID_TIMER);elseif(sc->data[SC_CLOAKINGEXCEED]&&!(sc->data[SC_CLOAKINGEXCEED]->val4 &2))
status_change_end(src, SC_CLOAKINGEXCEED, INVALID_TIMER);}if(tsc && tsc->data[SC_AUTOCOUNTER]&& status_check_skilluse(target, src, KN_AUTOCOUNTER,1)){uint8 dir = map_calc_dir(target,src->x,src->y);int t_dir = unit_getdir(target);int dist = distance_bl(src, target);if(dist <=0||(!map_check_dir(dir,t_dir)&& dist <= tstatus->rhw.range+1)){uint16 skill_lv = tsc->data[SC_AUTOCOUNTER]->val1;
clif_skillcastcancel(target);//Remove the casting bar. [Skotlex]
clif_damage(src, target, tick, sstatus->amotion,1,0,1, DMG_NORMAL,0,false);//Display MISS.
status_change_end(target, SC_AUTOCOUNTER, INVALID_TIMER);
skill_attack(BF_WEAPON,target,target,src,KN_AUTOCOUNTER,skill_lv,tick,0);return ATK_BLOCK;}}if( tsc && tsc->data[SC_BLADESTOP_WAIT]&& status_get_class_(src)!= CLASS_BOSS &&(src->type == BL_PC || tsd == NULL || distance_bl(src, target)<=(tsd->status.weapon == W_FIST ?1:2))){uint16 skill_lv = tsc->data[SC_BLADESTOP_WAIT]->val1;int duration = skill_get_time2(MO_BLADESTOP,skill_lv);
status_change_end(target, SC_BLADESTOP_WAIT, INVALID_TIMER);if(sc_start4(src,src, SC_BLADESTOP,100, sd?pc_checkskill(sd, MO_BLADESTOP):5,0,0, target->id, duration)){//Target locked.
clif_damage(src, target, tick, sstatus->amotion,1,0,1, DMG_NORMAL,0,false);//Display MISS.
clif_bladestop(target, src->id,1);
sc_start4(src,target, SC_BLADESTOP,100, skill_lv,0,0, src->id, duration);return ATK_BLOCK;}}if(sd &&(skillv = pc_checkskill(sd,MO_TRIPLEATTACK))>0){int triple_rate=30- skillv;//Base Rateif(sc && sc->data[SC_SKILLRATE_UP]&& sc->data[SC_SKILLRATE_UP]->val1 == MO_TRIPLEATTACK){
triple_rate+= triple_rate*(sc->data[SC_SKILLRATE_UP]->val2)/100;
status_change_end(src, SC_SKILLRATE_UP, INVALID_TIMER);}if(rnd()%100< triple_rate){//Need to apply canact_tick here because it doesn't go through skill_castend_id
sd->ud.canact_tick = max(tick + skill_delayfix(src, MO_TRIPLEATTACK, skillv), sd->ud.canact_tick);if( skill_attack(BF_WEAPON,src,src,target,MO_TRIPLEATTACK,skillv,tick,0))return ATK_DEF;return ATK_MISS;}}if(sc){if(sc->data[SC_SACRIFICE]){uint16 skill_lv = sc->data[SC_SACRIFICE]->val1;
damage_lv ret_val;if(--sc->data[SC_SACRIFICE]->val2 <=0)
status_change_end(src, SC_SACRIFICE, INVALID_TIMER);/**
* We need to calculate the DMG before the hp reduction, because it can kill the source.
* For further information: bugreport:4950
*/
ret_val =(damage_lv)skill_attack(BF_WEAPON,src,src,target,PA_SACRIFICE,skill_lv,tick,0);
status_zap(src, sstatus->max_hp*9/100,0);//Damage to self is always 9%if( ret_val == ATK_NONE )return ATK_MISS;return ret_val;}if(sc->data[SC_MAGICALATTACK]){if( skill_attack(BF_MAGIC,src,src,target,NPC_MAGICALATTACK,sc->data[SC_MAGICALATTACK]->val1,tick,0))return ATK_DEF;return ATK_MISS;}if( sc->data[SC_GT_ENERGYGAIN]){int spheres =5;if( sc->data[SC_RAISINGDRAGON])
spheres += sc->data[SC_RAISINGDRAGON]->val1;if( sd && rnd()%100< sc->data[SC_GT_ENERGYGAIN]->val2 )
pc_addspiritball(sd, skill_get_time2(SR_GENTLETOUCH_ENERGYGAIN, sc->data[SC_GT_ENERGYGAIN]->val1), spheres);}}if( tsc && tsc->data[SC_GT_ENERGYGAIN]){int spheres =5;if( tsc->data[SC_RAISINGDRAGON])
spheres += tsc->data[SC_RAISINGDRAGON]->val1;if( tsd && rnd()%100< tsc->data[SC_GT_ENERGYGAIN]->val2 )
pc_addspiritball(tsd, skill_get_time2(SR_GENTLETOUCH_ENERGYGAIN, tsc->data[SC_GT_ENERGYGAIN]->val1), spheres);}if(tsc && tsc->data[SC_MTF_MLEATKED]&& rnd()%100< tsc->data[SC_MTF_MLEATKED]->val2)
clif_skill_nodamage(target, target, SM_ENDURE, tsc->data[SC_MTF_MLEATKED]->val1, sc_start(src, target, SC_ENDURE,100, tsc->data[SC_MTF_MLEATKED]->val1, skill_get_time(SM_ENDURE, tsc->data[SC_MTF_MLEATKED]->val1)));if(tsc && tsc->data[SC_KAAHI]&& tstatus->hp < tstatus->max_hp && status_charge(target,0, tsc->data[SC_KAAHI]->val3)){int hp_heal = tstatus->max_hp - tstatus->hp;if(hp_heal > tsc->data[SC_KAAHI]->val2)
hp_heal = tsc->data[SC_KAAHI]->val2;if(hp_heal)
status_heal(target, hp_heal,0,2);}
wd = battle_calc_attack(BF_WEAPON, src, target,0,0, flag);
wd.isspdamage =false;// Default normal attacks to non-SP Damage attack until battle_vanish is determinedif(sd && wd.damage + wd.damage2 >0)
vanish_damage = battle_vanish(sd, target,&wd);if( sc && sc->count ){if(sc->data[SC_EXEEDBREAK]){if(!is_infinite_defense(target, wd.flag)&&!vanish_damage)
wd.damage *= sc->data[SC_EXEEDBREAK]->val2 /100;
status_change_end(src, SC_EXEEDBREAK, INVALID_TIMER);}if( sc->data[SC_SPELLFIST]){if(--(sc->data[SC_SPELLFIST]->val1)>=0&&!vanish_damage ){if(!is_infinite_defense(target, wd.flag)){structDamage ad = battle_calc_attack(BF_MAGIC, src, target, sc->data[SC_SPELLFIST]->val3, sc->data[SC_SPELLFIST]->val4, flag | BF_SHORT);
wd.damage = ad.damage;
DAMAGE_DIV_FIX(wd.damage, wd.div_);// Double the damage for multiple hits.}else{
wd.damage =1;
DAMAGE_DIV_FIX(wd.damage, wd.div_);}}else
status_change_end(src,SC_SPELLFIST,INVALID_TIMER);}if(sc->data[SC_GIANTGROWTH]&&(wd.flag&BF_SHORT)&& rnd()%100< sc->data[SC_GIANTGROWTH]->val2 &&!is_infinite_defense(target, wd.flag)&&!vanish_damage){
wd.damage <<=1;// Double Damageif(!sc->data[SC_CRUSHSTRIKE]){// Increase damage again if Crush Strike is not activeif(map_flag_vs(src->m))// Only half of the 2.5x increase on versus-type maps
wd.damage += wd.damage *125/100;else
wd.damage += wd.damage *250/100;}}if( sd && battle_config.arrow_decrement && sc->data[SC_FEARBREEZE]&& sc->data[SC_FEARBREEZE]->val4 >0){short idx = sd->equip_index[EQI_AMMO];if(idx >=0&& sd->inventory.u.items_inventory[idx].amount >= sc->data[SC_FEARBREEZE]->val4){
pc_delitem(sd,idx,sc->data[SC_FEARBREEZE]->val4,0,1,LOG_TYPE_CONSUME);
sc->data[SC_FEARBREEZE]->val4 =0;}}}if(sd && sd->state.arrow_atk)//Consume arrow.
battle_consume_ammo(sd,0,0);
damage = wd.damage + wd.damage2;if( damage >0&& src != target ){if( sc && sc->data[SC_DUPLELIGHT]&&(wd.flag&BF_SHORT)&& rnd()%100<=10+2*sc->data[SC_DUPLELIGHT]->val1 ){// Activates it only from melee damageuint16 skill_id;if( rnd()%2==1)
skill_id = AB_DUPLELIGHT_MELEE;else
skill_id = AB_DUPLELIGHT_MAGIC;
skill_attack(skill_get_type(skill_id), src, src, target, skill_id, sc->data[SC_DUPLELIGHT]->val1, tick, SD_LEVEL);}}
wd.dmotion = clif_damage(src, target, tick, wd.amotion, wd.dmotion, wd.damage, wd.div_ , wd.type, wd.damage2, wd.isspdamage);if(sd && sd->bonus.splash_range >0&& damage >0)
skill_castend_damage_id(src, target,0,1, tick,0);if( target->type == BL_SKILL && damage >0){
TBL_SKILL *su =(TBL_SKILL*)target;if(su && su->group){if(su->group->skill_id == HT_BLASTMINE)
skill_blown(src, target,3,-1, BLOWN_NONE);if(su->group->skill_id == GN_WALLOFTHORN){if(--su->val2 <=0)
skill_delunit(su);}}}
map_freeblock_lock();if(!(tsc && tsc->data[SC_DEVOTION])&&!vanish_damage && skill_check_shadowform(target, damage, wd.div_)){if(!status_isdead(target))
skill_additional_effect(src, target,0,0, wd.flag, wd.dmg_lv, tick);if( wd.dmg_lv > ATK_BLOCK )
skill_counter_additional_effect(src, target,0,0, wd.flag, tick);}else
battle_delay_damage(tick, wd.amotion, src, target, wd.flag,0,0, damage, wd.dmg_lv, wd.dmotion,true, wd.isspdamage);if( tsc ){if( tsc->data[SC_DEVOTION]){struct status_change_entry *sce = tsc->data[SC_DEVOTION];struct block_list *d_bl = map_id2bl(sce->val1);if( d_bl &&((d_bl->type == BL_MER &&((TBL_MER*)d_bl)->master &&((TBL_MER*)d_bl)->master->bl.id == target->id)||(d_bl->type == BL_PC &&((TBL_PC*)d_bl)->devotion[sce->val2]== target->id))&& check_distance_bl(target, d_bl, sce->val3)){
clif_damage(d_bl, d_bl, gettick(),0,0, damage,0, DMG_NORMAL,0,false);
status_fix_damage(NULL, d_bl, damage,0);}else
status_change_end(target, SC_DEVOTION, INVALID_TIMER);}if(target->type == BL_PC &&(wd.flag&BF_SHORT)&& tsc->data[SC_CIRCLE_OF_FIRE_OPTION]){struct elemental_data *ed =((TBL_PC*)target)->ed;if(ed){
clif_skill_damage(&ed->bl, target, tick, status_get_amotion(src),0,-30000,1, EL_CIRCLE_OF_FIRE, tsc->data[SC_CIRCLE_OF_FIRE_OPTION]->val1, DMG_SKILL);
skill_attack(BF_WEAPON,&ed->bl,&ed->bl,src,EL_CIRCLE_OF_FIRE,tsc->data[SC_CIRCLE_OF_FIRE_OPTION]->val1,tick,wd.flag);}}if(tsc->data[SC_WATER_SCREEN_OPTION]){struct block_list *e_bl = map_id2bl(tsc->data[SC_WATER_SCREEN_OPTION]->val1);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);}}}if(sc && sc->data[SC_AUTOSPELL]&& rnd()%100< sc->data[SC_AUTOSPELL]->val4){int sp =0;uint16 skill_id = sc->data[SC_AUTOSPELL]->val2;uint16 skill_lv = sc->data[SC_AUTOSPELL]->val3;int i = rnd()%100;if(sc->data[SC_SPIRIT]&& sc->data[SC_SPIRIT]->val2 == SL_SAGE)
i =0;//Max chance, no skill_lv reduction. [Skotlex]//reduction only for skill_lv > 1if(skill_lv >1){if(i >=50) skill_lv /=2;elseif(i >=15) skill_lv--;}
sp = skill_get_sp(skill_id,skill_lv)*2/3;if(status_charge(src,0, sp)){struct unit_data *ud = unit_bl2ud(src);switch(skill_get_casttype(skill_id)){case CAST_GROUND:
skill_castend_pos2(src, target->x, target->y, skill_id, skill_lv, tick, flag);break;case CAST_NODAMAGE:
skill_castend_nodamage_id(src, target, skill_id, skill_lv, tick, flag);break;case CAST_DAMAGE:
skill_castend_damage_id(src, target, skill_id, skill_lv, tick, flag);break;}if(ud){int autospell_tick = skill_delayfix(src, skill_id, skill_lv);if(DIFF_TICK(ud->canact_tick, tick + autospell_tick)<0){
ud->canact_tick = max(tick + autospell_tick, ud->canact_tick);if(battle_config.display_status_timers && sd)
clif_status_change(src, SI_ACTIONDELAY,1, autospell_tick,0,0,0);}}}}if(sd){uint16 r_skill =0, sk_idx =0;if( wd.flag&BF_SHORT && sc && sc->data[SC__AUTOSHADOWSPELL]&& rnd()%100< sc->data[SC__AUTOSHADOWSPELL]->val3 &&(r_skill =(uint16)sc->data[SC__AUTOSHADOWSPELL]->val1)&&(sk_idx = skill_get_index(r_skill))&&
sd->status.skill[sk_idx].id !=0&& sd->status.skill[sk_idx].flag == SKILL_FLAG_PLAGIARIZED ){int r_lv = sc->data[SC__AUTOSHADOWSPELL]->val2;if(r_skill != AL_HOLYLIGHT && r_skill != PR_MAGNUS){int type;if((type = skill_get_casttype(r_skill))== CAST_GROUND ){int maxcount =0;if(!(BL_PC&battle_config.skill_reiteration)&&
skill_get_unit_flag(r_skill)&UF_NOREITERATION )
type =-1;if( BL_PC&battle_config.skill_nofootset &&
skill_get_unit_flag(r_skill)&UF_NOFOOTSET )
type =-1;if( BL_PC&battle_config.land_skill_limit &&(maxcount = skill_get_maxcount(r_skill, r_lv))>0){int v;for(v=0;v<MAX_SKILLUNITGROUP && sd->ud.skillunit[v]&& maxcount;v++){if(sd->ud.skillunit[v]->skill_id == r_skill)
maxcount--;}if( maxcount ==0)
type =-1;}if( type != CAST_GROUND ){
clif_skill_fail(sd,r_skill,USESKILL_FAIL_LEVEL,0);
map_freeblock_unlock();return wd.dmg_lv;}}if(sd->state.autocast ==0){
sd->state.autocast =1;
skill_consume_requirement(sd, r_skill, r_lv,3);switch(type){case CAST_GROUND:
skill_castend_pos2(src, target->x, target->y, r_skill, r_lv, tick, flag);break;case CAST_NODAMAGE:
skill_castend_nodamage_id(src, target, r_skill, r_lv, tick, flag);break;case CAST_DAMAGE:
skill_castend_damage_id(src, target, r_skill, r_lv, tick, flag);break;}}
sd->state.autocast =0;
sd->ud.canact_tick = max(tick + skill_delayfix(src, r_skill, r_lv), sd->ud.canact_tick);
clif_status_change(src, SI_ACTIONDELAY,1, skill_delayfix(src, r_skill, r_lv),0,0,1);}}if(wd.flag & BF_WEAPON && src != target && damage >0){if(battle_config.left_cardfix_to_right)
battle_drain(sd, target, wd.damage, wd.damage, tstatus->race, tstatus->class_);else
battle_drain(sd, target, wd.damage, wd.damage2, tstatus->race, tstatus->class_);}}if(tsc){if(damage >0&& tsc->data[SC_POISONREACT]&&(rnd()%100< tsc->data[SC_POISONREACT]->val3
|| sstatus->def_ele == ELE_POISON)&&// check_distance_bl(src, target, tstatus->rhw.range+1) && Doesn't checks range! o.O;
status_check_skilluse(target, src, TF_POISON,0)){//Poison Reactstruct status_change_entry *sce = tsc->data[SC_POISONREACT];if(sstatus->def_ele == ELE_POISON){
sce->val2 =0;
skill_attack(BF_WEAPON,target,target,src,AS_POISONREACT,sce->val1,tick,0);}else{
skill_attack(BF_WEAPON,target,target,src,TF_POISON,5, tick,0);--sce->val2;}if(sce->val2 <=0)
status_change_end(target, SC_POISONREACT, INVALID_TIMER);}}
map_freeblock_unlock();return wd.dmg_lv;}
unit.c
int unit_attack(struct block_list *src,int target_id,int continuous){struct block_list *target;struct unit_data *ud;int range;
nullpo_ret(ud = unit_bl2ud(src));
target = map_id2bl(target_id);if( target == NULL || status_isdead(target)){
unit_unattackable(src);return1;}if( src->type == BL_PC ){
TBL_PC* sd =(TBL_PC*)src;if( target->type == BL_NPC ){// Monster npcs [Valaris]
npc_click(sd,(TBL_NPC*)target);// Submitted by leinsirk10 [Celest]return0;}if( pc_is90overweight(sd)|| pc_isridingwug(sd)){// Overweight or mounted on warg - stop attacking
unit_stop_attack(src);return0;}if(!pc_can_attack(sd, target_id)){
unit_stop_attack(src);return0;}}if( battle_check_target(src,target,BCT_ENEMY)<=0||!status_check_skilluse(src, target,0,0)){
unit_unattackable(src);return1;}
ud->state.attack_continue =(continuous&1)?1:0;
ud->state.step_attack =(continuous&2)?1:0;
unit_set_target(ud, target_id);
range = status_get_range(src);if(continuous)// If you're to attack continously, set to auto-chase character
ud->chaserange = range;// Just change target/type. [Skotlex]if(ud->attacktimer != INVALID_TIMER)return0;// New action request received, delete previous action request if not executed yetif(ud->stepaction || ud->steptimer != INVALID_TIMER)
unit_stop_stepaction(src);// Remember the attack request from the client while walking to the next cellif(src->type == BL_PC && ud->walktimer != INVALID_TIMER &&!battle_check_range(src, target, range-1)){
ud->stepaction =true;
ud->target_to = ud->target;
ud->stepskill_id =0;
ud->stepskill_lv =0;return0;// Attacking will be handled by unit_walktoxy_timer in this case}if(DIFF_TICK(ud->attackabletime, gettick())>0)// Do attack next time it is possible. [Skotlex]
ud->attacktimer=add_timer(ud->attackabletime,unit_attack_timer,src->id,0);else// Attack NOW.
unit_attack_timer(INVALID_TIMER, gettick(), src->id,0);return0;}
Question
Rebel
battle.c
unit.c
timer.c
Git Hash: 5fda4f0f65d3a239becb9f44df38a7cfad9a6160
our src has modification that im not aware of.
Can anyone help me to fix this.. I tried looking at it and comparing every line to the recent commit but Im having a hard time fixing it..
Edited by RebelAdded battle.c, unit.c, timer.c, git hash
Link to comment
Share on other sites
2 answers to this question
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.