Jump to content
  • 0

gdb Mapserver Crash Dump


Rebel

Question


  • Group:  Members
  • Topic Count:  68
  • Topics Per Day:  0.02
  • Content Count:  436
  • Reputation:   31
  • Joined:  02/19/12
  • Last Seen:  

[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_PC
	short cardfix = 1000;
	enum e_classAE s_class, ///< Attacker class
		t_class; ///< Target class
	enum e_race2 s_race2, /// Attacker Race2
		t_race2; ///< Target Race2
	enum e_element s_defele; ///< Attacker Element (not a weapon or skill element!)
	struct status_data *sstatus, ///< Attacker status data
		*tstatus; ///< Target status data
	int64 original_damage;
	int i;

	if( !damage )
		return 0;

	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 bonuses
			if( 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 bonuses
			if( tsd && !(nk&NK_NO_CARDFIX_DEF) ) {
				cardfix = 1000; // reset var for target

				if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonuses
					int 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 bonuses
			if( 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 bonuses
						int 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 attack
					int skill = 0;

					// Calculates each right & left hand weapon bonuses separatedly
					if( !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 bonuses
							int 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 bonuses
								int 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 unity
					else {
						//! 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 bonuses
							int 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;
#endif
				if (left&1) {
					APPLY_CARDFIX(damage, cardfix_);
				} else {
					APPLY_CARDFIX(damage, cardfix);
				}
			}
			// Affected by target DEF bonuses
			else if( tsd && !(nk&NK_NO_CARDFIX_DEF) && !(left&2) ) {
				if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonuses
					int 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 bonuses
			if( tsd && !(nk&NK_NO_CARDFIX_DEF) ) {
				if( !(nk&NK_NO_ELEFIX) ) { // Affected by Element modifier bonuses
					int 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);
}

......

static struct Damage 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);
	struct Damage 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 =
#endif
	0;

	wd.dmg_lv=ATK_DEF;	//This assumption simplifies the assignation later

	if(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 through
			case 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;
}

......

static struct Damage 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;
	struct Damage 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 Dodge
	if ((!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 hit
	if(!is_attack_hitting(wd, src, target, skill_id, skill_lv, true))
		wd.dmg_lv = ATK_FLEE;
	else if(!(infdef = is_infinite_defense(target, wd.flag))) { //no need for math against plants
		int64 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 Crasher
			struct 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 bonuses
		if( 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);
#endif

		if (wd.damage + wd.damage2) { //Check if attack ignores DEF
			if(!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;
	}
#endif

	switch (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);
#endif
		if( 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:
#endif
			case SO_VARETYR_SPEAR:
				break; //These skills will do a card fix later
			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, 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 again
	switch (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);
						}
					} else if (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 rest
	if(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:
#endif
		case SO_VARETYR_SPEAR:
			return wd; //These skills will do a GVG fix later
		default:
			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, unsigned int 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;
	struct Damage 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-chan
			if (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);
		else if (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 Rate
		if (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 determined

	if (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)) {
					struct Damage 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 Damage
			if (!sc->data[SC_CRUSHSTRIKE]) { // Increase damage again if Crush Strike is not active
				if (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 damage
			uint16 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 > 1
		if (skill_lv > 1) {
			if (i >= 50) skill_lv /= 2;
			else if (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 React
			struct 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);
		return 1;
	}

	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]
			return 0;
		}

		if( pc_is90overweight(sd) || pc_isridingwug(sd) ) { // Overweight or mounted on warg - stop attacking
			unit_stop_attack(src);
			return 0;
		}

		if( !pc_can_attack(sd, target_id) ) {
			unit_stop_attack(src);
			return 0;
		}
	}

	if( battle_check_target(src,target,BCT_ENEMY) <= 0 || !status_check_skilluse(src, target, 0, 0) ) {
		unit_unattackable(src);
		return 1;
	}

	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)
		return 0;

	// New action request received, delete previous action request if not executed yet
	if(ud->stepaction || ud->steptimer != INVALID_TIMER)
		unit_stop_stepaction(src);
	// Remember the attack request from the client while walking to the next cell
	if(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;
		return 0; // 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);

	return 0;
}

timer.c

unsigned long get_uptime(void)
{
	return (unsigned long)difftime(time(NULL), start_time);
}

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 Rebel
Added battle.c, unit.c, timer.c, git hash
Link to comment
Share on other sites

2 answers to this question

Recommended Posts

  • 0

  • Group:  Members
  • Topic Count:  99
  • Topics Per Day:  0.02
  • Content Count:  626
  • Reputation:   94
  • Joined:  05/11/12
  • Last Seen:  

Git hash? rathena latest?

Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  68
  • Topics Per Day:  0.02
  • Content Count:  436
  • Reputation:   31
  • Joined:  02/19/12
  • Last Seen:  

15 minutes ago, Kakaroto said:

Git hash? rathena latest?

Im using an old git hash.. and my battle.c is also modified. But I can send my battle.c if it can help.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...