PageRenderTime 72ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

/src/map/battle.c

https://gitlab.com/evol/hercules
C | 7664 lines | 6652 code | 592 blank | 420 comment | 2604 complexity | e182503114f24bba27284fff9fc670df MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. /**
  2. * This file is part of Hercules.
  3. * http://herc.ws - http://github.com/HerculesWS/Hercules
  4. *
  5. * Copyright (C) 2012-2016 Hercules Dev Team
  6. * Copyright (C) Athena Dev Teams
  7. *
  8. * Hercules is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. */
  21. #define HERCULES_CORE
  22. #include "config/core.h" // CELL_NOSTACK, CIRCULAR_AREA, CONSOLE_INPUT, HMAP_ZONE_DAMAGE_CAP_TYPE, OFFICIAL_WALKPATH, RENEWAL, RENEWAL_ASPD, RENEWAL_CAST, RENEWAL_DROP, RENEWAL_EDP, RENEWAL_EXP, RENEWAL_LVDMG, RE_LVL_DMOD(), RE_LVL_MDMOD(), RE_LVL_TMDMOD(), RE_SKILL_REDUCTION(), SCRIPT_CALLFUNC_CHECK, SECURE_NPCTIMEOUT, STATS_OPT_OUT
  23. #include "battle.h"
  24. #include "map/battleground.h"
  25. #include "map/chrif.h"
  26. #include "map/clif.h"
  27. #include "map/elemental.h"
  28. #include "map/guild.h"
  29. #include "map/homunculus.h"
  30. #include "map/itemdb.h"
  31. #include "map/map.h"
  32. #include "map/mercenary.h"
  33. #include "map/mob.h"
  34. #include "map/party.h"
  35. #include "map/path.h"
  36. #include "map/pc.h"
  37. #include "map/pet.h"
  38. #include "map/skill.h"
  39. #include "map/status.h"
  40. #include "common/HPM.h"
  41. #include "common/cbasetypes.h"
  42. #include "common/ers.h"
  43. #include "common/memmgr.h"
  44. #include "common/nullpo.h"
  45. #include "common/random.h"
  46. #include "common/showmsg.h"
  47. #include "common/socket.h"
  48. #include "common/strlib.h"
  49. #include "common/sysinfo.h"
  50. #include "common/timer.h"
  51. #include "common/utils.h"
  52. #include <math.h>
  53. #include <stdio.h>
  54. #include <stdlib.h>
  55. #include <string.h>
  56. struct Battle_Config battle_config;
  57. struct battle_interface battle_s;
  58. struct battle_interface *battle;
  59. /**
  60. * Returns the current/last skill in use by this bl.
  61. *
  62. * @param bl The bl to check.
  63. * @return The current/last skill ID.
  64. */
  65. int battle_getcurrentskill(struct block_list *bl)
  66. {
  67. const struct unit_data *ud;
  68. nullpo_ret(bl);
  69. if (bl->type == BL_SKILL) {
  70. const struct skill_unit *su = BL_UCCAST(BL_SKILL, bl);
  71. if (su->group == NULL)
  72. return 0;
  73. return su->group->skill_id;
  74. }
  75. ud = unit->bl2ud(bl);
  76. if (ud == NULL)
  77. return 0;
  78. return ud->skill_id;
  79. }
  80. /*==========================================
  81. * Get random targeting enemy
  82. *------------------------------------------*/
  83. int battle_gettargeted_sub(struct block_list *bl, va_list ap) {
  84. struct block_list **bl_list;
  85. struct unit_data *ud;
  86. int target_id;
  87. int *c;
  88. nullpo_ret(bl);
  89. bl_list = va_arg(ap, struct block_list **);
  90. c = va_arg(ap, int *);
  91. target_id = va_arg(ap, int);
  92. if (bl->id == target_id)
  93. return 0;
  94. if (*c >= 24)
  95. return 0;
  96. if (!(ud = unit->bl2ud(bl)))
  97. return 0;
  98. if (ud->target == target_id || ud->skilltarget == target_id) {
  99. bl_list[(*c)++] = bl;
  100. return 1;
  101. }
  102. return 0;
  103. }
  104. struct block_list* battle_gettargeted(struct block_list *target) {
  105. struct block_list *bl_list[24];
  106. int c = 0;
  107. nullpo_retr(NULL, target);
  108. memset(bl_list, 0, sizeof(bl_list));
  109. map->foreachinrange(battle->get_targeted_sub, target, AREA_SIZE, BL_CHAR, bl_list, &c, target->id);
  110. if ( c == 0 )
  111. return NULL;
  112. if( c > 24 )
  113. c = 24;
  114. return bl_list[rnd()%c];
  115. }
  116. //Returns the id of the current targeted character of the passed bl. [Skotlex]
  117. int battle_gettarget(struct block_list* bl) {
  118. nullpo_ret(bl);
  119. switch (bl->type) {
  120. case BL_PC: return BL_UCCAST(BL_PC, bl)->ud.target;
  121. case BL_MOB: return BL_UCCAST(BL_MOB, bl)->target_id;
  122. case BL_PET: return BL_UCCAST(BL_PET, bl)->target_id;
  123. case BL_HOM: return BL_UCCAST(BL_HOM, bl)->ud.target;
  124. case BL_MER: return BL_UCCAST(BL_MER, bl)->ud.target;
  125. case BL_ELEM: return BL_UCCAST(BL_ELEM, bl)->ud.target;
  126. }
  127. return 0;
  128. }
  129. int battle_getenemy_sub(struct block_list *bl, va_list ap) {
  130. struct block_list **bl_list;
  131. struct block_list *target;
  132. int *c;
  133. nullpo_ret(bl);
  134. bl_list = va_arg(ap, struct block_list **);
  135. c = va_arg(ap, int *);
  136. target = va_arg(ap, struct block_list *);
  137. if (bl->id == target->id)
  138. return 0;
  139. if (*c >= 24)
  140. return 0;
  141. if (status->isdead(bl))
  142. return 0;
  143. if (battle->check_target(target, bl, BCT_ENEMY) > 0) {
  144. bl_list[(*c)++] = bl;
  145. return 1;
  146. }
  147. return 0;
  148. }
  149. // Picks a random enemy of the given type (BL_PC, BL_CHAR, etc) within the range given. [Skotlex]
  150. struct block_list* battle_getenemy(struct block_list *target, int type, int range) {
  151. struct block_list *bl_list[24];
  152. int c = 0;
  153. nullpo_retr(NULL, target);
  154. memset(bl_list, 0, sizeof(bl_list));
  155. map->foreachinrange(battle->get_enemy_sub, target, range, type, bl_list, &c, target);
  156. if ( c == 0 )
  157. return NULL;
  158. if( c > 24 )
  159. c = 24;
  160. return bl_list[rnd()%c];
  161. }
  162. int battle_getenemyarea_sub(struct block_list *bl, va_list ap) {
  163. struct block_list **bl_list, *src;
  164. int *c, ignore_id;
  165. nullpo_ret(bl);
  166. bl_list = va_arg(ap, struct block_list **);
  167. nullpo_ret(bl_list);
  168. c = va_arg(ap, int *);
  169. nullpo_ret(c);
  170. src = va_arg(ap, struct block_list *);
  171. ignore_id = va_arg(ap, int);
  172. if( bl->id == src->id || bl->id == ignore_id )
  173. return 0; // Ignores Caster and a possible pre-target
  174. if( *c >= 23 )
  175. return 0;
  176. if( status->isdead(bl) )
  177. return 0;
  178. if( battle->check_target(src, bl, BCT_ENEMY) > 0 ) {// Is Enemy!...
  179. bl_list[(*c)++] = bl;
  180. return 1;
  181. }
  182. return 0;
  183. }
  184. // Pick a random enemy
  185. struct block_list* battle_getenemyarea(struct block_list *src, int x, int y, int range, int type, int ignore_id) {
  186. struct block_list *bl_list[24];
  187. int c = 0;
  188. nullpo_retr(NULL, src);
  189. memset(bl_list, 0, sizeof(bl_list));
  190. map->foreachinarea(battle->get_enemy_area_sub, src->m, x - range, y - range, x + range, y + range, type, bl_list, &c, src, ignore_id);
  191. if( c == 0 )
  192. return NULL;
  193. if( c >= 24 )
  194. c = 23;
  195. return bl_list[rnd()%c];
  196. }
  197. int battle_delay_damage_sub(int tid, int64 tick, int id, intptr_t data) {
  198. struct delay_damage *dat = (struct delay_damage *)data;
  199. if ( dat ) {
  200. struct block_list *src = map->id2bl(dat->src_id);
  201. struct map_session_data *sd = BL_CAST(BL_PC, src);
  202. struct block_list *target = map->id2bl(dat->target_id);
  203. if (target != NULL && !status->isdead(target)) {
  204. //Check to see if you haven't teleported. [Skotlex]
  205. if (src != NULL && (
  206. battle_config.fix_warp_hit_delay_abuse ?
  207. (dat->skill_id == MO_EXTREMITYFIST || target->m != src->m || check_distance_bl(src, target, dat->distance))
  208. :
  209. ((target->type != BL_PC || BL_UCAST(BL_PC, target)->invincible_timer == INVALID_TIMER)
  210. && (dat->skill_id == MO_EXTREMITYFIST || (target->m == src->m && check_distance_bl(src, target, dat->distance))))
  211. )) {
  212. map->freeblock_lock();
  213. status_fix_damage(src, target, dat->damage, dat->delay);
  214. if (dat->attack_type && !status->isdead(target) && dat->additional_effects)
  215. skill->additional_effect(src,target,dat->skill_id,dat->skill_lv,dat->attack_type,dat->dmg_lv,tick);
  216. if (dat->dmg_lv > ATK_BLOCK && dat->attack_type)
  217. skill->counter_additional_effect(src,target,dat->skill_id,dat->skill_lv,dat->attack_type,tick);
  218. map->freeblock_unlock();
  219. } else if (src == NULL && dat->skill_id == CR_REFLECTSHIELD) {
  220. // it was monster reflected damage, and the monster died, we pass the damage to the character as expected
  221. map->freeblock_lock();
  222. status_fix_damage(target, target, dat->damage, dat->delay);
  223. map->freeblock_unlock();
  224. }
  225. }
  226. if (sd != NULL && --sd->delayed_damage == 0 && sd->state.hold_recalc) {
  227. sd->state.hold_recalc = 0;
  228. status_calc_pc(sd, SCO_FORCE);
  229. }
  230. }
  231. ers_free(battle->delay_damage_ers, dat);
  232. return 0;
  233. }
  234. int battle_delay_damage(int64 tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, uint16 skill_id, uint16 skill_lv, int64 damage, enum damage_lv dmg_lv, int ddelay, bool additional_effects) {
  235. struct delay_damage *dat;
  236. struct status_change *sc;
  237. struct block_list *d_tbl = NULL;
  238. nullpo_ret(src);
  239. nullpo_ret(target);
  240. sc = status->get_sc(target);
  241. if (sc && sc->data[SC_DEVOTION] && sc->data[SC_DEVOTION]->val1)
  242. d_tbl = map->id2bl(sc->data[SC_DEVOTION]->val1);
  243. if (d_tbl && sc && check_distance_bl(target, d_tbl, sc->data[SC_DEVOTION]->val3) && damage > 0 && skill_id != PA_PRESSURE && skill_id != CR_REFLECTSHIELD)
  244. damage = 0;
  245. if ( !battle_config.delay_battle_damage || amotion <= 1 ) {
  246. map->freeblock_lock();
  247. status_fix_damage(src, target, damage, ddelay); // We have to separate here between reflect damage and others [icescope]
  248. if( attack_type && !status->isdead(target) && additional_effects )
  249. skill->additional_effect(src, target, skill_id, skill_lv, attack_type, dmg_lv, timer->gettick());
  250. if( dmg_lv > ATK_BLOCK && attack_type )
  251. skill->counter_additional_effect(src, target, skill_id, skill_lv, attack_type, timer->gettick());
  252. map->freeblock_unlock();
  253. return 0;
  254. }
  255. dat = ers_alloc(battle->delay_damage_ers, struct delay_damage);
  256. dat->src_id = src->id;
  257. dat->target_id = target->id;
  258. dat->skill_id = skill_id;
  259. dat->skill_lv = skill_lv;
  260. dat->attack_type = attack_type;
  261. dat->damage = damage;
  262. dat->dmg_lv = dmg_lv;
  263. dat->delay = ddelay;
  264. dat->distance = distance_bl(src, target) + (battle_config.snap_dodge ? 10 : battle_config.area_size);
  265. dat->additional_effects = additional_effects;
  266. dat->src_type = src->type;
  267. if (src->type != BL_PC && amotion > 1000)
  268. amotion = 1000; //Aegis places a damage-delay cap of 1 sec to non player attacks. [Skotlex]
  269. if (src->type == BL_PC) {
  270. BL_UCAST(BL_PC, src)->delayed_damage++;
  271. }
  272. timer->add(tick+amotion, battle->delay_damage_sub, 0, (intptr_t)dat);
  273. return 0;
  274. }
  275. int battle_attr_ratio(int atk_elem,int def_type, int def_lv)
  276. {
  277. if (atk_elem < ELE_NEUTRAL || atk_elem >= ELE_MAX)
  278. return 100;
  279. if (def_type < ELE_NEUTRAL || def_type >= ELE_MAX || def_lv < 1 || def_lv > 4)
  280. return 100;
  281. return battle->attr_fix_table[def_lv-1][atk_elem][def_type];
  282. }
  283. /*==========================================
  284. * Does attribute fix modifiers.
  285. * Added passing of the chars so that the status changes can affect it. [Skotlex]
  286. * Note: Passing src/target == NULL is perfectly valid, it skips SC_ checks.
  287. *------------------------------------------*/
  288. int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 damage,int atk_elem,int def_type, int def_lv)
  289. {
  290. struct status_change *sc=NULL, *tsc=NULL;
  291. int ratio;
  292. if (src) sc = status->get_sc(src);
  293. if (target) tsc = status->get_sc(target);
  294. if (atk_elem < ELE_NEUTRAL || atk_elem >= ELE_MAX)
  295. atk_elem = rnd()%ELE_MAX;
  296. if (def_type < ELE_NEUTRAL || def_type >= ELE_MAX ||
  297. def_lv < 1 || def_lv > 4) {
  298. ShowError("battle_attr_fix: unknown attr type: atk=%d def_type=%d def_lv=%d\n",atk_elem,def_type,def_lv);
  299. return damage;
  300. }
  301. ratio = battle->attr_fix_table[def_lv-1][atk_elem][def_type];
  302. if (sc && sc->count) {
  303. if(sc->data[SC_VOLCANO] && atk_elem == ELE_FIRE)
  304. ratio += skill->enchant_eff[sc->data[SC_VOLCANO]->val1-1];
  305. if(sc->data[SC_VIOLENTGALE] && atk_elem == ELE_WIND)
  306. ratio += skill->enchant_eff[sc->data[SC_VIOLENTGALE]->val1-1];
  307. if(sc->data[SC_DELUGE] && atk_elem == ELE_WATER)
  308. ratio += skill->enchant_eff[sc->data[SC_DELUGE]->val1-1];
  309. if(sc->data[SC_FIRE_CLOAK_OPTION] && atk_elem == ELE_FIRE)
  310. damage += damage * sc->data[SC_FIRE_CLOAK_OPTION]->val2 / 100;
  311. }
  312. if( target && target->type == BL_SKILL ) {
  313. if( atk_elem == ELE_FIRE && battle->get_current_skill(target) == GN_WALLOFTHORN ) {
  314. struct skill_unit *su = BL_UCAST(BL_SKILL, target);
  315. struct skill_unit_group *sg;
  316. struct block_list *sgsrc;
  317. if(!su->alive
  318. || (sg = su->group) == NULL || sg->val3 == -1
  319. || (sgsrc = map->id2bl(sg->src_id)) == NULL || status->isdead(sgsrc)
  320. )
  321. return 0;
  322. if( sg->unit_id != UNT_FIREWALL ) {
  323. int x,y;
  324. x = sg->val3 >> 16;
  325. y = sg->val3 & 0xffff;
  326. skill->unitsetting(sgsrc,su->group->skill_id,su->group->skill_lv,x,y,1);
  327. sg->val3 = -1;
  328. sg->limit = DIFF_TICK32(timer->gettick(),sg->tick)+300;
  329. }
  330. }
  331. }
  332. if( tsc && tsc->count ) { //since an atk can only have one type let's optimize this a bit
  333. switch(atk_elem){
  334. case ELE_FIRE:
  335. if( tsc->data[SC_SPIDERWEB]) {
  336. tsc->data[SC_SPIDERWEB]->val1 = 0; // free to move now
  337. if( tsc->data[SC_SPIDERWEB]->val2-- > 0 )
  338. damage <<= 1; // double damage
  339. if( tsc->data[SC_SPIDERWEB]->val2 == 0 )
  340. status_change_end(target, SC_SPIDERWEB, INVALID_TIMER);
  341. }
  342. if( tsc->data[SC_THORNS_TRAP])
  343. status_change_end(target, SC_THORNS_TRAP, INVALID_TIMER);
  344. if( tsc->data[SC_COLD] && target->type != BL_MOB)
  345. status_change_end(target, SC_COLD, INVALID_TIMER);
  346. if( tsc->data[SC_EARTH_INSIGNIA]) damage += damage/2;
  347. if( tsc->data[SC_FIRE_CLOAK_OPTION])
  348. damage -= damage * tsc->data[SC_FIRE_CLOAK_OPTION]->val2 / 100;
  349. if( tsc->data[SC_VOLCANIC_ASH]) damage += damage/2; //150%
  350. break;
  351. case ELE_HOLY:
  352. if( tsc->data[SC_ORATIO]) ratio += tsc->data[SC_ORATIO]->val1 * 2;
  353. break;
  354. case ELE_POISON:
  355. if( tsc->data[SC_VENOMIMPRESS] && atk_elem == ELE_POISON ) ratio += tsc->data[SC_VENOMIMPRESS]->val2;
  356. break;
  357. case ELE_WIND:
  358. if( tsc->data[SC_COLD] && target->type != BL_MOB) damage += damage/2;
  359. if( tsc->data[SC_WATER_INSIGNIA]) damage += damage/2;
  360. break;
  361. case ELE_WATER:
  362. if( tsc->data[SC_FIRE_INSIGNIA]) damage += damage/2;
  363. break;
  364. case ELE_EARTH:
  365. if( tsc->data[SC_WIND_INSIGNIA]) damage += damage/2;
  366. break;
  367. }
  368. } //end tsc check
  369. if( ratio < 100 )
  370. return damage - (damage * (100 - ratio) / 100);
  371. else
  372. return damage + (damage * (ratio - 100) / 100);
  373. }
  374. //FIXME: Missing documentation for flag, flag2
  375. int64 battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, struct weapon_atk *watk, int nk, bool n_ele, short s_ele, short s_ele_, int size, int type, int flag, int flag2){ // [malufett]
  376. #ifdef RENEWAL
  377. int64 damage, eatk = 0;
  378. struct status_change *sc;
  379. struct map_session_data *sd;
  380. if( !src || !bl )
  381. return 0;
  382. sc = status->get_sc(src);
  383. sd = BL_CAST(BL_PC, src);
  384. damage = status->get_weapon_atk(src, watk, flag);
  385. if ( sd ) {
  386. if ( type == EQI_HAND_R )
  387. damage = battle->calc_sizefix(sd, damage, EQI_HAND_R, size, flag & 8);
  388. else
  389. damage = battle->calc_sizefix(sd, damage, EQI_HAND_L, size, flag & 8);
  390. if ( flag & 2 && sd->bonus.arrow_atk && skill_id != GN_CARTCANNON )
  391. damage += sd->bonus.arrow_atk;
  392. if ( sd->battle_status.equip_atk != 0 )
  393. eatk = sd->base_status.equip_atk;
  394. if ( sd->bonus.atk_rate )
  395. damage += damage * sd->bonus.atk_rate / 100;
  396. }
  397. if ( skill_id == TF_POISON )
  398. eatk += 15 * skill_lv;
  399. if ( skill_id != ASC_METEORASSAULT ) {
  400. if ( sc && sc->data[SC_SUB_WEAPONPROPERTY] ) // Temporary. [malufett]
  401. damage += damage * sc->data[SC_SUB_WEAPONPROPERTY]->val2 / 100;
  402. }
  403. if( sc && sc->count ){
  404. if( sc->data[SC_ZENKAI] && watk->ele == sc->data[SC_ZENKAI]->val2 )
  405. eatk += 200;
  406. }
  407. #ifdef RENEWAL_EDP
  408. if ( sc && sc->data[SC_EDP] && skill_id != AS_GRIMTOOTH && skill_id != AS_VENOMKNIFE && skill_id != ASC_BREAKER ) {
  409. struct status_data *tstatus;
  410. tstatus = status->get_status_data(bl);
  411. eatk += damage * 0x19 * battle->attr_fix_table[tstatus->ele_lv - 1][ELE_POISON][tstatus->def_ele] / 10000;
  412. damage += (eatk + damage) * sc->data[SC_EDP]->val3 / 100 + eatk;
  413. } else /* fall through */
  414. #endif
  415. damage += eatk;
  416. damage = battle->calc_elefix(src, bl, skill_id, skill_lv, damage, nk, n_ele, s_ele, s_ele_, type == EQI_HAND_L, flag);
  417. /**
  418. * In RE Shield Boomerang takes weapon element only for damage calculation,
  419. * - resist calculation is always against neutral
  420. **/
  421. if ( skill_id == CR_SHIELDBOOMERANG )
  422. s_ele = s_ele_ = ELE_NEUTRAL;
  423. // attacker side
  424. damage = battle->calc_cardfix(BF_WEAPON, src, bl, nk, s_ele, s_ele_, damage, 2|(type == EQI_HAND_L), flag2);
  425. // target side
  426. damage = battle->calc_cardfix(BF_WEAPON, src, bl, nk, s_ele, s_ele_, damage, 0, flag2);
  427. return damage;
  428. #else
  429. return 0;
  430. #endif
  431. }
  432. /*==========================================
  433. * Calculates the standard damage of a normal attack assuming it hits,
  434. * it calculates nothing extra fancy, is needed for magnum breaks WATK_ELEMENT bonus. [Skotlex]
  435. *------------------------------------------
  436. * Pass damage2 as NULL to not calc it.
  437. * Flag values: // TODO: Check whether these values are correct (the flag parameter seems to be passed through to other functions), and replace them with an enum.
  438. * &1: Critical hit
  439. * &2: Arrow attack
  440. * &4: Skill is Magic Crasher
  441. * &8: Skip target size adjustment (Extremity Fist?)
  442. *&16: Arrow attack but BOW, REVOLVER, RIFLE, SHOTGUN, GATLING or GRENADE type weapon not equipped (i.e. shuriken, kunai and venom knives not affected by DEX)
  443. */
  444. /* 'battle_calc_base_damage' is used on renewal, 'battle_calc_base_damage2' otherwise. */
  445. // FIXME: Missing documentation for flag2
  446. int64 battle_calc_base_damage(struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int nk, bool n_ele, short s_ele, short s_ele_, int type, int flag, int flag2) {
  447. int64 damage;
  448. struct status_data *st = status->get_status_data(src);
  449. struct status_change *sc = status->get_sc(src);
  450. const struct map_session_data *sd = NULL;
  451. nullpo_retr(0, src);
  452. sd = BL_CCAST(BL_PC, src);
  453. if ( !skill_id ) {
  454. s_ele = st->rhw.ele;
  455. s_ele_ = st->lhw.ele;
  456. if (sd != NULL) {
  457. if (sd->charm_type != CHARM_TYPE_NONE && sd->charm_count >= MAX_SPIRITCHARM) {
  458. s_ele = s_ele_ = sd->charm_type;
  459. }
  460. if (flag&2 && sd->bonus.arrow_ele != 0)
  461. s_ele = sd->bonus.arrow_ele;
  462. }
  463. }
  464. if (src->type == BL_PC) {
  465. int64 batk;
  466. // Property from mild wind bypasses it
  467. if (sc && sc->data[SC_TK_SEVENWIND])
  468. batk = battle->calc_elefix(src, bl, skill_id, skill_lv, status->calc_batk(bl, sc, st->batk, false), nk, n_ele, s_ele, s_ele_, false, flag);
  469. else
  470. batk = battle->calc_elefix(src, bl, skill_id, skill_lv, status->calc_batk(bl, sc, st->batk, false), nk, n_ele, ELE_NEUTRAL, ELE_NEUTRAL, false, flag);
  471. if (type == EQI_HAND_L)
  472. damage = batk + 3 * battle->calc_weapon_damage(src, bl, skill_id, skill_lv, &st->lhw, nk, n_ele, s_ele, s_ele_, status_get_size(bl), type, flag, flag2) / 4;
  473. else
  474. damage = (batk << 1) + battle->calc_weapon_damage(src, bl, skill_id, skill_lv, &st->rhw, nk, n_ele, s_ele, s_ele_, status_get_size(bl), type, flag, flag2);
  475. } else {
  476. damage = st->batk + battle->calc_weapon_damage(src, bl, skill_id, skill_lv, &st->rhw, nk, n_ele, s_ele, s_ele_, status_get_size(bl), type, flag, flag2);
  477. }
  478. return damage;
  479. }
  480. int64 battle_calc_base_damage2(struct status_data *st, struct weapon_atk *wa, struct status_change *sc, unsigned short t_size, struct map_session_data *sd, int flag) {
  481. unsigned int atkmin=0, atkmax=0;
  482. short type = 0;
  483. int64 damage = 0;
  484. nullpo_retr(damage, st);
  485. nullpo_retr(damage, wa);
  486. if (!sd) { //Mobs/Pets
  487. if(flag&4) {
  488. atkmin = st->matk_min;
  489. atkmax = st->matk_max;
  490. } else {
  491. atkmin = wa->atk;
  492. atkmax = wa->atk2;
  493. }
  494. if (atkmin > atkmax)
  495. atkmin = atkmax;
  496. } else { //PCs
  497. atkmax = wa->atk;
  498. type = (wa == &st->lhw)?EQI_HAND_L:EQI_HAND_R;
  499. if (!(flag&1) || (flag&2)) { //Normal attacks
  500. atkmin = st->dex;
  501. if (sd->equip_index[type] >= 0 && sd->inventory_data[sd->equip_index[type]])
  502. atkmin = atkmin*(80 + sd->inventory_data[sd->equip_index[type]]->wlv*20)/100;
  503. if (atkmin > atkmax)
  504. atkmin = atkmax;
  505. if(flag&2 && !(flag&16)) { //Bows
  506. atkmin = atkmin*atkmax/100;
  507. if (atkmin > atkmax)
  508. atkmax = atkmin;
  509. }
  510. }
  511. }
  512. if (sc && sc->data[SC_MAXIMIZEPOWER])
  513. atkmin = atkmax;
  514. //Weapon Damage calculation
  515. if (!(flag&1))
  516. damage = (atkmax>atkmin? rnd()%(atkmax-atkmin):0)+atkmin;
  517. else
  518. damage = atkmax;
  519. if (sd) {
  520. //rodatazone says the range is 0~arrow_atk-1 for non crit
  521. if (flag&2 && sd->bonus.arrow_atk)
  522. damage += ( (flag&1) ? sd->bonus.arrow_atk : rnd()%sd->bonus.arrow_atk );
  523. //SizeFix only for players
  524. if (!(sd->special_state.no_sizefix || (flag&8)))
  525. damage = damage * ( type == EQI_HAND_L ? sd->left_weapon.atkmods[t_size] : sd->right_weapon.atkmods[t_size] ) / 100;
  526. }
  527. //Finally, add baseatk
  528. if(flag&4)
  529. damage += st->matk_min;
  530. else
  531. damage += st->batk;
  532. //rodatazone says that Overrefined bonuses are part of baseatk
  533. //Here we also apply the weapon_atk_rate bonus so it is correctly applied on left/right hands.
  534. if(sd) {
  535. if (type == EQI_HAND_L) {
  536. if(sd->left_weapon.overrefine)
  537. damage += rnd()%sd->left_weapon.overrefine+1;
  538. if (sd->weapon_atk_rate[sd->weapontype2])
  539. damage += damage * sd->weapon_atk_rate[sd->weapontype2] / 100;
  540. } else { //Right hand
  541. if(sd->right_weapon.overrefine)
  542. damage += rnd()%sd->right_weapon.overrefine+1;
  543. if (sd->weapon_atk_rate[sd->weapontype1])
  544. damage += damage * sd->weapon_atk_rate[sd->weapontype1] / 100;
  545. }
  546. }
  547. return damage;
  548. }
  549. int64 battle_calc_sizefix(struct map_session_data *sd, int64 damage, int type, int size, bool ignore){
  550. //SizeFix only for players
  551. nullpo_retr(damage, sd);
  552. if (!(sd->special_state.no_sizefix || (ignore)))
  553. damage = damage * ( type == EQI_HAND_L ? sd->left_weapon.atkmods[size] : sd->right_weapon.atkmods[size] ) / 100;
  554. return damage;
  555. }
  556. /*==========================================
  557. * Passive skill damages increases
  558. *------------------------------------------*/
  559. // FIXME: type is undocumented
  560. int64 battle_addmastery(struct map_session_data *sd,struct block_list *target,int64 dmg,int type) {
  561. int64 damage;
  562. struct status_data *st = status->get_status_data(target);
  563. int weapon, skill_lv;
  564. damage = dmg;
  565. nullpo_retr(damage, sd);
  566. nullpo_retr(damage, target);
  567. if((skill_lv = pc->checkskill(sd,AL_DEMONBANE)) > 0 &&
  568. target->type == BL_MOB && //This bonus doesn't work against players.
  569. (battle->check_undead(st->race,st->def_ele) || st->race==RC_DEMON) )
  570. damage += (int)(skill_lv*(3+sd->status.base_level/20.0));
  571. //damage += (skill_lv * 3);
  572. if( (skill_lv = pc->checkskill(sd, RA_RANGERMAIN)) > 0 && (st->race == RC_BRUTE || st->race == RC_PLANT || st->race == RC_FISH) )
  573. damage += (skill_lv * 5);
  574. if( (skill_lv = pc->checkskill(sd,NC_RESEARCHFE)) > 0 && (st->def_ele == ELE_FIRE || st->def_ele == ELE_EARTH) )
  575. damage += (skill_lv * 10);
  576. if( pc_ismadogear(sd) )
  577. damage += 15 * pc->checkskill(sd, NC_MADOLICENCE);
  578. #ifdef RENEWAL
  579. if( (skill_lv = pc->checkskill(sd,BS_WEAPONRESEARCH)) > 0 )
  580. damage += (skill_lv * 2);
  581. #endif
  582. if((skill_lv = pc->checkskill(sd,HT_BEASTBANE)) > 0 && (st->race==RC_BRUTE || st->race==RC_INSECT) ) {
  583. damage += (skill_lv * 4);
  584. if (sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_HUNTER)
  585. damage += sd->status.str;
  586. }
  587. if(type == 0)
  588. weapon = sd->weapontype1;
  589. else
  590. weapon = sd->weapontype2;
  591. switch(weapon) {
  592. case W_1HSWORD:
  593. #ifdef RENEWAL
  594. if((skill_lv = pc->checkskill(sd,AM_AXEMASTERY)) > 0)
  595. damage += (skill_lv * 3);
  596. #endif
  597. case W_DAGGER:
  598. if((skill_lv = pc->checkskill(sd,SM_SWORD)) > 0)
  599. damage += (skill_lv * 4);
  600. if((skill_lv = pc->checkskill(sd,GN_TRAINING_SWORD)) > 0)
  601. damage += skill_lv * 10;
  602. break;
  603. case W_2HSWORD:
  604. #ifdef RENEWAL
  605. if((skill_lv = pc->checkskill(sd,AM_AXEMASTERY)) > 0)
  606. damage += (skill_lv * 3);
  607. #endif
  608. if((skill_lv = pc->checkskill(sd,SM_TWOHAND)) > 0)
  609. damage += (skill_lv * 4);
  610. break;
  611. case W_1HSPEAR:
  612. case W_2HSPEAR:
  613. if ((skill_lv = pc->checkskill(sd,KN_SPEARMASTERY)) > 0) {
  614. if (pc_isridingdragon(sd))
  615. damage += (skill_lv * 10);
  616. else if (pc_isridingpeco(sd))
  617. damage += (skill_lv * 5);
  618. else
  619. damage += (skill_lv * 4);
  620. }
  621. break;
  622. case W_1HAXE:
  623. case W_2HAXE:
  624. if((skill_lv = pc->checkskill(sd,AM_AXEMASTERY)) > 0)
  625. damage += (skill_lv * 3);
  626. if((skill_lv = pc->checkskill(sd,NC_TRAININGAXE)) > 0)
  627. damage += (skill_lv * 5);
  628. break;
  629. case W_MACE:
  630. case W_2HMACE:
  631. if((skill_lv = pc->checkskill(sd,PR_MACEMASTERY)) > 0)
  632. damage += (skill_lv * 3);
  633. if((skill_lv = pc->checkskill(sd,NC_TRAININGAXE)) > 0)
  634. damage += (skill_lv * 5);
  635. break;
  636. case W_FIST:
  637. if((skill_lv = pc->checkskill(sd,TK_RUN)) > 0)
  638. damage += (skill_lv * 10);
  639. // No break, fall through to Knuckles
  640. case W_KNUCKLE:
  641. if((skill_lv = pc->checkskill(sd,MO_IRONHAND)) > 0)
  642. damage += (skill_lv * 3);
  643. break;
  644. case W_MUSICAL:
  645. if((skill_lv = pc->checkskill(sd,BA_MUSICALLESSON)) > 0)
  646. damage += (skill_lv * 3);
  647. break;
  648. case W_WHIP:
  649. if((skill_lv = pc->checkskill(sd,DC_DANCINGLESSON)) > 0)
  650. damage += (skill_lv * 3);
  651. break;
  652. case W_BOOK:
  653. if((skill_lv = pc->checkskill(sd,SA_ADVANCEDBOOK)) > 0)
  654. damage += (skill_lv * 3);
  655. break;
  656. case W_KATAR:
  657. if((skill_lv = pc->checkskill(sd,AS_KATAR)) > 0)
  658. damage += (skill_lv * 3);
  659. break;
  660. }
  661. return damage;
  662. }
  663. /*==========================================
  664. * Calculates ATK masteries.
  665. *------------------------------------------*/
  666. int64 battle_calc_masteryfix(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 damage, int div, bool left, bool weapon) {
  667. int skill2_lv, i;
  668. struct status_change *sc;
  669. struct map_session_data *sd;
  670. struct status_data *tstatus;
  671. nullpo_ret(src);
  672. nullpo_ret(target);
  673. sc = status->get_sc(src);
  674. sd = BL_CAST(BL_PC, src);
  675. tstatus = status->get_status_data(target);
  676. if ( !sd )
  677. return damage;
  678. damage = battle->add_mastery(sd, target, damage, left);
  679. switch( skill_id ){ // specific skill masteries
  680. case MO_INVESTIGATE:
  681. case MO_EXTREMITYFIST:
  682. case CR_GRANDCROSS:
  683. case NJ_ISSEN:
  684. case CR_ACIDDEMONSTRATION:
  685. return damage;
  686. case NJ_SYURIKEN:
  687. if( (skill2_lv = pc->checkskill(sd,NJ_TOBIDOUGU)) > 0
  688. #ifndef RENEWAL
  689. && weapon
  690. #endif
  691. )
  692. damage += 3 * skill2_lv;
  693. break;
  694. #ifndef RENEWAL
  695. case NJ_KUNAI:
  696. if( weapon )
  697. damage += 60;
  698. break;
  699. #endif
  700. case RA_WUGDASH://(Caster Current Weight x 10 / 8)
  701. if( sd->weight )
  702. damage += sd->weight / 8;
  703. /* Fall through */
  704. case RA_WUGSTRIKE:
  705. case RA_WUGBITE:
  706. damage += 30*pc->checkskill(sd, RA_TOOTHOFWUG);
  707. break;
  708. case HT_FREEZINGTRAP:
  709. damage += 40 * pc->checkskill(sd, RA_RESEARCHTRAP);
  710. break;
  711. default:
  712. battle->calc_masteryfix_unknown(src, target, &skill_id, &skill_lv, &damage, &div, &left, &weapon);
  713. break;
  714. }
  715. if( sc ){ // sc considered as masteries
  716. if(sc->data[SC_GN_CARTBOOST])
  717. damage += 10 * sc->data[SC_GN_CARTBOOST]->val1;
  718. if(sc->data[SC_CAMOUFLAGE])
  719. damage += 30 * ( 10 - sc->data[SC_CAMOUFLAGE]->val4 );
  720. #ifdef RENEWAL
  721. if(sc->data[SC_NIBELUNGEN] && weapon)
  722. damage += sc->data[SC_NIBELUNGEN]->val2;
  723. if(sc->data[SC_IMPOSITIO])
  724. damage += sc->data[SC_IMPOSITIO]->val2;
  725. if(sc->data[SC_DRUMBATTLE]){
  726. if(tstatus->size == SZ_SMALL)
  727. damage += sc->data[SC_DRUMBATTLE]->val2;
  728. else if(tstatus->size == SZ_MEDIUM)
  729. damage += 10 * sc->data[SC_DRUMBATTLE]->val1;
  730. //else no bonus for large target
  731. }
  732. if(sc->data[SC_GS_MADNESSCANCEL])
  733. damage += 100;
  734. if(sc->data[SC_GS_GATLINGFEVER]){
  735. if(tstatus->size == SZ_SMALL)
  736. damage += 10 * sc->data[SC_GS_GATLINGFEVER]->val1;
  737. else if(tstatus->size == SZ_MEDIUM)
  738. damage += -5 * sc->data[SC_GS_GATLINGFEVER]->val1;
  739. else
  740. damage += sc->data[SC_GS_GATLINGFEVER]->val1;
  741. }
  742. #if 0
  743. if(sc->data[SC_SPECIALZONE])
  744. damage += sc->data[SC_SPECIALZONE]->val2 >> 4;
  745. #endif // 0
  746. #endif // RENEWAL
  747. }
  748. // general skill masteries
  749. #ifdef RENEWAL
  750. if( div < 0 ) // div fix
  751. div = 1;
  752. if( skill_id == MO_FINGEROFFENSIVE )//The finger offensive spheres on moment of attack do count. [Skotlex]
  753. damage += div * sd->spiritball_old * 3;
  754. else
  755. damage += div * sd->spiritball * 3;
  756. if( skill_id != CR_SHIELDBOOMERANG ) // Only Shield boomerang doesn't takes the Star Crumbs bonus.
  757. damage += div * (left ? sd->left_weapon.star : sd->right_weapon.star);
  758. if( skill_id != MC_CARTREVOLUTION && (skill2_lv=pc->checkskill(sd,BS_HILTBINDING)) > 0 )
  759. damage += 4;
  760. if(sd->status.party_id && (skill2_lv=pc->checkskill(sd,TK_POWER)) > 0) {
  761. if( (i = party->foreachsamemap(party->sub_count, sd, 0)) > 1 )
  762. damage += 2 * skill2_lv * i * (damage /*+ unknown value*/) / 100 /*+ unknown value*/;
  763. }
  764. #else
  765. if( skill_id != ASC_BREAKER && weapon ) // Adv Katar Mastery is does not applies to ASC_BREAKER, but other masteries DO apply >_>
  766. if( sd->status.weapon == W_KATAR && (skill2_lv=pc->checkskill(sd,ASC_KATAR)) > 0 )
  767. damage += damage * (10 + 2 * skill2_lv) / 100;
  768. #endif
  769. // percentage factor masteries
  770. if ( sc && sc->data[SC_MIRACLE] )
  771. i = 2; //Star anger
  772. else
  773. ARR_FIND(0, MAX_PC_FEELHATE, i, status->get_class(target) == sd->hate_mob[i]);
  774. if (i < MAX_PC_FEELHATE && (skill2_lv=pc->checkskill(sd,pc->sg_info[i].anger_id)) > 0 && weapon) {
  775. int ratio = sd->status.base_level + status_get_dex(src) + status_get_luk(src);
  776. if ( i == 2 ) ratio += status_get_str(src); //Star Anger
  777. if (skill2_lv < 4 )
  778. ratio /= (12 - 3 * skill2_lv);
  779. damage += damage * ratio / 100;
  780. }
  781. if( sd->status.class_ == JOB_ARCH_BISHOP_T || sd->status.class_ == JOB_ARCH_BISHOP ){
  782. if((skill2_lv = pc->checkskill(sd,AB_EUCHARISTICA)) > 0 &&
  783. (tstatus->race == RC_DEMON || tstatus->def_ele == ELE_DARK) )
  784. damage += damage * skill2_lv / 100;
  785. }
  786. return damage;
  787. }
  788. void battle_calc_masteryfix_unknown(struct block_list *src, struct block_list *target, uint16 *skill_id, uint16 *skill_lv, int64 *damage, int *div, bool *left, bool *weapon) {
  789. }
  790. /*==========================================
  791. * Elemental attribute fix.
  792. *------------------------------------------*/
  793. // FIXME: flag is undocumented
  794. int64 battle_calc_elefix(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 damage, int nk, int n_ele, int s_ele, int s_ele_, bool left, int flag){
  795. struct status_data *tstatus;
  796. nullpo_ret(src);
  797. nullpo_ret(target);
  798. tstatus = status->get_status_data(target);
  799. if( (nk&NK_NO_ELEFIX) || n_ele )
  800. return damage;
  801. if( damage > 0 ) {
  802. if( left )
  803. damage = battle->attr_fix(src, target, damage, s_ele_, tstatus->def_ele, tstatus->ele_lv);
  804. else{
  805. damage=battle->attr_fix(src, target, damage, s_ele, tstatus->def_ele, tstatus->ele_lv);
  806. if( skill_id == MC_CARTREVOLUTION ) //Cart Revolution applies the element fix once more with neutral element
  807. damage = battle->attr_fix(src,target,damage,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv);
  808. if( skill_id == NC_ARMSCANNON )
  809. damage = battle->attr_fix(src,target,damage,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv);
  810. if( skill_id == GS_GROUNDDRIFT ) //Additional 50*lv Neutral damage.
  811. damage += battle->attr_fix(src,target,50*skill_lv,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv);
  812. }
  813. }
  814. #ifndef RENEWAL
  815. {
  816. struct status_data *sstatus;
  817. struct status_change *sc;
  818. sstatus = status->get_status_data(src);
  819. sc = status->get_sc(src);
  820. if( sc && sc->data[SC_SUB_WEAPONPROPERTY] ) { // Descriptions indicate this means adding a percent of a normal attack in another element. [Skotlex]
  821. int64 temp = battle->calc_base_damage2(sstatus, &sstatus->rhw, sc, tstatus->size, BL_CAST(BL_PC, src), (flag?2:0)) * sc->data[SC_SUB_WEAPONPROPERTY]->val2 / 100;
  822. damage += battle->attr_fix(src, target, temp, sc->data[SC_SUB_WEAPONPROPERTY]->val1, tstatus->def_ele, tstatus->ele_lv);
  823. if( left ) {
  824. temp = battle->calc_base_damage2(sstatus, &sstatus->lhw, sc, tstatus->size, BL_CAST(BL_PC, src), (flag?2:0)) * sc->data[SC_SUB_WEAPONPROPERTY]->val2 / 100;
  825. damage += battle->attr_fix(src, target, temp, sc->data[SC_SUB_WEAPONPROPERTY]->val1, tstatus->def_ele, tstatus->ele_lv);
  826. }
  827. }
  828. }
  829. #endif
  830. return damage;
  831. }
  832. int64 battle_calc_cardfix2(struct block_list *src, struct block_list *bl, int64 damage, int s_ele, int nk, int flag) {
  833. #ifdef RENEWAL
  834. struct map_session_data *tsd;
  835. struct status_data *sstatus;
  836. if ( !damage )
  837. return 0;
  838. nullpo_ret(bl);
  839. nullpo_ret(src);
  840. tsd = BL_CAST(BL_PC, bl);
  841. sstatus = status->get_status_data(src);
  842. if ( tsd ) {
  843. if ( !(nk&NK_NO_CARDFIX_DEF) ) {
  844. // RaceAddTolerance
  845. damage -= damage * tsd->race_tolerance[sstatus->race] / 100;
  846. damage -= damage * tsd->race_tolerance[is_boss(src) ? RC_BOSS : RC_NONBOSS] / 100;
  847. if ( flag&BF_SHORT )
  848. damage -= damage * tsd->bonus.near_attack_def_rate / 100;
  849. else // SubRangeAttackDamage or bLongAtkDef
  850. damage -= damage * tsd->bonus.long_attack_def_rate / 100;
  851. }
  852. if ( flag&BF_LONG && tsd->sc.data[SC_GS_ADJUSTMENT] ) {
  853. damage -= 20 * damage / 100;
  854. }
  855. }
  856. #endif
  857. return damage;
  858. }
  859. /*==========================================
  860. * Calculates card bonuses damage adjustments.
  861. * cflag(cardfix flag):
  862. * &1 - calc for left hand.
  863. * &2 - atker side cardfix(BF_WEAPON) otherwise target side(BF_WEAPON).
  864. *------------------------------------------*/
  865. // FIXME: wflag is undocumented
  866. int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_list *target, int nk, int s_ele, int s_ele_, int64 damage, int cflag, int wflag){
  867. struct map_session_data *sd, *tsd;
  868. #ifdef RENEWAL
  869. short cardfix = 100;
  870. #else
  871. short cardfix = 1000;
  872. #endif
  873. short t_class, s_class, s_race2, t_race2;
  874. struct status_data *sstatus, *tstatus;
  875. int i;
  876. if( !damage )
  877. return 0;
  878. nullpo_ret(src);
  879. nullpo_ret(target);
  880. sd = BL_CAST(BL_PC, src);
  881. tsd = BL_CAST(BL_PC, target);
  882. t_class = status->get_class(target);
  883. s_class = status->get_class(src);
  884. sstatus = status->get_status_data(src);
  885. tstatus = status->get_status_data(target);
  886. s_race2 = status->get_race2(src);
  887. switch(attack_type){
  888. case BF_MAGIC:
  889. if ( sd && !(nk&NK_NO_CARDFIX_ATK) ) {
  890. cardfix = cardfix * (100 + sd->magic_addrace[tstatus->race]) / 100;
  891. if (!(nk&NK_NO_ELEFIX))
  892. cardfix = cardfix*(100+sd->magic_addele[tstatus->def_ele]) / 100;
  893. cardfix = cardfix * (100 + sd->magic_addsize[tstatus->size]) / 100;
  894. cardfix = cardfix * (100 + sd->magic_addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]) / 100;
  895. cardfix = cardfix * (100 + sd->magic_atk_ele[s_ele])/100;
  896. for(i=0; i< ARRAYLENGTH(sd->add_mdmg) && sd->add_mdmg[i].rate; i++) {
  897. if(sd->add_mdmg[i].class_ == t_class) {
  898. cardfix = cardfix * (100 + sd->add_mdmg[i].rate) / 100;
  899. break;
  900. }
  901. }
  902. }
  903. if( tsd && !(nk&NK_NO_CARDFIX_DEF) )
  904. { // Target cards.
  905. if (!(nk&NK_NO_ELEFIX))
  906. {
  907. int ele_fix = tsd->subele[s_ele];
  908. for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++)
  909. {
  910. if(tsd->subele2[i].ele != s_ele) continue;
  911. if(!(tsd->subele2[i].flag&wflag&BF_WEAPONMASK &&
  912. tsd->subele2[i].flag&wflag&BF_RANGEMASK &&
  913. tsd->subele2[i].flag&wflag&BF_SKILLMASK))
  914. continue;
  915. ele_fix += tsd->subele2[i].rate;
  916. }
  917. cardfix = cardfix * (100 - ele_fix) / 100;
  918. }
  919. cardfix = cardfix * (100 - tsd->subsize[sstatus->size]) / 100;
  920. cardfix = cardfix * (100 - tsd->subrace2[s_race2]) / 100;
  921. cardfix = cardfix * (100 - tsd->subrace[sstatus->race]) / 100;
  922. cardfix = cardfix * (100 - tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS]) / 100;
  923. for(i=0; i < ARRAYLENGTH(tsd->add_mdef) && tsd->add_mdef[i].rate;i++) {
  924. if(tsd->add_mdef[i].class_ == s_class) {
  925. cardfix = cardfix * (100-tsd->add_mdef[i].rate) / 100;
  926. break;
  927. }
  928. }
  929. #ifndef RENEWAL
  930. //It was discovered that ranged defense also counts vs magic! [Skotlex]
  931. if ( wflag&BF_SHORT )
  932. cardfix = cardfix * ( 100 - tsd->bonus.near_attack_def_rate ) / 100;
  933. else
  934. cardfix = cardfix * ( 100 - tsd->bonus.long_attack_def_rate ) / 100;
  935. #endif
  936. cardfix = cardfix * ( 100 - tsd->bonus.magic_def_rate ) / 100;
  937. if( tsd->sc.data[SC_PROTECT_MDEF] )
  938. cardfix = cardfix * ( 100 - tsd->sc.data[SC_PROTECT_MDEF]->val1 ) / 100;
  939. }
  940. #ifdef RENEWAL
  941. if ( cardfix != 100 )
  942. damage += damage * (cardfix - 100) / 100;
  943. #else
  944. if ( cardfix != 1000 )
  945. damage = damage * cardfix / 1000;
  946. #endif
  947. break;
  948. case BF_WEAPON:
  949. t_race2 = status->get_race2(target);
  950. if( cflag&2 ){
  951. if( sd && !(nk&NK_NO_CARDFIX_ATK) ){
  952. short cardfix_ =
  953. #ifdef RENEWAL
  954. 100;
  955. #else
  956. 1000;
  957. #endif
  958. if( sd->state.arrow_atk ){
  959. cardfix = cardfix * (100 + sd->right_weapon.addrace[tstatus->race] + sd->arrow_addrace[tstatus->race]) / 100;
  960. if( !(nk&NK_NO_ELEFIX) ){
  961. int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->arrow_addele[tstatus->def_ele];
  962. for(i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++){
  963. if (sd->right_weapon.addele2[i].ele != tstatus->def_ele) continue;
  964. if(!(sd->right_weapon.addele2[i].flag&wflag&BF_WEAPONMASK &&
  965. sd->right_weapon.addele2[i].flag&wflag&BF_RANGEMASK &&
  966. sd->right_weapon.addele2[i].flag&wflag&BF_SKILLMASK))
  967. continue;
  968. ele_fix += sd->right_weapon.addele2[i].rate;
  969. }
  970. cardfix = cardfix * (100 + ele_fix) / 100;
  971. }
  972. cardfix = cardfix * (100 + sd->right_weapon.addsize[tstatus->size]+sd->arrow_addsize[tstatus->size]) / 100;
  973. cardfix = cardfix * (100 + sd->right_weapon.addrace2[t_race2]) / 100;
  974. cardfix = cardfix * (100 + sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS] + sd->arrow_addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]) / 100;
  975. }else{ // Melee attack
  976. if( !battle_config.left_cardfix_to_right ){
  977. cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race])/100;
  978. if( !(nk&NK_NO_ELEFIX) ){
  979. int ele_fix = sd->right_weapon.addele[tstatus->def_ele];
  980. for (i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++) {
  981. if (sd->right_weapon.addele2[i].ele != tstatus->def_ele) continue;
  982. if(!(sd->right_weapon.addele2[i].flag&wflag&BF_WEAPONMASK &&
  983. sd->right_weapon.addele2[i].flag&wflag&BF_RANGEMASK &&
  984. sd->right_weapon.addele2[i].flag&wflag&BF_SKILLMASK))
  985. continue;
  986. ele_fix += sd->right_weapon.addele2[i].rate;
  987. }
  988. cardfix = cardfix * (100+ele_fix) / 100;
  989. }
  990. cardfix = cardfix * (100+sd->right_weapon.addsize[tstatus->size]) / 100;
  991. cardfix = cardfix * (100+sd->right_weapon.addrace2[t_race2]) / 100;
  992. cardfix = cardfix * (100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]) / 100;
  993. if( cflag&1 ){
  994. cardfix_ = cardfix_*(100+sd->left_weapon.addrace[tstatus->race])/100;
  995. if (!(nk&NK_NO_ELEFIX)){
  996. int ele_fix_lh = sd->left_weapon.addele[tstatus->def_ele];
  997. for (i = 0; ARRAYLENGTH(sd->left_weapon.addele2) > i && sd->left_weapon.addele2[i].rate != 0; i++) {
  998. if (sd->left_weapon.addele2[i].ele != tstatus->def_ele) continue;
  999. if(!(sd->left_weapon.addele2[i].flag&wflag&BF_WEAPONMASK &&
  1000. sd->left_weapon.addele2[i].flag&wflag&BF_RANGEMASK &&
  1001. sd->left_weapon.addele2[i].flag&wflag&BF_SKILLMASK))
  1002. continue;
  1003. ele_fix_lh += sd->left_weapon.addele2[i].rate;
  1004. }
  1005. cardfix = cardfix * (100+ele_fix_lh) / 100;
  1006. }
  1007. cardfix_ = cardfix_ * (100+sd->left_weapon.addsize[tstatus->size]) / 100;
  1008. cardfix_ = cardfix_ * (100+sd->left_weapon.addrace2[t_race2]) / 100;
  1009. cardfix_ = cardfix_ * (100+sd->left_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]) / 100;
  1010. }
  1011. }else{
  1012. int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->left_weapon.addele[tstatus->def_ele];
  1013. for (i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++){
  1014. if (sd->right_weapon.addele2[i].ele != tstatus->def_ele) continue;
  1015. if(!(sd->right_weapon.addele2[i].flag&wflag&BF_WEAPONMASK &&
  1016. sd->right_weapon.addele2[i].flag&wflag&BF_RANGEMASK &&
  1017. sd->right_weapon.addele2[i].flag&wflag&BF_SKILLMASK))
  1018. continue;
  1019. ele_fix += sd->right_weapon.addele2[i].rate;
  1020. }
  1021. for (i = 0; ARRAYLENGTH(sd->left_weapon.addele2) > i && sd->left_weapon.addele2[i].rate != 0; i++){
  1022. if (sd->left_weapon.addele2[i].ele != tstatus->def_ele) continue;
  1023. if(!(sd->left_weapon.addele2[i].flag&wflag&BF_WEAPONMASK &&
  1024. sd->left_weapon.addele2[i].flag&wflag&BF_RANGEMASK &&
  1025. sd->left_weapon.addele2[i].flag&wflag&BF_SKILLMASK))
  1026. continue;
  1027. ele_fix += sd->left_weapon.addele2[i].rate;
  1028. }
  1029. cardfix = cardfix * (100 + sd->right_weapon.addrace[tstatus->race] + sd->left_weapon.addrace[tstatus->race]) / 100;
  1030. cardfix = cardfix * (100 + ele_fix) / 100;
  1031. cardfix = cardfix * (100 + sd->right_weapon.addsize[tstatus->size] + sd->left_weapon.addsize[tstatus->size])/100;
  1032. cardfix = cardfix * (100 + sd->right_weapon.addrace2[t_race2] + sd->left_weapon.addrace2[t_race2])/100;
  1033. cardfix = cardfix * (100 + sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS] + sd->left_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]) / 100;
  1034. }
  1035. }
  1036. for( i = 0; i < ARRAYLENGTH(sd->right_weapon.add_dmg) && sd->right_weapon.add_dmg[i].rate; i++ ){
  1037. if( sd->right_weapon.add_dmg[i].class_ == t_class ){
  1038. cardfix = cardfix * (100 + sd->right_weapon.add_dmg[i].rate) / 100;
  1039. break;
  1040. }
  1041. }
  1042. if( cflag&1 ){
  1043. for( i = 0; i < ARRAYLENGTH(sd->left_weapon.add_dmg) && sd->left_weapon.add_dmg[i].rate; i++ ){
  1044. if( sd->left_weapon.add_dmg[i].class_ == t_class ){
  1045. cardfix_ = cardfix_ * (100 + sd->left_weapon.add_dmg[i].rate) / 100;
  1046. break;
  1047. }
  1048. }
  1049. }
  1050. #ifndef RENEWAL
  1051. if( wflag&BF_LONG )
  1052. cardfix = cardfix * (100 + sd->bonus.long_attack_atk_rate) / 100;
  1053. if( (cflag&1) && cardfix_ != 1000 )
  1054. damage = damage * cardfix_ / 1000;
  1055. else if( cardfix != 1000 )
  1056. damage = damage * cardfix / 1000;
  1057. #else
  1058. if ((cflag & 1) && cardfix_ != 100)
  1059. damage += damage * (cardfix_ - 100) / 100;
  1060. else if (cardfix != 100)
  1061. damage += damage * (cardfix - 100) / 100;
  1062. #endif
  1063. }
  1064. }else{
  1065. // Target side
  1066. if( tsd && !(nk&NK_NO_CARDFIX_DEF) ){
  1067. if( !(nk&NK_NO_ELEFIX) ){
  1068. int ele_fix = tsd->subele[s_ele];
  1069. for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++)
  1070. {
  1071. if(tsd->subele2[i].ele != s_ele) continue;
  1072. if(!(tsd->subele2[i].flag&wflag&BF_WEAPONMASK &&
  1073. tsd->subele2[i].flag&wflag&BF_RANGEMASK &&
  1074. tsd->subele2[i].flag&wflag&BF_SKILLMASK))
  1075. continue;
  1076. ele_fix += tsd->subele2[i].rate;
  1077. }
  1078. cardfix = cardfix * (100-ele_fix) / 100;
  1079. if( cflag&1 && s_ele_ != s_ele ){
  1080. int ele_fix_lh = tsd->subele[s_ele_];
  1081. for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++){
  1082. if(tsd->subele2[i].ele != s_ele_) continue;
  1083. if(!(tsd->subele2[i].flag&wflag&BF_WEAPONMASK &&
  1084. tsd->subele2[i].flag&wflag&BF_RANGEMASK &&
  1085. tsd->subele2[i].flag&wflag&BF_SKILLMASK))
  1086. continue;
  1087. ele_fix_lh += tsd->subele2[i].rate;
  1088. }
  1089. cardfix = cardfix * (100 - ele_fix_lh) / 100;
  1090. }
  1091. }
  1092. cardfix = cardfix * (100-tsd->subsize[sstatus->size]) / 100;
  1093. cardfix = cardfix * (100-tsd->subrace2[s_race2]) / 100;
  1094. cardfix = cardfix * (100-tsd->subrace[sstatus->race]) / 100;
  1095. cardfix = cardfix * (100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS]) / 100;
  1096. for( i = 0; i < ARRAYLENGTH(tsd->add_def) && tsd->add_def[i].rate;i++ ){
  1097. if( tsd->add_def[i].class_ == s_class )
  1098. {
  1099. cardfix = cardfix * (100 - tsd->add_def[i].rate) / 100;
  1100. break;
  1101. }
  1102. }
  1103. #ifndef RENEWAL
  1104. if( wflag&BF_SHORT )
  1105. cardfix = cardfix * (100 - tsd->bonus.near_attack_def_rate) / 100;
  1106. else // BF_LONG (there's no other choice)
  1107. cardfix = cardfix * (100 - tsd->bonus.long_attack_def_rate) / 100;
  1108. #endif
  1109. if( tsd->sc.data[SC_PROTECT_DEF] )
  1110. cardfix = cardfix * (100 - tsd->sc.data[SC_PROTECT_DEF]->val1) / 100;
  1111. #ifdef RENEWAL
  1112. if ( cardfix != 100 )
  1113. damage += damage * (cardfix - 100) / 100;
  1114. #else
  1115. if( cardfix != 1000 )
  1116. damage = damage * cardfix / 1000;
  1117. #endif
  1118. }
  1119. }
  1120. break;
  1121. case BF_MISC:
  1122. if ( tsd && !(nk&NK_NO_CARDFIX_DEF) ) {
  1123. // misc damage reduction from equipment
  1124. #ifndef RENEWAL
  1125. if ( !(nk&NK_NO_ELEFIX) )
  1126. {
  1127. int ele_fix = tsd->subele[s_ele];
  1128. for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++)
  1129. {
  1130. if(tsd->subele2[i].ele != s_ele) continue;
  1131. if(!(tsd->subele2[i].flag&wflag&BF_WEAPONMASK &&
  1132. tsd->subele2[i].flag&wflag&BF_RANGEMASK &&
  1133. tsd->subele2[i].flag&wflag&BF_SKILLMASK))
  1134. continue;
  1135. ele_fix += tsd->subele2[i].rate;
  1136. }
  1137. cardfix = cardfix * (100 - ele_fix) / 100;
  1138. }
  1139. cardfix = cardfix*(100-tsd->subrace[sstatus->race]) / 100;
  1140. cardfix = cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS]) / 100;
  1141. if( wflag&BF_SHORT )
  1142. cardfix = cardfix * ( 100 - tsd->bonus.near_attack_def_rate ) / 100;
  1143. else // BF_LONG (there's no other choice)
  1144. cardfix = cardfix * ( 100 - tsd->bonus.long_attack_def_rate ) / 100;
  1145. #endif
  1146. cardfix = cardfix*(100 - tsd->subsize[sstatus->size]) / 100;
  1147. cardfix = cardfix*(100 - tsd->subrace2[s_race2]) / 100;
  1148. cardfix = cardfix * (100 - tsd->bonus.misc_def_rate) / 100;
  1149. #ifdef RENEWAL
  1150. if ( cardfix != 100 )
  1151. damage += damage * (cardfix - 100) / 100;
  1152. #else
  1153. if ( cardfix != 1000 )
  1154. damage = damage * cardfix / 1000;
  1155. #endif
  1156. }
  1157. break;
  1158. }
  1159. return damage;
  1160. }
  1161. /*==========================================
  1162. * Calculates defense reduction. [malufett]
  1163. * flag:
  1164. * &1 - idef/imdef(Ignore defense)
  1165. * &2 - pdef(Pierce defense)
  1166. * &4 - tdef(Total defense reduction)
  1167. *------------------------------------------*/
  1168. // TODO: Add an enum for flag
  1169. int64 battle_calc_defense(int attack_type, struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 damage, int flag, int pdef){
  1170. struct status_data *sstatus, *tstatus;
  1171. struct map_session_data *sd, *tsd;
  1172. struct status_change *sc, *tsc;
  1173. int i;
  1174. if( !damage )
  1175. return 0;
  1176. nullpo_ret(src);
  1177. nullpo_ret(target);
  1178. sd = BL_CAST(BL_PC, src);
  1179. tsd = BL_CAST(BL_PC, target);
  1180. sstatus = status->get_status_data(src);
  1181. tstatus = status->get_status_data(target);
  1182. sc = status->get_sc(src);
  1183. tsc = status->get_sc(target);
  1184. switch(attack_type){
  1185. case BF_WEAPON:
  1186. {
  1187. /* Take note in RE
  1188. * def1 = equip def
  1189. * def2 = status def
  1190. */
  1191. defType def1 = status->get_def(target); //Don't use tstatus->def1 due to skill timer reductions.
  1192. short def2 = tstatus->def2, vit_def;
  1193. #ifdef RENEWAL
  1194. def1 = status->calc_def2(target, tsc, def1, false); // equip def(RE)
  1195. def2 = status->calc_def(target, tsc, def2, false); // status def(RE)
  1196. #else
  1197. def1 = status->calc_def(target, tsc, def1, false); // equip def(RE)
  1198. def2 = status->calc_def2(target, tsc, def2, false); // status def(RE)
  1199. #endif
  1200. if ( sd ) {
  1201. if ( sd->charm_type == CHARM_TYPE_LAND && sd->charm_count > 0 ) // hidden from status window
  1202. def1 += 10 * def1 * sd->charm_count / 100;
  1203. i = sd->ignore_def[is_boss(target) ? RC_BOSS : RC_NONBOSS];
  1204. i += sd->ignore_def[tstatus->race];
  1205. if ( i ) {
  1206. if ( i > 100 ) i = 100;
  1207. def1 -= def1 * i / 100;
  1208. #ifndef RENEWAL
  1209. def2 -= def2 * i / 100;
  1210. #endif
  1211. }
  1212. }
  1213. if( sc && sc->data[SC_EXPIATIO] ){
  1214. i = 5 * sc->data[SC_EXPIATIO]->val1; // 5% per level
  1215. def1 -= def1 * i / 100;
  1216. #ifndef RENEWAL
  1217. def2 -= def2 * i / 100;
  1218. #endif
  1219. }
  1220. if( battle_config.vit_penalty_type && battle_config.vit_penalty_target&target->type ) {
  1221. unsigned char target_count; //256 max targets should be a sane max
  1222. target_count = unit->counttargeted(target);
  1223. if(target_count >= battle_config.vit_penalty_count) {
  1224. if(battle_config.vit_penalty_type == 1) {
  1225. if( !tsc || !tsc->data[SC_STEELBODY] )
  1226. def1 = (def1 * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100;
  1227. def2 = (def2 * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100;
  1228. } else { //Assume type 2
  1229. if( !tsc || !tsc->data[SC_STEELBODY] )
  1230. def1 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num;
  1231. def2 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num;
  1232. }
  1233. }
  1234. #ifndef RENEWAL
  1235. if(skill_id == AM_ACIDTERROR) def1 = 0; //Acid Terror ignores only armor defense. [Skotlex]
  1236. #endif
  1237. if(def2 < 1) def2 = 1;
  1238. }
  1239. //Vitality reduction from rodatazone: http://rodatazone.simgaming.net/mechanics/substats.php#def
  1240. if (tsd) {
  1241. //Sd vit-eq
  1242. #ifndef RENEWAL
  1243. //[VIT*0.5] + rnd([VIT*0.3], max([VIT*0.3],[VIT^2/150]-1))
  1244. vit_def = def2*(def2-15)/150;
  1245. vit_def = def2/2 + (vit_def>0?rnd()%vit_def:0);
  1246. #else
  1247. vit_def = def2;
  1248. #endif
  1249. if((battle->check_undead(sstatus->race,sstatus->def_ele) || sstatus->race==RC_DEMON) && //This bonus already doesn't work vs players
  1250. src->type == BL_MOB && (i=pc->checkskill(tsd,AL_DP)) > 0)
  1251. vit_def += i*(int)(3 +(tsd->status.base_level+1)*0.04); // [orn]
  1252. if( src->type == BL_MOB && (i=pc->checkskill(tsd,RA_RANGERMAIN))>0 &&
  1253. (sstatus->race == RC_BRUTE || sstatus->race == RC_FISH || sstatus->race == RC_PLANT) )
  1254. vit_def += i*5;
  1255. }
  1256. else { //Mob-Pet vit-eq
  1257. #ifndef RENEWAL
  1258. //VIT + rnd(0,[VIT/20]^2-1)
  1259. vit_def = (def2/20)*(def2/20);
  1260. vit_def = def2 + (vit_def>0?rnd()%vit_def:0);
  1261. #else
  1262. vit_def = def2;
  1263. #endif
  1264. }
  1265. if (battle_config.weapon_defense_type) {
  1266. vit_def += def1*battle_config.weapon_defense_type;
  1267. def1 = 0;
  1268. }
  1269. #ifdef RENEWAL
  1270. /**
  1271. * RE DEF Reduction
  1272. * Pierce defense gains 1 atk per def/2
  1273. **/
  1274. if( def1 < -399 ) // it stops at -399
  1275. def1 = 399; // in aegis it set to 1 but in our case it may lead to exploitation so limit it to 399
  1276. //return 1;
  1277. if( flag&2 )
  1278. damage += def1 >> 1;
  1279. if( !(flag&1) && !(flag&2) ) {
  1280. if( flag&4 )
  1281. damage -= (def1 + vit_def);
  1282. else
  1283. damage = (int)((100.0f - de

Large files files are truncated, but you can click here to view the full file