yuhsing

Untitled

Feb 22nd, 2013
91
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 64.46 KB | None | 0 0
  1. // Copyright (c) Athena Dev Teams - Licensed under GNU GPL
  2. // For more information, see LICENCE in the main folder
  3.  
  4. #include "../common/cbasetypes.h"
  5. #include "../common/timer.h"
  6. #include "../common/nullpo.h"
  7. #include "../common/malloc.h"
  8. #include "../common/showmsg.h"
  9. #include "../common/ers.h"
  10. #include "../common/strlib.h"
  11. #include "../common/utils.h"
  12.  
  13. #include "map.h"
  14. #include "path.h"
  15. #include "pc.h"
  16. #include "status.h"
  17. #include "skill.h"
  18. #include "homunculus.h"
  19. #include "mercenary.h"
  20. #include "elemental.h"
  21. #include "mob.h"
  22. #include "itemdb.h"
  23. #include "clif.h"
  24. #include "pet.h"
  25. #include "guild.h"
  26. #include "party.h"
  27. #include "battle.h"
  28. #include "battleground.h"
  29.  
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33. #include <math.h>
  34.  
  35. int attr_fix_table[4][ELE_MAX][ELE_MAX];
  36.  
  37. struct Battle_Config battle_config;
  38. static struct eri *delay_damage_ers; //For battle delay damage structures.
  39.  
  40. int battle_getcurrentskill(struct block_list *bl)
  41. { //Returns the current/last skill in use by this bl.
  42. struct unit_data *ud;
  43.  
  44. if( bl->type == BL_SKILL )
  45. {
  46. struct skill_unit * su = (struct skill_unit*)bl;
  47. return su->group?su->group->skill_id:0;
  48. }
  49. ud = unit_bl2ud(bl);
  50. return ud?ud->skillid:0;
  51. }
  52.  
  53. /*==========================================
  54. * Get random targetting enemy
  55. *------------------------------------------*/
  56. static int battle_gettargeted_sub(struct block_list *bl, va_list ap)
  57. {
  58. struct block_list **bl_list;
  59. struct unit_data *ud;
  60. int target_id;
  61. int *c;
  62.  
  63. bl_list = va_arg(ap, struct block_list **);
  64. c = va_arg(ap, int *);
  65. target_id = va_arg(ap, int);
  66.  
  67. if (bl->id == target_id)
  68. return 0;
  69. if (*c >= 24)
  70. return 0;
  71.  
  72. ud = unit_bl2ud(bl);
  73. if (!ud) return 0;
  74.  
  75. if (ud->target == target_id || ud->skilltarget == target_id) {
  76. bl_list[(*c)++] = bl;
  77. return 1;
  78. }
  79. return 0;
  80. }
  81.  
  82. struct block_list* battle_gettargeted(struct block_list *target)
  83. {
  84. struct block_list *bl_list[24];
  85. int c = 0;
  86. nullpo_retr(NULL, target);
  87.  
  88. memset(bl_list, 0, sizeof(bl_list));
  89. map_foreachinrange(battle_gettargeted_sub, target, AREA_SIZE, BL_CHAR, bl_list, &c, target->id);
  90. if (c == 0 || c > 24)
  91. return NULL;
  92. return bl_list[rand()%c];
  93. }
  94.  
  95.  
  96. //Returns the id of the current targetted character of the passed bl. [Skotlex]
  97. int battle_gettarget(struct block_list* bl)
  98. {
  99. switch (bl->type)
  100. {
  101. case BL_PC: return ((struct map_session_data*)bl)->ud.target;
  102. case BL_MOB: return ((struct mob_data*)bl)->target_id;
  103. case BL_PET: return ((struct pet_data*)bl)->target_id;
  104. case BL_HOM: return ((struct homun_data*)bl)->ud.target;
  105. case BL_MER: return ((struct mercenary_data*)bl)->ud.target;
  106. case BL_ELEM: return ((struct elemental_data*)bl)->ud.target;
  107. }
  108. return 0;
  109. }
  110.  
  111. static int battle_getenemy_sub(struct block_list *bl, va_list ap)
  112. {
  113. struct block_list **bl_list;
  114. struct block_list *target;
  115. int *c;
  116.  
  117. bl_list = va_arg(ap, struct block_list **);
  118. c = va_arg(ap, int *);
  119. target = va_arg(ap, struct block_list *);
  120.  
  121. if (bl->id == target->id)
  122. return 0;
  123. if (*c >= 24)
  124. return 0;
  125. if (status_isdead(bl))
  126. return 0;
  127. if (battle_check_target(target, bl, BCT_ENEMY) > 0) {
  128. bl_list[(*c)++] = bl;
  129. return 1;
  130. }
  131. return 0;
  132. }
  133.  
  134. // Picks a random enemy of the given type (BL_PC, BL_CHAR, etc) within the range given. [Skotlex]
  135. struct block_list* battle_getenemy(struct block_list *target, int type, int range)
  136. {
  137. struct block_list *bl_list[24];
  138. int c = 0;
  139. memset(bl_list, 0, sizeof(bl_list));
  140. map_foreachinrange(battle_getenemy_sub, target, range, type, bl_list, &c, target);
  141. if (c == 0 || c > 24)
  142. return NULL;
  143. return bl_list[rand()%c];
  144. }
  145.  
  146. static int battle_getenemyarea_sub(struct block_list *bl, va_list ap)
  147. {
  148. struct block_list **bl_list, *src;
  149. int *c, ignore_id;
  150.  
  151. bl_list = va_arg(ap, struct block_list **);
  152. c = va_arg(ap, int *);
  153. src = va_arg(ap, struct block_list *);
  154. ignore_id = va_arg(ap, int);
  155.  
  156. if( bl->id == src->id || bl->id == ignore_id )
  157. return 0; // Ignores Caster and a possible pre-target
  158. if( *c >= 24 )
  159. return 0;
  160. if( status_isdead(bl) )
  161. return 0;
  162. if( battle_check_target(src, bl, BCT_ENEMY) > 0 )
  163. { // Is Enemy!...
  164. bl_list[(*c)++] = bl;
  165. return 1;
  166. }
  167. return 0;
  168. }
  169.  
  170. // Pick a random enemy
  171. struct block_list* battle_getenemyarea(struct block_list *src, int x, int y, int range, int type, int ignore_id)
  172. {
  173. struct block_list *bl_list[24];
  174. int c = 0;
  175. memset(bl_list, 0, sizeof(bl_list));
  176. map_foreachinarea(battle_getenemyarea_sub, src->m, x - range, y - range, x + range, y + range, type, bl_list, &c, src, ignore_id);
  177. if( c == 0 || c > 24 )
  178. return NULL;
  179. return bl_list[rand()%c];
  180. }
  181.  
  182. // ƒ_??[ƒW‚Ì’x‰„
  183. struct delay_damage {
  184. struct block_list *src;
  185. int target;
  186. int damage;
  187. int delay;
  188. unsigned short distance;
  189. unsigned short skill_lv;
  190. unsigned short skill_id;
  191. enum damage_lv dmg_lv;
  192. unsigned short attack_type;
  193. };
  194.  
  195. int battle_delay_damage_sub(int tid, unsigned int tick, int id, intptr data)
  196. {
  197. struct delay_damage *dat = (struct delay_damage *)data;
  198. struct block_list *target = map_id2bl(dat->target);
  199. if (target && dat && map_id2bl(id) == dat->src && target->prev != NULL && !status_isdead(target) &&
  200. target->m == dat->src->m &&
  201. (target->type != BL_PC || ((TBL_PC*)target)->invincible_timer == INVALID_TIMER) &&
  202. check_distance_bl(dat->src, target, dat->distance)) //Check to see if you haven't teleported. [Skotlex]
  203. {
  204. map_freeblock_lock();
  205. status_fix_damage(dat->src, target, dat->damage, dat->delay);
  206. if( dat->attack_type && !status_isdead(target) )
  207. skill_additional_effect(dat->src,target,dat->skill_id,dat->skill_lv,dat->attack_type,dat->dmg_lv,tick);
  208. if( dat->dmg_lv > ATK_BLOCK && dat->attack_type )
  209. skill_counter_additional_effect(dat->src,target,dat->skill_id,dat->skill_lv,dat->attack_type,tick);
  210. map_freeblock_unlock();
  211. }
  212. ers_free(delay_damage_ers, dat);
  213. return 0;
  214. }
  215.  
  216. int battle_delay_damage (unsigned int tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, int skill_id, int skill_lv, int damage, enum damage_lv dmg_lv, int ddelay)
  217. {
  218. struct delay_damage *dat;
  219. struct status_change *sc;
  220. nullpo_ret(src);
  221. nullpo_ret(target);
  222.  
  223. sc = status_get_sc(target);
  224. if( sc && sc->data[SC_DEVOTION] && damage > 0 )
  225. damage = 0;
  226.  
  227. if (!battle_config.delay_battle_damage) {
  228. map_freeblock_lock();
  229. status_fix_damage(src, target, damage, ddelay); // We have to seperate here between reflect damage and others [icescope]
  230. if( attack_type && !status_isdead(target) )
  231. skill_additional_effect(src, target, skill_id, skill_lv, attack_type, dmg_lv, gettick());
  232. if( dmg_lv > ATK_BLOCK && attack_type )
  233. skill_counter_additional_effect(src, target, skill_id, skill_lv, attack_type, gettick());
  234. map_freeblock_unlock();
  235. return 0;
  236. }
  237. dat = ers_alloc(delay_damage_ers, struct delay_damage);
  238. dat->src = src;
  239. dat->target = target->id;
  240. dat->skill_id = skill_id;
  241. dat->skill_lv = skill_lv;
  242. dat->attack_type = attack_type;
  243. dat->damage = damage;
  244. dat->dmg_lv = dmg_lv;
  245. dat->delay = ddelay;
  246. dat->distance = distance_bl(src, target)+10; //Attack should connect regardless unless you teleported.
  247. if (src->type != BL_PC && amotion > 1000)
  248. amotion = 1000; //Aegis places a damage-delay cap of 1 sec to non player attacks. [Skotlex]
  249. add_timer(tick+amotion, battle_delay_damage_sub, src->id, (intptr)dat);
  250.  
  251. return 0;
  252. }
  253.  
  254. int battle_attr_ratio(int atk_elem,int def_type, int def_lv)
  255. {
  256.  
  257. if (atk_elem < 0 || atk_elem >= ELE_MAX)
  258. return 100;
  259.  
  260. if (def_type < 0 || def_type > ELE_MAX || def_lv < 1 || def_lv > 4)
  261. return 100;
  262.  
  263. return attr_fix_table[def_lv-1][atk_elem][def_type];
  264. }
  265.  
  266. /*==========================================
  267. * Does attribute fix modifiers.
  268. * Added passing of the chars so that the status changes can affect it. [Skotlex]
  269. * Note: Passing src/target == NULL is perfectly valid, it skips SC_ checks.
  270. *------------------------------------------*/
  271. int battle_attr_fix(struct block_list *src, struct block_list *target, int damage,int atk_elem,int def_type, int def_lv)
  272. {
  273. struct status_change *sc=NULL, *tsc=NULL;
  274. int ratio;
  275.  
  276. if (src) sc = status_get_sc(src);
  277. if (target) tsc = status_get_sc(target);
  278.  
  279. if (atk_elem < 0 || atk_elem >= ELE_MAX)
  280. atk_elem = rand()%ELE_MAX;
  281.  
  282. if (def_type < 0 || def_type > ELE_MAX ||
  283. def_lv < 1 || def_lv > 4) {
  284. ShowError("battle_attr_fix: unknown attr type: atk=%d def_type=%d def_lv=%d\n",atk_elem,def_type,def_lv);
  285. return damage;
  286. }
  287.  
  288. ratio = attr_fix_table[def_lv-1][atk_elem][def_type];
  289. if (sc && sc->count)
  290. {
  291. if(sc->data[SC_VOLCANO] && atk_elem == ELE_FIRE)
  292. ratio += enchant_eff[sc->data[SC_VOLCANO]->val1-1];
  293. if(sc->data[SC_VIOLENTGALE] && atk_elem == ELE_WIND)
  294. ratio += enchant_eff[sc->data[SC_VIOLENTGALE]->val1-1];
  295. if(sc->data[SC_DELUGE] && atk_elem == ELE_WATER)
  296. ratio += enchant_eff[sc->data[SC_DELUGE]->val1-1];
  297. if(sc->data[SC_FIRE_CLOAK_OPTION] && atk_elem == ELE_FIRE)
  298. damage += damage * sc->data[SC_FIRE_CLOAK_OPTION]->val2 / 100;
  299. }
  300. if( atk_elem == ELE_FIRE && tsc && tsc->count && tsc->data[SC_SPIDERWEB] )
  301. {
  302. tsc->data[SC_SPIDERWEB]->val1 = 0; // free to move now
  303. if( tsc->data[SC_SPIDERWEB]->val2-- > 0 )
  304. damage <<= 1; // double damage
  305. if( tsc->data[SC_SPIDERWEB]->val2 == 0 )
  306. status_change_end(target, SC_SPIDERWEB, INVALID_TIMER);
  307. }
  308. if( tsc && tsc->count )
  309. {
  310. if( tsc->data[SC_ORATIO] && atk_elem == ELE_HOLY )
  311. ratio += tsc->data[SC_ORATIO]->val1 * 2;
  312. if( tsc->data[SC_VENOMIMPRESS] && atk_elem == ELE_POISON)
  313. ratio += tsc->data[SC_VENOMIMPRESS]->val2;
  314. if( atk_elem == ELE_FIRE && tsc->data[SC_THORNSTRAP] )
  315. status_change_end(target, SC_THORNSTRAP, -1);
  316. if( tsc->data[SC_FIRE_CLOAK_OPTION] && atk_elem == ELE_FIRE)
  317. damage -= damage * tsc->data[SC_FIRE_CLOAK_OPTION]->val2 / 100;
  318. }
  319. if( target && target->type == BL_SKILL )
  320. {
  321. if( atk_elem == ELE_FIRE && battle_getcurrentskill(target) == GN_WALLOFTHORN )
  322. {
  323. struct skill_unit *su = (struct skill_unit*)target;
  324. struct skill_unit_group *sg;
  325. struct block_list *src;
  326. int x,y;
  327.  
  328. if( !su || !su->alive || (sg = su->group) == NULL || !sg || sg->val3 == -1 ||
  329. (src = map_id2bl(su->val2)) == NULL || status_isdead(src) )
  330. return 0;
  331.  
  332. if( sg->unit_id != UNT_FIREWALL )
  333. {
  334. x = sg->val3 >> 16;
  335. y = sg->val3 & 0xffff;
  336. skill_unitsetting(src,su->group->skill_id,su->group->skill_lv,x,y,1);
  337. sg->val3 = -1;
  338. sg->limit = DIFF_TICK(gettick(),sg->tick)+300;
  339. }
  340. }
  341. }
  342. if( atk_elem == ELE_FIRE && tsc && tsc->count && tsc->data[SC_CRYSTALIZE] )
  343. { //FIXTHIS: is this right to be an accurate way to remove Crystalize status when hitted by fire element? [Jobbie]
  344. tsc->data[SC_CRYSTALIZE]->val1 = 0;
  345. if( tsc->data[SC_CRYSTALIZE]->val2 == 0 )
  346. status_change_end(target,SC_CRYSTALIZE,-1);
  347. }
  348. return damage*ratio/100;
  349. }
  350.  
  351. /*==========================================
  352. * ƒ_??[ƒW??IŒvŽZ
  353. *------------------------------------------*/
  354. int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damage *d,int damage,int skill_num,int skill_lv,int element)
  355. {
  356. struct map_session_data *sd = NULL;
  357. struct status_change *sc, *tsc;
  358. struct status_change_entry *sce;
  359. int div_ = d->div_, flag = d->flag;
  360.  
  361. nullpo_ret(bl);
  362.  
  363. // emistry - immune to skills and only receive 1 damage.
  364. if( ((TBL_MOB*)bl)->class_ == 1084 || ((TBL_MOB*)bl)->class_ == 1085 ){
  365. return (( flag&BF_SKILL )? 0:1 );
  366. }
  367.  
  368. if( !damage )
  369. return 0;
  370. if( mob_ksprotected(src, bl) )
  371. return 0;
  372.  
  373. if (bl->type == BL_PC) {
  374. sd=(struct map_session_data *)bl;
  375. //Special no damage states
  376. if(flag&BF_WEAPON && sd->special_state.no_weapon_damage)
  377. damage -= damage*sd->special_state.no_weapon_damage/100;
  378.  
  379. if(flag&BF_MAGIC && sd->special_state.no_magic_damage)
  380. damage -= damage*sd->special_state.no_magic_damage/100;
  381.  
  382. if(flag&BF_MISC && sd->special_state.no_misc_damage)
  383. damage -= damage*sd->special_state.no_misc_damage/100;
  384.  
  385. if(!damage) return 0;
  386. }
  387.  
  388. sc = status_get_sc(bl);
  389. tsc = status_get_sc(src);
  390.  
  391. if( sc && sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF] )
  392. return 1;
  393.  
  394. if (skill_num == PA_PRESSURE)
  395. return damage; //This skill bypass everything else.
  396.  
  397. if( sc && sc->count )
  398. {
  399. //First, sc_*'s that reduce damage to 0.
  400. if( sc->data[SC_BASILICA] && !(status_get_mode(src)&MD_BOSS) && skill_num != PA_PRESSURE )
  401. {
  402. d->dmg_lv = ATK_BLOCK;
  403. return 0;
  404. }
  405.  
  406. if( sc->data[SC_WHITEIMPRISON] && skill_num != HW_GRAVITATION && skill_num != PA_PRESSURE )
  407. { // Gravitation and Pressure do damage without removing the effect
  408. if( skill_num == MG_NAPALMBEAT || skill_num == MG_SOULSTRIKE || skill_num == WL_SOULEXPANSION || element == ELE_GHOST )
  409. status_change_end(bl,SC_WHITEIMPRISON,-1); // Those skills do damage and removes effect
  410. else
  411. {
  412. d->dmg_lv = ATK_BLOCK;
  413. return 0;
  414. }
  415. }
  416.  
  417. if( sc->data[SC_SAFETYWALL] && (flag&(BF_SHORT|BF_MAGIC)) == BF_SHORT )
  418. {
  419. struct skill_unit_group* group = skill_id2group(sc->data[SC_SAFETYWALL]->val3);
  420. if (group) {
  421. if (--group->val2<=0)
  422. skill_delunitgroup(group);
  423. d->dmg_lv = ATK_BLOCK;
  424. return 0;
  425. }
  426. status_change_end(bl, SC_SAFETYWALL, INVALID_TIMER);
  427. }
  428.  
  429. if( (sc->data[SC_PNEUMA] && (flag&(BF_MAGIC|BF_LONG)) == BF_LONG) || sc->data[SC__MANHOLE] )
  430. {
  431. d->dmg_lv = ATK_BLOCK;
  432. return 0;
  433. }
  434. if( sc->data[SC_ZEPHYR] && ((flag&BF_LONG) || rand()%100 < 10) )
  435. { // TODO: check if it blocks both, magic and physical ranged damages.
  436. d->dmg_lv = ATK_BLOCK;
  437. return 0;
  438. }
  439.  
  440. if( map_getcell(bl->m,bl->x,bl->y,CELL_CHKMAELSTROM) && (flag&BF_MAGIC) && skill_num && (skill_get_inf(skill_num)&INF_GROUND_SKILL) )
  441. {
  442. int sp = damage * 20 / 100; // Steel need official value.
  443. status_heal(bl,0,sp,3);
  444. d->dmg_lv = ATK_BLOCK;
  445. return 0;
  446. }
  447.  
  448. if( sc->data[SC_WEAPONBLOCKING] && flag&(BF_SHORT|BF_WEAPON) && rand()%100 < sc->data[SC_WEAPONBLOCKING]->val2 )
  449. {
  450. clif_skill_nodamage(bl,src,GC_WEAPONBLOCKING,1,1);
  451. d->dmg_lv = ATK_NONE;
  452. sc_start2(bl,SC_COMBO,100,GC_WEAPONBLOCKING,src->id,2000);
  453. return 0;
  454. }
  455.  
  456. if( (sce=sc->data[SC_AUTOGUARD]) && flag&BF_WEAPON && !(skill_get_nk(skill_num)&NK_NO_CARDFIX_ATK) && rand()%100 < sce->val2 )
  457. {
  458. int delay;
  459. clif_skill_nodamage(bl,bl,CR_AUTOGUARD,sce->val1,1);
  460. // different delay depending on skill level [celest]
  461. if (sce->val1 <= 5)
  462. delay = 300;
  463. else if (sce->val1 > 5 && sce->val1 <= 9)
  464. delay = 200;
  465. else
  466. delay = 100;
  467. unit_set_walkdelay(bl, gettick(), delay, 1);
  468.  
  469. if(sc->data[SC_SHRINK] && rand()%100<5*sce->val1)
  470. skill_blown(bl,src,skill_get_blewcount(CR_SHRINK,1),-1,0);
  471. return 0;
  472. }
  473.  
  474. if( sd && (sce = sc->data[SC_MILLENNIUMSHIELD]) && sce->val2 > 0 && damage > 0 )
  475. {
  476. clif_skill_nodamage(bl, bl, RK_MILLENNIUMSHIELD, 1, 1);
  477. sce->val3 -= damage; // absorb damage
  478. d->dmg_lv = ATK_BLOCK;
  479. sc_start(bl,SC_STUN,15,0,skill_get_time2(RK_MILLENNIUMSHIELD,sce->val1)); // There is a chance to be stuned when one shield is broken.
  480. if( sce->val3 <= 0 ) // Shield Down
  481. {
  482. sce->val2--;
  483. if( sce->val2 > 0 )
  484. {
  485. clif_millenniumshield(sd,sce->val2);
  486. sce->val3 = 1000; // Next Shield
  487. }
  488. else
  489. status_change_end(bl,SC_MILLENNIUMSHIELD,-1); // All shields down
  490. }
  491. return 0;
  492. }
  493.  
  494. if( (sce=sc->data[SC_PARRYING]) && flag&BF_WEAPON && skill_num != WS_CARTTERMINATION && rand()%100 < sce->val2 )
  495. { // attack blocked by Parrying
  496. clif_skill_nodamage(bl, bl, LK_PARRYING, sce->val1,1);
  497. return 0;
  498. }
  499.  
  500. if(sc->data[SC_DODGE] && !sc->opt1 &&
  501. (flag&BF_LONG || sc->data[SC_SPURT])
  502. && rand()%100 < 20)
  503. {
  504. if (sd && pc_issit(sd) && !sc->data[SC_SITDOWN_FORCE]) pc_setstand(sd); //Stand it to dodge.
  505. clif_skill_nodamage(bl,bl,TK_DODGE,1,1);
  506. if (!sc->data[SC_COMBO])
  507. sc_start4(bl, SC_COMBO, 100, TK_JUMPKICK, src->id, 1, 0, 2000);
  508. return 0;
  509. }
  510.  
  511. if(sc->data[SC_HERMODE] && flag&BF_MAGIC)
  512. return 0;
  513.  
  514. if(sc->data[SC_TATAMIGAESHI] && (flag&(BF_MAGIC|BF_LONG)) == BF_LONG)
  515. return 0;
  516.  
  517. if((sce=sc->data[SC_KAUPE]) && rand()%100 < sce->val2)
  518. { //Kaupe blocks damage (skill or otherwise) from players, mobs, homuns, mercenaries.
  519. clif_specialeffect(bl, 462, AREA);
  520. //Shouldn't end until Breaker's non-weapon part connects.
  521. if (skill_num != ASC_BREAKER || !(flag&BF_WEAPON))
  522. if (--(sce->val3) <= 0) //We make it work like Safety Wall, even though it only blocks 1 time.
  523. status_change_end(bl, SC_KAUPE, INVALID_TIMER);
  524. return 0;
  525. }
  526.  
  527. if( flag&BF_MAGIC && (sce=sc->data[SC_PRESTIGE]) && rand()%100 < sce->val2)
  528. {
  529. clif_specialeffect(bl, 462, AREA); // Still need confirm it.
  530. return 0;
  531. }
  532.  
  533. if (((sce=sc->data[SC_UTSUSEMI]) || sc->data[SC_BUNSINJYUTSU])
  534. &&
  535. flag&BF_WEAPON && !(skill_get_nk(skill_num)&NK_NO_CARDFIX_ATK))
  536. {
  537. if (sce) {
  538. clif_specialeffect(bl, 462, AREA);
  539. skill_blown(src,bl,sce->val3,-1,0);
  540. }
  541. //Both need to be consumed if they are active.
  542. if (sce && --(sce->val2) <= 0)
  543. status_change_end(bl, SC_UTSUSEMI, INVALID_TIMER);
  544. if ((sce=sc->data[SC_BUNSINJYUTSU]) && --(sce->val2) <= 0)
  545. status_change_end(bl, SC_BUNSINJYUTSU, INVALID_TIMER);
  546. return 0;
  547. }
  548.  
  549. //Now damage increasing effects
  550. if( sc->data[SC_AETERNA] && skill_num != PF_SOULBURN )
  551. {
  552. if( src->type != BL_MER || skill_num == 0 )
  553. damage <<= 1; // Lex Aeterna only doubles damage of regular attacks from mercenaries
  554.  
  555. if( skill_num != ASC_BREAKER || !(flag&BF_WEAPON) )
  556. status_change_end(bl, SC_AETERNA, INVALID_TIMER); //Shouldn't end until Breaker's non-weapon part connects.
  557. }
  558. if( sc->data[SC_DEEPSLEEP] )
  559. {
  560. damage += damage / 2; // 1.5 times more damage while in Deep Sleep.
  561. status_change_end(bl,SC_DEEPSLEEP,-1);
  562. }
  563. if( sc->data[SC_VOICEOFSIREN] && damage > 0)
  564. status_change_end(bl,SC_VOICEOFSIREN,-1);
  565.  
  566. //Finally damage reductions....
  567. if( sc->data[SC_ASSUMPTIO] )
  568. {
  569. if( map_flag_vs(bl->m) )
  570. damage = damage * 2 / 3; //Receive 66% damage
  571. else
  572. damage >>= 1; //Receive 50% damage
  573. }
  574.  
  575. if( sc->data[SC_DEFENDER] && (flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON) )
  576. damage = damage * (100 - sc->data[SC_DEFENDER]->val2) / 100;
  577.  
  578. if( sc->data[SC_ADJUSTMENT] && (flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON) )
  579. damage -= 20 * damage / 100;
  580.  
  581. if( sc->data[SC_FOGWALL] )
  582. {
  583. if( flag&BF_SKILL ) //25% reduction
  584. damage -= 25 * damage / 100;
  585. else if( (flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON) )
  586. damage >>= 2; //75% reduction
  587. }
  588.  
  589. // Compressed code, fixed by map.h [Epoque]
  590. if( src->type == BL_MOB )
  591. {
  592. int i;
  593. if( sc->data[SC_MANU_DEF] )
  594. for( i = 0; ARRAYLENGTH(mob_manuk) > i; i++ )
  595. if( mob_manuk[i] == ((TBL_MOB*)src)->class_ )
  596. {
  597. damage -= sc->data[SC_MANU_DEF]->val1 * damage / 100;
  598. break;
  599. }
  600. if( sc->data[SC_SPL_DEF] )
  601. for (i=0;ARRAYLENGTH(mob_splendide)>i;i++)
  602. if (mob_splendide[i]==((TBL_MOB*)src)->class_) {
  603. damage -= sc->data[SC_SPL_DEF]->val1*damage/100;
  604. break;
  605. }
  606. }
  607.  
  608. if((sce=sc->data[SC_ARMOR]) && //NPC_DEFENDER
  609. sce->val3&flag && sce->val4&flag)
  610. damage -= damage*sc->data[SC_ARMOR]->val2/100;
  611.  
  612. if(sc->data[SC_ENERGYCOAT] && flag&BF_WEAPON
  613. && skill_num != WS_CARTTERMINATION)
  614. {
  615. struct status_data *status = status_get_status_data(bl);
  616. int per = 100*status->sp / status->max_sp -1; //100% should be counted as the 80~99% interval
  617. per /=20; //Uses 20% SP intervals.
  618. //SP Cost: 1% + 0.5% per every 20% SP
  619. if (!status_charge(bl, 0, (10+5*per)*status->max_sp/1000))
  620. status_change_end(bl, SC_ENERGYCOAT, INVALID_TIMER);
  621. //Reduction: 6% + 6% every 20%
  622. damage -= damage * 6 * (1+per) / 100;
  623. }
  624.  
  625. if( (sce = sc->data[SC_STONEHARDSKIN]) && flag&BF_WEAPON && damage > 0 )
  626. {
  627. sce->val2 -= damage;
  628. skill_break_equip(src,EQP_WEAPON,3000,BCT_SELF);// Need to code something that will lower a monster's attack by 25%. [Rytech]
  629.  
  630. if( sce->val2 <= 0 ) status_change_end(bl, SC_STONEHARDSKIN, -1);
  631. }
  632.  
  633. // FIXME:
  634. // So Reject Sword calculates the redirected damage before calculating WoE/BG reduction? This is weird. [Inkfish]
  635. if((sce=sc->data[SC_REJECTSWORD]) && flag&BF_WEAPON &&
  636. // Fixed the condition check [Aalye]
  637. (src->type!=BL_PC || (
  638. ((TBL_PC *)src)->status.weapon == W_DAGGER ||
  639. ((TBL_PC *)src)->status.weapon == W_1HSWORD ||
  640. ((TBL_PC *)src)->status.weapon == W_2HSWORD
  641. )) &&
  642. rand()%100 < sce->val2
  643. ){
  644. damage = damage*50/100;
  645. status_fix_damage(bl,src,damage,clif_damage(bl,src,gettick(),0,0,damage,0,0,0));
  646. clif_skill_nodamage(bl,bl,ST_REJECTSWORD,sce->val1,1);
  647. if(--(sce->val3)<=0)
  648. status_change_end(bl, SC_REJECTSWORD, INVALID_TIMER);
  649. }
  650.  
  651. //Finally added to remove the status of immobile when aimedbolt is used. [Jobbie]
  652. if( skill_num == RA_AIMEDBOLT && (sc->data[SC_BITE] || sc->data[SC_ANKLE] || sc->data[SC_ELECTRICSHOCKER]) )
  653. {
  654. status_change_end(bl, SC_BITE, -1);
  655. status_change_end(bl, SC_ANKLE, -1);
  656. status_change_end(bl, SC_ELECTRICSHOCKER, -1);
  657. }
  658.  
  659. //Finally Kyrie because it may, or not, reduce damage to 0.
  660. if((sce = sc->data[SC_KYRIE]) && damage > 0){
  661. sce->val2-=damage;
  662. if(flag&BF_WEAPON || skill_num == TF_THROWSTONE){
  663. if(sce->val2>=0)
  664. damage=0;
  665. else
  666. damage=-sce->val2;
  667. }
  668. if((--sce->val3)<=0 || (sce->val2<=0) || skill_num == AL_HOLYLIGHT)
  669. status_change_end(bl, SC_KYRIE, INVALID_TIMER);
  670. }
  671.  
  672. if( (sce = sc->data[SC_LIGHTNINGWALK]) && flag&BF_LONG && damage > 0 && rand()%100 < sce->val1 )
  673. {
  674. skill_blown(src,bl,distance_bl(src,bl)-1,unit_getdir(src),0);
  675. d->div_ = ATK_DEF;
  676. status_change_end(bl, SC_LIGHTNINGWALK, -1);
  677. return 0;
  678. }
  679.  
  680. if (!damage) return 0;
  681.  
  682. //Probably not the most correct place, but it'll do here
  683. //(since battle_drain is strictly for players currently)
  684. if ((sce=sc->data[SC_BLOODLUST]) && flag&BF_WEAPON && damage > 0 &&
  685. rand()%100 < sce->val3)
  686. status_heal(src, damage*sce->val4/100, 0, 3);
  687.  
  688. if( sd && (sce = sc->data[SC_FORCEOFVANGUARD]) && flag&BF_WEAPON && rand()%100 < sce->val2 )
  689. pc_addrageball(sd,skill_get_time(LG_FORCEOFVANGUARD,sce->val1),sce->val3);
  690.  
  691. if( (sce = sc->data[SC_GT_ENERGYGAIN]) && flag&BF_WEAPON && rand()%100 < 10 + 5 * sce->val1 )
  692. {
  693. int duration = skill_get_time2(MO_CALLSPIRITS, sce->val1);
  694. if( sd ) pc_addspiritball(sd, duration, sce->val1);
  695. }
  696.  
  697. if( sc->data[SC__DEADLYINFECT] && damage > 0 && rand()%100 < 65 + 5 * sc->data[SC__DEADLYINFECT]->val1 )
  698. status_change_spread(bl, src); // Deadly infect attacked side
  699. }
  700.  
  701. if( tsc && tsc->count )
  702. {
  703. if( tsc->data[SC_INVINCIBLE] && !tsc->data[SC_INVINCIBLEOFF] )
  704. damage += damage * 75 / 100;
  705. // [Epoque]
  706. if (bl->type == BL_MOB)
  707. {
  708. int i;
  709.  
  710. if ( ((sce=tsc->data[SC_MANU_ATK]) && (flag&BF_WEAPON)) ||
  711. ((sce=tsc->data[SC_MANU_MATK]) && (flag&BF_MAGIC))
  712. )
  713. for (i=0;ARRAYLENGTH(mob_manuk)>i;i++)
  714. if (((TBL_MOB*)bl)->class_==mob_manuk[i]) {
  715. damage += damage*sce->val1/100;
  716. break;
  717. }
  718. if ( ((sce=tsc->data[SC_SPL_ATK]) && (flag&BF_WEAPON)) ||
  719. ((sce=tsc->data[SC_SPL_MATK]) && (flag&BF_MAGIC))
  720. )
  721. for (i=0;ARRAYLENGTH(mob_splendide)>i;i++)
  722. if (((TBL_MOB*)bl)->class_==mob_splendide[i]) {
  723. damage += damage*sce->val1/100;
  724. break;
  725. }
  726. }
  727. if( tsc->data[SC_POISONINGWEAPON] && skill_num != GC_VENOMPRESSURE && (flag&BF_WEAPON) && damage > 0 && rand()%100 < tsc->data[SC_POISONINGWEAPON]->val3 )
  728. sc_start(bl,tsc->data[SC_POISONINGWEAPON]->val2,100,tsc->data[SC_POISONINGWEAPON]->val1,skill_get_time2(GC_POISONINGWEAPON,tsc->data[SC_POISONINGWEAPON]->val1));
  729. if( tsc->data[SC__DEADLYINFECT] && damage > 0 && rand()%100 < 65 + 5 * tsc->data[SC__DEADLYINFECT]->val1 )
  730. status_change_spread(src, bl);
  731. }
  732.  
  733. if( battle_config.pk_mode && sd && bl->type == BL_PC && damage )
  734. {
  735. if( flag & BF_SKILL )
  736. { //Skills get a different reduction than non-skills. [Skotlex]
  737. if( flag&BF_WEAPON )
  738. damage = damage * battle_config.pk_weapon_damage_rate/100;
  739. if( flag&BF_MAGIC )
  740. damage = damage * battle_config.pk_magic_damage_rate/100;
  741. if( flag&BF_MISC )
  742. damage = damage * battle_config.pk_misc_damage_rate/100;
  743. }
  744. else
  745. { //Normal attacks get reductions based on range.
  746. if( flag&BF_SHORT )
  747. damage = damage * battle_config.pk_short_damage_rate/100;
  748. if( flag&BF_LONG )
  749. damage = damage * battle_config.pk_long_damage_rate/100;
  750. }
  751. if( !damage ) damage = 1;
  752. }
  753.  
  754. if(battle_config.skill_min_damage && damage > 0 && damage < div_)
  755. {
  756. if ((flag&BF_WEAPON && battle_config.skill_min_damage&1)
  757. || (flag&BF_MAGIC && battle_config.skill_min_damage&2)
  758. || (flag&BF_MISC && battle_config.skill_min_damage&4)
  759. )
  760. damage = div_;
  761. }
  762.  
  763. if( bl->type == BL_MOB && !status_isdead(bl) && src != bl) {
  764. if (damage > 0 )
  765. mobskill_event((TBL_MOB*)bl,src,gettick(),flag);
  766. if (skill_num)
  767. mobskill_event((TBL_MOB*)bl,src,gettick(),MSC_SKILLUSED|(skill_num<<16));
  768. }
  769.  
  770. if( sd && pc_isriding(sd,OPTION_MADO) && (element == ELE_FIRE || element == ELE_WATER) && rand()%100 < 50 )
  771. pc_overheat(sd,element == ELE_FIRE ? 1 : -1);
  772.  
  773. if( sc && sc->data[SC__SHADOWFORM] )
  774. {
  775. struct block_list *s_bl = map_id2bl(sc->data[SC__SHADOWFORM]->val2);
  776. if( !s_bl )
  777. { // If the shadow form target is not present remove the sc.
  778. status_change_end(bl, SC__SHADOWFORM, -1);
  779. }
  780. else if( status_isdead(s_bl) || !battle_check_target(src,s_bl,BCT_ENEMY))
  781. { // If the shadow form target is dead or not your enemy remove the sc in both.
  782. status_change_end(bl, SC__SHADOWFORM, -1);
  783. if( s_bl->type == BL_PC )
  784. ((TBL_PC*)s_bl)->shadowform_id = 0;
  785. }
  786. else
  787. {
  788. if( (--sc->data[SC__SHADOWFORM]->val3) < 0 )
  789. { // If you have exceded max hits supported, remove the sc in both.
  790. status_change_end(bl, SC__SHADOWFORM, -1);
  791. if( s_bl->type == BL_PC )
  792. ((TBL_PC*)s_bl)->shadowform_id = 0;
  793. }
  794. else
  795. {
  796. status_damage(src, s_bl, damage, 0, clif_damage(s_bl, s_bl, gettick(), 500, 500, damage, -1, 0, 0), 0);
  797. return ATK_NONE;
  798. }
  799. }
  800. }
  801.  
  802. return damage;
  803. }
  804.  
  805. /*==========================================
  806. * Calculates BG related damage adjustments.
  807. *------------------------------------------*/
  808. int battle_calc_bg_damage(struct block_list *src, struct block_list *bl, int damage, int div_, int skill_num, int skill_lv, int flag)
  809. {
  810.  
  811. if( !damage )
  812. return 0;
  813.  
  814. if( bl->type == BL_MOB )
  815. {
  816. struct mob_data* md = BL_CAST(BL_MOB, bl);
  817. if( map[bl->m].flag.battleground && (md->class_ == 1914 || md->class_ == 1915) && flag&BF_SKILL )
  818. return 0; // Crystal cannot receive skill damage on battlegrounds
  819.  
  820. // emistry - skill immune + 1 damage only
  821. if(md->class_ == 1084 || md->class_ == 1085){
  822. return (( flag&BF_SKILL )? 0:1 );
  823. }
  824.  
  825. }
  826.  
  827. switch( skill_num )
  828. {
  829. case PA_PRESSURE:
  830. case HW_GRAVITATION:
  831. case NJ_ZENYNAGE:
  832. //case RK_DRAGONBREATH:
  833. //case GN_HELLS_PLANT_ATK:
  834. //case KO_MUCHANAGE:
  835. break;
  836. default:
  837. if( flag&BF_SKILL )
  838. { //Skills get a different reduction than non-skills. [Skotlex]
  839. if( flag&BF_WEAPON )
  840. damage = damage * battle_config.bg_weapon_damage_rate/100;
  841. if( flag&BF_MAGIC )
  842. damage = damage * battle_config.bg_magic_damage_rate/100;
  843. if( flag&BF_MISC )
  844. damage = damage * battle_config.bg_misc_damage_rate/100;
  845. }
  846. else
  847. { //Normal attacks get reductions based on range.
  848. if( flag&BF_SHORT )
  849. damage = damage * battle_config.bg_short_damage_rate/100;
  850. if( flag&BF_LONG )
  851. damage = damage * battle_config.bg_long_damage_rate/100;
  852. }
  853.  
  854. if( !damage ) damage = 1;
  855. }
  856.  
  857. return damage;
  858. }
  859.  
  860. /*==========================================
  861. * Calculates GVG related damage adjustments.
  862. *------------------------------------------*/
  863. int battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int damage,int div_,int skill_num,int skill_lv,int flag)
  864. {
  865. struct mob_data* md = BL_CAST(BL_MOB, bl);
  866. int class_ = status_get_class(bl);
  867.  
  868. // emistry - immune to skills and only receive 1 damage.
  869. if( class_ == 1084 || class_ == 1085 ){
  870. return (( flag&BF_SKILL )? 0:1 );
  871. }
  872.  
  873. if (!damage) //No reductions to make.
  874. return 0;
  875.  
  876. if(md && md->guardian_data) {
  877. if(class_ == MOBID_EMPERIUM && flag&BF_SKILL)
  878. //Skill immunity.
  879. switch (skill_num) {
  880. case MO_TRIPLEATTACK:
  881. case HW_GRAVITATION:
  882. break;
  883. default:
  884. return 0;
  885. }
  886. if(src->type != BL_MOB) {
  887. struct guild *g=guild_search(status_get_guild_id(src));
  888. if (!g) return 0;
  889. if (class_ == MOBID_EMPERIUM && guild_checkskill(g,GD_APPROVAL) <= 0)
  890. return 0;
  891. if (battle_config.guild_max_castles && guild_checkcastles(g)>=battle_config.guild_max_castles)
  892. return 0; // [MouseJstr]
  893. }
  894. }
  895.  
  896. switch (skill_num) {
  897. //Skills with no damage reduction.
  898. case PA_PRESSURE:
  899. case HW_GRAVITATION:
  900. case NJ_ZENYNAGE:
  901. //case RK_DRAGONBREATH:
  902. //case GN_HELLS_PLANT_ATK:
  903. //case KO_MUCHANAGE:
  904. break;
  905. default:
  906. if (md && md->guardian_data) {
  907. damage -= damage * (md->guardian_data->castle->defense/100) * battle_config.castle_defense_rate/100;
  908. }
  909. if (flag & BF_SKILL) { //Skills get a different reduction than non-skills. [Skotlex]
  910. if (flag&BF_WEAPON)
  911. damage = damage * battle_config.gvg_weapon_damage_rate/100;
  912. if (flag&BF_MAGIC)
  913. damage = damage * battle_config.gvg_magic_damage_rate/100;
  914. if (flag&BF_MISC)
  915. damage = damage * battle_config.gvg_misc_damage_rate/100;
  916. } else { //Normal attacks get reductions based on range.
  917. if (flag & BF_SHORT)
  918. damage = damage * battle_config.gvg_short_damage_rate/100;
  919. if (flag & BF_LONG)
  920. damage = damage * battle_config.gvg_long_damage_rate/100;
  921. }
  922. if(!damage) damage = 1;
  923. }
  924. return damage;
  925. }
  926.  
  927. /*==========================================
  928. * HP/SP‹zŽû‚ÌŒvŽZ
  929. *------------------------------------------*/
  930. static int battle_calc_drain(int damage, int rate, int per)
  931. {
  932. int diff = 0;
  933.  
  934. if (per && rand()%1000 < rate) {
  935. diff = (damage * per) / 100;
  936. if (diff == 0) {
  937. if (per > 0)
  938. diff = 1;
  939. else
  940. diff = -1;
  941. }
  942. }
  943. return diff;
  944. }
  945.  
  946. /*==========================================
  947. * ?C—ûƒ_??[ƒW
  948. *------------------------------------------*/
  949. int battle_addmastery(struct map_session_data *sd,struct block_list *target,int dmg,int type)
  950. {
  951. int damage,skill;
  952. struct status_data *status = status_get_status_data(target);
  953. int weapon;
  954. damage = dmg;
  955.  
  956. nullpo_ret(sd);
  957.  
  958. if((skill = pc_checkskill(sd,AL_DEMONBANE)) > 0 &&
  959. target->type == BL_MOB && //This bonus doesnt work against players.
  960. (battle_check_undead(status->race,status->def_ele) || status->race==RC_DEMON) )
  961. damage += (skill*(int)(3+(sd->status.base_level+1)*0.05)); // submitted by orn
  962. //damage += (skill * 3);
  963.  
  964. if((skill = pc_checkskill(sd,HT_BEASTBANE)) > 0 && (status->race==RC_BRUTE || status->race==RC_INSECT) ) {
  965. damage += (skill * 4);
  966. if (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_HUNTER)
  967. damage += sd->status.str;
  968. }
  969.  
  970. if( (skill = pc_checkskill(sd, RA_RANGERMAIN)) > 0 && (status->race == RC_BRUTE || status->race == RC_PLANT || status->race == RC_FISH) )
  971. damage += (skill * 5);
  972.  
  973. if( (skill = pc_checkskill(sd,NC_RESEARCHFE)) > 0 && (status->def_ele == ELE_FIRE || status->def_ele == ELE_EARTH) )
  974. damage += (skill * 10);
  975.  
  976. if( pc_isriding(sd, OPTION_MADO) )
  977. damage += 15 * pc_checkskill(sd, NC_MADOLICENCE);
  978.  
  979. if(type == 0)
  980. weapon = sd->weapontype1;
  981. else
  982. weapon = sd->weapontype2;
  983. switch(weapon)
  984. {
  985. case W_DAGGER:
  986. case W_1HSWORD:
  987. if((skill = pc_checkskill(sd,SM_SWORD)) > 0)
  988. damage += (skill * 4);
  989. if((skill = pc_checkskill(sd,GN_TRAINING_SWORD)) > 0)
  990. damage += skill * 10;
  991. break;
  992. case W_2HSWORD:
  993. if((skill = pc_checkskill(sd,SM_TWOHAND)) > 0)
  994. damage += (skill * 4);
  995. break;
  996. case W_1HSPEAR:
  997. case W_2HSPEAR:
  998. if((skill = pc_checkskill(sd,KN_SPEARMASTERY)) > 0) {
  999. if(!pc_isriding(sd, OPTION_RIDING|OPTION_RIDING_DRAGON))
  1000. damage += skill * 4;
  1001. else
  1002. damage += skill * (5 + pc_checkskill(sd,RK_DRAGONTRAINING));//Mastery damage is higher when on a Dragon Mount. [Rytech]
  1003. }
  1004. break;
  1005. case W_1HAXE:
  1006. case W_2HAXE:
  1007. if((skill = pc_checkskill(sd,AM_AXEMASTERY)) > 0)
  1008. damage += (skill * 3);
  1009. if((skill = pc_checkskill(sd,NC_TRAININGAXE)) > 0)
  1010. damage += (skill * 5);
  1011. break;
  1012. case W_MACE:
  1013. case W_2HMACE:
  1014. if((skill = pc_checkskill(sd,PR_MACEMASTERY)) > 0)
  1015. damage += (skill * 3);
  1016. if((skill = pc_checkskill(sd,NC_TRAININGAXE)) > 0)
  1017. damage += (skill * 4);
  1018. break;
  1019. case W_FIST:
  1020. if((skill = pc_checkskill(sd,TK_RUN)) > 0)
  1021. damage += (skill * 10);
  1022. // No break, fallthrough to Knuckles
  1023. case W_KNUCKLE:
  1024. if((skill = pc_checkskill(sd,MO_IRONHAND)) > 0)
  1025. damage += (skill * 3);
  1026. break;
  1027. case W_MUSICAL:
  1028. if((skill = pc_checkskill(sd,BA_MUSICALLESSON)) > 0)
  1029. damage += (skill * 3);
  1030. break;
  1031. case W_WHIP:
  1032. if((skill = pc_checkskill(sd,DC_DANCINGLESSON)) > 0)
  1033. damage += (skill * 3);
  1034. break;
  1035. case W_BOOK:
  1036. if((skill = pc_checkskill(sd,SA_ADVANCEDBOOK)) > 0)
  1037. damage += (skill * 3);
  1038. break;
  1039. case W_KATAR:
  1040. if((skill = pc_checkskill(sd,AS_KATAR)) > 0)
  1041. damage += (skill * 3);
  1042. break;
  1043. }
  1044.  
  1045. return damage;
  1046. }
  1047. /*==========================================
  1048. * Calculates the standard damage of a normal attack assuming it hits,
  1049. * it calculates nothing extra fancy, is needed for magnum break's WATK_ELEMENT bonus. [Skotlex]
  1050. *------------------------------------------
  1051. * Pass damage2 as NULL to not calc it.
  1052. * Flag values:
  1053. * &1: Critical hit
  1054. * &2: Arrow attack
  1055. * &4: Skill is Magic Crasher
  1056. * &8: Skip target size adjustment (Extremity Fist?)
  1057. *&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)
  1058. */
  1059. static int battle_calc_base_damage(struct status_data *status, struct weapon_atk *wa, struct status_change *sc, unsigned short t_size, struct map_session_data *sd, int flag)
  1060. {
  1061. unsigned short atkmin = 0, atkmax = 0;
  1062. short type = 0;
  1063. int damage = 0;
  1064.  
  1065. if( !sd )
  1066. { //Mobs/Pets
  1067. if( flag&4 )
  1068. {
  1069. atkmin = status->matk_min;
  1070. atkmax = status->matk_max;
  1071. } else {
  1072. atkmin = wa->atk;
  1073. atkmax = wa->atk2;
  1074. }
  1075. if (atkmin > atkmax)
  1076. atkmin = atkmax;
  1077. } else { //PCs
  1078. atkmax = wa->atk;
  1079. type = (wa == &status->lhw)?EQI_HAND_L:EQI_HAND_R;
  1080.  
  1081. if (!(flag&1) || (flag&2))
  1082. { //Normal attacks
  1083. atkmin = status->dex;
  1084.  
  1085. if (sd->equip_index[type] >= 0 && sd->inventory_data[sd->equip_index[type]])
  1086. atkmin = atkmin*(80 + sd->inventory_data[sd->equip_index[type]]->wlv*20)/100;
  1087.  
  1088. if (atkmin > atkmax)
  1089. atkmin = atkmax;
  1090.  
  1091. if(flag&2 && !(flag&16))
  1092. { //Bows
  1093. atkmin = atkmin*atkmax/100;
  1094. if (atkmin > atkmax)
  1095. atkmax = atkmin;
  1096. }
  1097. }
  1098. }
  1099.  
  1100. if (sc && sc->data[SC_MAXIMIZEPOWER])
  1101. atkmin = atkmax;
  1102.  
  1103. //Weapon Damage calculation
  1104. if (!(flag&1))
  1105. damage = (atkmax>atkmin? rand()%(atkmax-atkmin):0)+atkmin;
  1106. else
  1107. damage = atkmax;
  1108.  
  1109. if (sd)
  1110. {
  1111. //rodatazone says the range is 0~arrow_atk-1 for non crit
  1112. if (flag&2 && sd->arrow_atk)
  1113. damage += ((flag&1)?sd->arrow_atk:rand()%sd->arrow_atk);
  1114.  
  1115. //SizeFix only for players
  1116. if (!(sd->special_state.no_sizefix || (flag&8)))
  1117. damage = damage*(type==EQI_HAND_L?
  1118. sd->left_weapon.atkmods[t_size]:
  1119. sd->right_weapon.atkmods[t_size])/100;
  1120. }
  1121.  
  1122. //Finally, add baseatk
  1123. if(flag&4)
  1124. damage += status->matk_min;
  1125. else
  1126. damage += status->batk;
  1127.  
  1128. //rodatazone says that Overrefine bonuses are part of baseatk
  1129. //Here we also apply the weapon_atk_rate bonus so it is correctly applied on left/right hands.
  1130. if(sd) {
  1131. if (type == EQI_HAND_L) {
  1132. if(sd->left_weapon.overrefine)
  1133. damage += rand()%sd->left_weapon.overrefine+1;
  1134. if (sd->weapon_atk_rate[sd->weapontype2])
  1135. damage += damage*sd->weapon_atk_rate[sd->weapontype2]/100;;
  1136. } else { //Right hand
  1137. if(sd->right_weapon.overrefine)
  1138. damage += rand()%sd->right_weapon.overrefine+1;
  1139. if (sd->weapon_atk_rate[sd->weapontype1])
  1140. damage += damage*sd->weapon_atk_rate[sd->weapontype1]/100;;
  1141. }
  1142. }
  1143. return damage;
  1144. }
  1145.  
  1146. /*==========================================
  1147. * Consumes ammo for the given skill.
  1148. *------------------------------------------*/
  1149. void battle_consume_ammo(TBL_PC*sd, int skill, int lv)
  1150. {
  1151. int qty=1;
  1152. if (!battle_config.arrow_decrement)
  1153. return;
  1154.  
  1155. if (skill)
  1156. {
  1157. qty = skill_get_ammo_qty(skill, lv);
  1158. if (!qty) qty = 1;
  1159. }
  1160.  
  1161. if(sd->equip_index[EQI_AMMO]>=0) //Qty check should have been done in skill_check_condition
  1162. pc_delitem(sd,sd->equip_index[EQI_AMMO],qty,0,1);
  1163.  
  1164. sd->state.arrow_atk = 0;
  1165. }
  1166.  
  1167. static int battle_range_type(
  1168. struct block_list *src, struct block_list *target,
  1169. int skill_num, int skill_lv)
  1170. { //Skill Range Criteria
  1171. if (battle_config.skillrange_by_distance &&
  1172. (src->type&battle_config.skillrange_by_distance)
  1173. ) { //based on distance between src/target [Skotlex]
  1174. if (check_distance_bl(src, target, 5))
  1175. return BF_SHORT;
  1176. return BF_LONG;
  1177. }
  1178. //based on used skill's range
  1179. if (skill_get_range2(src, skill_num, skill_lv) < 5)
  1180. return BF_SHORT;
  1181. return BF_LONG;
  1182. }
  1183.  
  1184. static int battle_blewcount_bonus(struct map_session_data *sd, int skill_num)
  1185. {
  1186. int i;
  1187. if (!sd->skillblown[0].id)
  1188. return 0;
  1189. //Apply the bonus blewcount. [Skotlex]
  1190. for (i = 0; i < ARRAYLENGTH(sd->skillblown) && sd->skillblown[i].id; i++) {
  1191. if (sd->skillblown[i].id == skill_num)
  1192. return sd->skillblown[i].val;
  1193. }
  1194. return 0;
  1195. }
  1196.  
  1197. struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list *target,int skill_num,int skill_lv,int mflag);
  1198. struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *target,int skill_num,int skill_lv,int mflag);
  1199.  
  1200. //For quick div adjustment.
  1201. #define damage_div_fix(dmg, div) { if (div > 1) (dmg)*=div; else if (div < 0) (div)*=-1; }
  1202. /*==========================================
  1203. * battle_calc_weapon_attack (by Skotlex)
  1204. *------------------------------------------*/
  1205. static struct Damage battle_calc_weapon_attack(struct block_list *src, struct block_list *target, int skill_num, int skill_lv, int wflag)
  1206. {
  1207. unsigned int skillratio = 100; //Skill dmg modifiers.
  1208. short skill=0;
  1209. short s_ele, s_ele_, t_class;
  1210. int i, nk, s_level;
  1211. bool n_ele = false; // non-elemental
  1212. char re_baselv_bonus = battle_config.renewal_baselvl_skill_ratio;//BaseLv config for renewal skills.
  1213. int chorusbonus = 0;//Chorus bonus value for chorus skills. Bonus remains 0 unless 3 or more Minstrel's/Wanderer's are in the party.
  1214.  
  1215. struct map_session_data *sd, *tsd;
  1216. struct Damage wd;
  1217. struct status_change *sc = status_get_sc(src);
  1218. struct status_change *tsc = status_get_sc(target);
  1219. struct status_data *sstatus = status_get_status_data(src);
  1220. struct status_data *tstatus = status_get_status_data(target);
  1221. struct {
  1222. unsigned hit : 1; //the attack Hit? (not a miss)
  1223. unsigned cri : 1; //Critical hit
  1224. unsigned idef : 1; //Ignore defense
  1225. unsigned idef2 : 1; //Ignore defense (left weapon)
  1226. unsigned pdef : 2; //Pierces defense (Investigate/Ice Pick)
  1227. unsigned pdef2 : 2; //1: Use def+def2/100, 2: Use def+def2/50
  1228. unsigned infdef : 1; //Infinite defense (plants)
  1229. unsigned arrow : 1; //Attack is arrow-based
  1230. unsigned rh : 1; //Attack considers right hand (wd.damage)
  1231. unsigned lh : 1; //Attack considers left hand (wd.damage2)
  1232. unsigned weapon : 1; //It's a weapon attack (consider VVS, and all that)
  1233. } flag;
  1234.  
  1235. memset(&wd,0,sizeof(wd));
  1236. memset(&flag,0,sizeof(flag));
  1237.  
  1238. if(src==NULL || target==NULL)
  1239. {
  1240. nullpo_info(NLP_MARK);
  1241. return wd;
  1242. }
  1243.  
  1244. s_level = status_get_lv(src);
  1245. if( skill_num >= RK_ENCHANTBLADE && skill_num <= LG_OVERBRAND_PLUSATK &&
  1246. battle_config.max_highlvl_nerf && s_level > battle_config.max_highlvl_nerf )
  1247. s_level = battle_config.max_highlvl_nerf;
  1248.  
  1249. //Initial flag
  1250. flag.rh = 1;
  1251. flag.weapon = 1;
  1252. flag.infdef =(tstatus->mode&MD_PLANT) ? 1 : 0;
  1253. if( !flag.infdef && (target->type == BL_SKILL && ((TBL_SKILL*)target)->group->unit_id == UNT_REVERBERATION) )
  1254. flag.infdef = 1; // Reberberation takes 1 damage
  1255.  
  1256. //Initial Values
  1257. wd.type = 0; //Normal attack
  1258. wd.div_ = skill_num?skill_get_num(skill_num,skill_lv):1;
  1259. wd.amotion = (skill_num && skill_get_inf(skill_num)&INF_GROUND_SKILL)?0:sstatus->amotion; //Amotion should be 0 for ground skills.
  1260. if( skill_num == KN_AUTOCOUNTER )
  1261. wd.amotion >>= 1;
  1262. wd.dmotion = tstatus->dmotion;
  1263. wd.blewcount = skill_get_blewcount(skill_num,skill_lv);
  1264. wd.flag = BF_WEAPON; //Initial Flag
  1265. wd.flag |= (skill_num||wflag)?BF_SKILL:BF_NORMAL; // Baphomet card's splash damage is counted as a skill. [Inkfish]
  1266. wd.dmg_lv = ATK_DEF; //This assumption simplifies the assignation later
  1267. nk = skill_get_nk(skill_num);
  1268. if( !skill_num && wflag ) //If flag, this is splash damage from Baphomet Card and it always hits.
  1269. nk |= NK_NO_CARDFIX_ATK|NK_IGNORE_FLEE;
  1270. flag.hit = nk&NK_IGNORE_FLEE?1:0;
  1271. flag.idef = flag.idef2 = nk&NK_IGNORE_DEF?1:0;
  1272.  
  1273. if (sc && !sc->count)
  1274. sc = NULL; //Skip checking as there are no status changes active.
  1275. if (tsc && !tsc->count)
  1276. tsc = NULL; //Skip checking as there are no status changes active.
  1277.  
  1278. sd = BL_CAST(BL_PC, src);
  1279. tsd = BL_CAST(BL_PC, target);
  1280.  
  1281. // Minstrel/Wanderer number check for chorus skills.
  1282. // Bonus remains 0 unless 3 or more Minstrel's/Wanderer's are in the party.
  1283. if( sd && sd->status.party_id && party_foreachsamemap(party_sub_count_chorus, sd, 0) > 7)
  1284. chorusbonus = 5;//Maximum effect possiable from 7 or more Minstrel's/Wanderer's
  1285. else if( sd && sd->status.party_id && party_foreachsamemap(party_sub_count_chorus, sd, 0) > 2)
  1286. chorusbonus = party_foreachsamemap(party_sub_count_chorus, sd, 0) - 2;//Effect bonus from additional Minstrel's/Wanderer's if not above the max possiable.
  1287.  
  1288. if(sd)
  1289. wd.blewcount += battle_blewcount_bonus(sd, skill_num);
  1290.  
  1291. //Set miscellaneous data that needs be filled regardless of hit/miss
  1292. if(
  1293. (sd && sd->state.arrow_atk) ||
  1294. (!sd && ((skill_num && skill_get_ammotype(skill_num)) || sstatus->rhw.range>3))
  1295. )
  1296. flag.arrow = 1;
  1297.  
  1298. if(skill_num){
  1299. wd.flag |= battle_range_type(src, target, skill_num, skill_lv);
  1300. switch(skill_num)
  1301. {
  1302. case MO_FINGEROFFENSIVE:
  1303. if(sd) {
  1304. if (battle_config.finger_offensive_type)
  1305. wd.div_ = 1;
  1306. else
  1307. wd.div_ = sd->spiritball_old;
  1308. }
  1309. break;
  1310. case HT_PHANTASMIC:
  1311. //Since these do not consume ammo, they need to be explicitly set as arrow attacks.
  1312. flag.arrow = 1;
  1313. break;
  1314.  
  1315. case CR_SHIELDBOOMERANG:
  1316. case PA_SHIELDCHAIN:
  1317. case LG_SHIELDPRESS:
  1318. case LG_EARTHDRIVE:
  1319. flag.weapon = 0;
  1320. break;
  1321.  
  1322. case KN_PIERCE:
  1323. case ML_PIERCE:
  1324. wd.div_= (wd.div_>0?tstatus->size+1:-(tstatus->size+1));
  1325. break;
  1326.  
  1327. case TF_DOUBLE: //For NPC used skill.
  1328. case GS_CHAINACTION:
  1329. wd.type = 0x08;
  1330. break;
  1331.  
  1332. case GS_GROUNDDRIFT:
  1333. case KN_SPEARSTAB:
  1334. case KN_BOWLINGBASH:
  1335. case MS_BOWLINGBASH:
  1336. case MO_BALKYOUNG:
  1337. case TK_TURNKICK:
  1338. wd.blewcount=0;
  1339. break;
  1340.  
  1341. case KN_AUTOCOUNTER:
  1342. wd.flag=(wd.flag&~BF_SKILLMASK)|BF_NORMAL;
  1343. break;
  1344.  
  1345. case NPC_CRITICALSLASH:
  1346. case LG_PINPOINTATTACK:
  1347. flag.cri = 1; //Always critical skill.
  1348. break;
  1349.  
  1350. case LK_SPIRALPIERCE:
  1351. if (!sd) wd.flag=(wd.flag&~(BF_RANGEMASK|BF_WEAPONMASK))|BF_LONG|BF_MISC;
  1352. break;
  1353.  
  1354. case EL_STONE_RAIN:
  1355. if( !(wflag&1) )
  1356. wd.div_ = 1;
  1357. break;
  1358. }
  1359. } else //Range for normal attacks.
  1360. wd.flag |= flag.arrow?BF_LONG:BF_SHORT;
  1361.  
  1362. if ( (!skill_num || skill_num == PA_SACRIFICE) && tstatus->flee2 && rand()%1000 < tstatus->flee2 )
  1363. { //Check for Lucky Dodge
  1364. wd.type=0x0b;
  1365. wd.dmg_lv=ATK_LUCKY;
  1366. if (wd.div_ < 0) wd.div_*=-1;
  1367. return wd;
  1368. }
  1369.  
  1370. t_class = status_get_class(target);
  1371. s_ele = s_ele_ = skill_get_ele(skill_num, skill_lv);
  1372. if( !skill_num || s_ele == -1 )
  1373. { //Take weapon's element
  1374. s_ele = sstatus->rhw.ele;
  1375. s_ele_ = sstatus->lhw.ele;
  1376. if( flag.arrow && sd && sd->arrow_ele )
  1377. s_ele = sd->arrow_ele;
  1378. if( battle_config.attack_attr_none&src->type )
  1379. n_ele = true; //Weapon's element is "not elemental"
  1380. }
  1381. else if( s_ele == -2 ) //Use enchantment's element
  1382. s_ele = s_ele_ = status_get_attack_sc_element(src,sc);
  1383. else if( s_ele == -3 ) //Use random element
  1384. s_ele = s_ele_ = rand()%ELE_MAX;
  1385. switch( skill_num )
  1386. {
  1387. case GS_GROUNDDRIFT:
  1388. s_ele = s_ele_ = wflag; //element comes in flag.
  1389. break;
  1390. case LK_SPIRALPIERCE:
  1391. if (!sd) n_ele = false; //forced neutral for monsters
  1392. break;
  1393. }
  1394.  
  1395. if(!skill_num)
  1396. { //Skills ALWAYS use ONLY your right-hand weapon (tested on Aegis 10.2)
  1397. if (sd && sd->weapontype1 == 0 && sd->weapontype2 > 0)
  1398. {
  1399. flag.rh=0;
  1400. flag.lh=1;
  1401. }
  1402. if (sstatus->lhw.atk)
  1403. flag.lh=1;
  1404. }
  1405.  
  1406. if( sd && !skill_num )
  1407. { //Check for double attack.
  1408. if( ( ( skill_lv = pc_checkskill(sd,TF_DOUBLE) ) > 0 && sd->weapontype1 == W_DAGGER )
  1409. || ( sd->double_rate > 0 && sd->weapontype1 != W_FIST ) ) //Will fail bare-handed
  1410. { //Success chance is not added, the higher one is used [Skotlex]
  1411. if( rand()%100 < ( 5*skill_lv > sd->double_rate ? 5*skill_lv : sd->double_rate ) )
  1412. {
  1413. wd.div_ = skill_get_num(TF_DOUBLE,skill_lv?skill_lv:1);
  1414. wd.type = 0x08;
  1415. }
  1416. }
  1417. else if( sd->weapontype1 == W_REVOLVER && (skill_lv = pc_checkskill(sd,GS_CHAINACTION)) > 0 && rand()%100 < 5*skill_lv )
  1418. {
  1419. wd.div_ = skill_get_num(GS_CHAINACTION,skill_lv);
  1420. wd.type = 0x08;
  1421. }
  1422. else if( sc && sc->data[SC_FEARBREEZE] && sd->weapontype1 == W_BOW && (i = sd->equip_index[EQI_AMMO]) >= 0 && sd->inventory_data[i] && sd->status.inventory[i].amount > 1 )
  1423. {
  1424. short rate[] = { 12, 12, 21, 27, 30 };
  1425. if( sc->data[SC_FEARBREEZE]->val1 > 0 && sc->data[SC_FEARBREEZE]->val1 < 6 && rand()%100 < rate[sc->data[SC_FEARBREEZE]->val1 - 1] )
  1426. {
  1427. wd.type = 0x08;
  1428. wd.div_ = 2 + (sc->data[SC_FEARBREEZE]->val1 > 2 ? rand()%(sc->data[SC_FEARBREEZE]->val1 - 2) : 0);
  1429. wd.div_ = min(wd.div_,sd->status.inventory[i].amount); // Reduce number of hits if you don't have enough arrows
  1430. sd->state.fearbreeze = wd.div_ - 1;
  1431. }
  1432. }
  1433. }
  1434.  
  1435. //Check for critical
  1436. if( !flag.cri && !(wd.type&0x08) && sstatus->cri &&
  1437. (!skill_num ||
  1438. skill_num == KN_AUTOCOUNTER ||
  1439. skill_num == SN_SHARPSHOOTING || skill_num == MA_SHARPSHOOTING ||
  1440. skill_num == NJ_KIRIKAGE))
  1441. {
  1442. short cri = sstatus->cri;
  1443. if (sd)
  1444. {
  1445. cri+= sd->critaddrace[tstatus->race];
  1446. if(flag.arrow)
  1447. cri += sd->arrow_cri;
  1448. if(sd->status.weapon == W_KATAR)
  1449. cri <<=1;
  1450. }
  1451. //The official equation is *2, but that only applies when sd's do critical.
  1452. //Therefore, we use the old value 3 on cases when an sd gets attacked by a mob
  1453. cri -= tstatus->luk*(!sd&&tsd?3:2);
  1454.  
  1455. if(tsc)
  1456. {
  1457. if (tsc->data[SC_SLEEP])
  1458. cri <<=1;
  1459. }
  1460. switch (skill_num)
  1461. {
  1462. case KN_AUTOCOUNTER:
  1463. if(battle_config.auto_counter_type &&
  1464. (battle_config.auto_counter_type&src->type))
  1465. flag.cri = 1;
  1466. else
  1467. cri <<= 1;
  1468. break;
  1469. case SN_SHARPSHOOTING:
  1470. case MA_SHARPSHOOTING:
  1471. cri += 200;
  1472. break;
  1473. case NJ_KIRIKAGE:
  1474. cri += 250 + 50*skill_lv;
  1475. break;
  1476. }
  1477. if(tsd && tsd->critical_def)
  1478. cri = cri*(100-tsd->critical_def)/100;
  1479. if (rand()%1000 < cri) // Steel need confirm if critical def reduce it.
  1480. flag.cri= 1;
  1481. }
  1482. if (flag.cri)
  1483. {
  1484. wd.type = 0x0a;
  1485. flag.idef = flag.idef2 = flag.hit = 1;
  1486. } else { //Check for Perfect Hit
  1487. if(sd && sd->perfect_hit > 0 && rand()%100 < sd->perfect_hit)
  1488. flag.hit = 1;
  1489. if (sc && sc->data[SC_FUSION]) {
  1490. flag.hit = 1; //SG_FUSION always hit [Komurka]
  1491. flag.idef = flag.idef2 = 1; //def ignore [Komurka]
  1492. }
  1493. if( !flag.hit )
  1494. switch(skill_num)
  1495. {
  1496. case AS_SPLASHER:
  1497. if( !wflag ) // Always hits the one exploding.
  1498. flag.hit = 1;
  1499. break;
  1500. case CR_SHIELDBOOMERANG:
  1501. if( sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_CRUSADER )
  1502. flag.hit = 1;
  1503. break;
  1504. }
  1505. if (tsc && !flag.hit && tsc->opt1 && tsc->opt1 != OPT1_STONEWAIT)
  1506. flag.hit = 1;
  1507. }
  1508.  
  1509. if (!flag.hit)
  1510. { //Hit/Flee calculation
  1511. short flee = tstatus->flee, hitrate=80; //Default hitrate
  1512.  
  1513. if( tsc && tsc->data[SC_NEUTRALBARRIER] && (wd.flag&(BF_SHORT|BF_MAGIC)) == BF_SHORT )
  1514. hitrate = 5; // Currently Neutral Barrier just do this
  1515. else
  1516. {
  1517. if(battle_config.agi_penalty_type &&
  1518. battle_config.agi_penalty_target&target->type)
  1519. {
  1520. unsigned char attacker_count; //256 max targets should be a sane max
  1521. attacker_count = unit_counttargeted(target,battle_config.agi_penalty_count_lv);
  1522. if(attacker_count >= battle_config.agi_penalty_count)
  1523. {
  1524. if (battle_config.agi_penalty_type == 1)
  1525. flee = (flee * (100 - (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num))/100;
  1526. else //asume type 2: absolute reduction
  1527. flee -= (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num;
  1528. if(flee < 1) flee = 1;
  1529. }
  1530. }
  1531.  
  1532. hitrate+= sstatus->hit - flee;
  1533.  
  1534. if(wd.flag&BF_LONG && !skill_num && //Fogwall's hit penalty is only for normal ranged attacks.
  1535. tsc && tsc->data[SC_FOGWALL])
  1536. hitrate -= 50;
  1537.  
  1538. if(sd && flag.arrow)
  1539. hitrate += sd->arrow_hit;
  1540. if(skill_num)
  1541. switch(skill_num)
  1542. { //Hit skill modifiers
  1543. //It is proven that bonus is applied on final hitrate, not hit.
  1544. case SM_BASH:
  1545. case MS_BASH:
  1546. hitrate += hitrate * 5 * skill_lv / 100;
  1547. break;
  1548. case MS_MAGNUM:
  1549. case SM_MAGNUM:
  1550. hitrate += hitrate * 10 * skill_lv / 100;
  1551. break;
  1552. case KN_AUTOCOUNTER:
  1553. case PA_SHIELDCHAIN:
  1554. case NPC_WATERATTACK:
  1555. case NPC_GROUNDATTACK:
  1556. case NPC_FIREATTACK:
  1557. case NPC_WINDATTACK:
  1558. case NPC_POISONATTACK:
  1559. case NPC_HOLYATTACK:
  1560. case NPC_DARKNESSATTACK:
  1561. case NPC_UNDEADATTACK:
  1562. case NPC_TELEKINESISATTACK:
  1563. case NPC_BLEEDING:
  1564. hitrate += hitrate * 20 / 100;
  1565. break;
  1566. case KN_PIERCE:
  1567. case ML_PIERCE:
  1568. hitrate += hitrate * 5 * skill_lv / 100;
  1569. break;
  1570. case AS_SONICBLOW:
  1571. if( sd && pc_checkskill(sd,AS_SONICACCEL) > 0 )
  1572. hitrate += hitrate * 50 / 100;
  1573. break;
  1574. case MC_CARTREVOLUTION:
  1575. case GN_CART_TORNADO:
  1576. case GN_CARTCANNON:
  1577. if( sd && pc_checkskill(sd, GN_REMODELING_CART) )
  1578. hitrate += pc_checkskill(sd, GN_REMODELING_CART) * 4;
  1579. break;
  1580. case GC_VENOMPRESSURE:
  1581. hitrate += 10 + 4 * skill_lv;
  1582. break;
  1583. case SC_FATALMENACE:
  1584. hitrate -= (35 - skill_lv * 5);
  1585. break;
  1586. case LG_BANISHINGPOINT:
  1587. hitrate += 3 * skill_lv;
  1588. break;
  1589. }
  1590.  
  1591. // Weaponry Research hidden bonus
  1592. if (sd && (skill = pc_checkskill(sd,BS_WEAPONRESEARCH)) > 0)
  1593. hitrate += hitrate * ( 2 * skill ) / 100;
  1594.  
  1595. if( sd && (sd->status.weapon == W_1HSWORD || sd->status.weapon == W_DAGGER) &&
  1596. (skill = pc_checkskill(sd, GN_TRAINING_SWORD))>0 )
  1597. hitrate += 3 * skill;
  1598. }
  1599.  
  1600. hitrate = cap_value(hitrate, battle_config.min_hitrate, battle_config.max_hitrate);
  1601.  
  1602. if(rand()%100 >= hitrate)
  1603. wd.dmg_lv = ATK_FLEE;
  1604. else
  1605. flag.hit = 1;
  1606. } //End hit/miss calculation
  1607.  
  1608. if (flag.hit && !flag.infdef) //No need to do the math for plants
  1609. { //Hitting attack
  1610.  
  1611. //Assuming that 99% of the cases we will not need to check for the flag.rh... we don't.
  1612. //ATK_RATE scales the damage. 100 = no change. 50 is halved, 200 is doubled, etc
  1613. #define ATK_RATE( a ) { wd.damage= wd.damage*(a)/100 ; if(flag.lh) wd.damage2= wd.damage2*(a)/100; }
  1614. #define ATK_RATE2( a , b ) { wd.damage= wd.damage*(a)/100 ; if(flag.lh) wd.damage2= wd.damage2*(b)/100; }
  1615. //Adds dmg%. 100 = +100% (double) damage. 10 = +10% damage
  1616. #define ATK_ADDRATE( a ) { wd.damage+= wd.damage*(a)/100 ; if(flag.lh) wd.damage2+= wd.damage2*(a)/100; }
  1617. #define ATK_ADDRATE2( a , b ) { wd.damage+= wd.damage*(a)/100 ; if(flag.lh) wd.damage2+= wd.damage2*(b)/100; }
  1618. //Adds an absolute value to damage. 100 = +100 damage
  1619. #define ATK_ADD( a ) { wd.damage+= a; if (flag.lh) wd.damage2+= a; }
  1620. #define ATK_ADD2( a , b ) { wd.damage+= a; if (flag.lh) wd.damage2+= b; }
  1621.  
  1622. switch (skill_num)
  1623. { //Calc base damage according to skill
  1624. // Below renewal multi hit Final Strike , MyRO
  1625. case NJ_ISSEN:
  1626. wd.div_ = 1;
  1627. if (sc && sc->data[SC_BUNSINJYUTSU] && sc->data[SC_BUNSINJYUTSU]->val2>0)
  1628. wd.div_ = (sc->data[SC_BUNSINJYUTSU]->val2)+2;
  1629. //[(ATK*40) + (HP*80%)] * (1+(0.25*Mirror illusion))
  1630. //wd.damage = 40*sstatus->batk +(skill_lv*8/100)*sstatus->hp;
  1631. wd.damage = 40*sstatus->batk +skill_lv*(sstatus->hp/10 + 35);
  1632. if(wd.div_!=1)
  1633. wd.damage = wd.damage *(1+sc->data[SC_BUNSINJYUTSU]->val2*25/100);
  1634. wd.damage = (wd.damage/wd.div_)/2;
  1635. // wd.damage = wd.damage/wd.div_;
  1636.  
  1637. wd.damage2 = 0;
  1638. status_set_hp(src, sstatus->max_hp/100, 0);
  1639. break;
  1640. case PA_SACRIFICE:
  1641. wd.damage = sstatus->max_hp* 9/100;
  1642. wd.damage2 = 0;
  1643. break;
  1644. // below edited for MyRO (below orig)
  1645. //case LK_SPIRALPIERCE:
  1646. //case ML_SPIRALPIERCE:
  1647. // if (sd) {
  1648. // short index = sd->equip_index[EQI_HAND_R];
  1649.  
  1650. // if (index >= 0 &&
  1651. // sd->inventory_data[index] &&
  1652. // sd->inventory_data[index]->type == IT_WEAPON)
  1653. // wd.damage = sd->inventory_data[index]->weight*8/100; //80% of weight
  1654. // } else
  1655. // wd.damage = sstatus->rhw.atk2*8/10; //Else use Atk2
  1656.  
  1657. // ATK_ADDRATE(50*skill_lv); //Skill modifier applies to weight only.
  1658. // i = sstatus->str/10;
  1659. // i*=i;
  1660. // ATK_ADD(i); //Add str bonus.
  1661. // if( sc && sc->data[SC_GLOOMYDAY_SK] && skill_num == LK_SPIRALPIERCE )
  1662. // ATK_ADD(50 + 5 * sc->data[SC_GLOOMYDAY_SK]->val1);
  1663. // switch (tstatus->size) { //Size-fix. Is this modified by weapon perfection?
  1664. // case 0: //Small: 125%
  1665. // ATK_RATE(125);
  1666. // break;
  1667. // //case 1: //Medium: 100%
  1668. // case 2: //Large: 75%
  1669. // ATK_RATE(75);
  1670. // break;
  1671. // }
  1672. // break;
  1673.  
  1674. // new spiral pierce formula below (MyRO) (based on wieght) (May 30, 2011)
  1675. case LK_SPIRALPIERCE:
  1676. case ML_SPIRALPIERCE:
  1677. wd.damage = sstatus->batk;
  1678. if (sd) {
  1679. short index = sd->equip_index[EQI_HAND_R];
  1680.  
  1681. if (index >= 0 &&
  1682. sd->inventory_data[index] &&
  1683. sd->inventory_data[index]->type == IT_WEAPON)
  1684. ATK_ADD(sd->inventory_data[index]->weight*5/100*skill_lv); //50% of weight * skill level [ADVENT]
  1685. /*wd.damage = sd->inventory_data[index]->weight*8/100; //80% of weight*/
  1686. } else
  1687. /*wd.damage = sstatus->rhw.atk2*8/10; //Else use Atk2*/
  1688. ATK_ADD((sstatus->rhw.atk2*5/10)*skill_lv);
  1689.  
  1690. skillratio += (150+(40*skill_lv));
  1691. if( sc && sc->data[SC_GLOOMYDAY_SK] && skill_num == LK_SPIRALPIERCE )
  1692. ATK_ADDRATE(100+25*(sc->data[SC_GLOOMYDAY_SK]->val1-1));
  1693. //wd.damage = wd.damage*(2 + (sc->data[SC_GLOOMYDAY_SK]->val1-(sc->data[SC_GLOOMYDAY_SK]->val1-1)));
  1694. //ATK_ADD(50 + 5 * sc->data[SC_GLOOMYDAY_SK]->val1);
  1695. switch (tstatus->size) { //Size-fix. Is this modified by weapon perfection?
  1696. case 0: //Small: 125%
  1697. ATK_RATE(125);
  1698. break;
  1699. //case 1: //Medium: 100%
  1700. case 2: //Large: 75%
  1701. ATK_RATE(75);
  1702. break;
  1703. }
  1704. break;
  1705. case CR_SHIELDBOOMERANG:
  1706. case PA_SHIELDCHAIN:
  1707. wd.damage = sstatus->batk;
  1708. if( sd )
  1709. {
  1710. int damagevalue = 0;
  1711. short index = sd->equip_index[EQI_HAND_L];
  1712. if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR )
  1713. damagevalue = sd->inventory_data[index]->weight/10;
  1714. if( sc && sc->data[SC_GLOOMYDAY_SK] )
  1715. damagevalue += damagevalue * (15 + rand()%sc->data[SC_GLOOMYDAY_SK]->val3) / 100;
  1716. ATK_ADD(damagevalue);
  1717. }
  1718. else
  1719. ATK_ADD(sstatus->rhw.atk2); //Else use Atk2
  1720. break;
  1721. case HFLI_SBR44: //[orn]
  1722. if(src->type == BL_HOM) {
  1723. wd.damage = ((TBL_HOM*)src)->homunculus.intimacy ;
  1724. break;
  1725. }
  1726. default:
  1727. {
  1728. i = (flag.cri?1:0)|
  1729. (flag.arrow?2:0)|
  1730. (skill_num == HW_MAGICCRASHER?4:0)|
  1731. (!skill_num && sc && sc->data[SC_CHANGE]?4:0)|
  1732. (skill_num == MO_EXTREMITYFIST?8:0)|
  1733. (sc && sc->data[SC_WEAPONPERFECTION]?8:0);
  1734. if (flag.arrow && sd)
  1735. switch(sd->status.weapon) {
  1736. case W_BOW:
  1737. case W_REVOLVER:
  1738. case W_GATLING:
  1739. case W_SHOTGUN:
  1740. case W_GRENADE:
  1741. break;
  1742. default:
  1743. i |= 16; // for ex. shuriken must not be influenced by DEX
  1744. }
  1745. wd.damage = battle_calc_base_damage(sstatus, &sstatus->rhw, sc, tstatus->size, sd, i);
  1746. if (flag.lh)
  1747. wd.damage2 = battle_calc_base_damage(sstatus, &sstatus->lhw, sc, tstatus->size, sd, i);
  1748.  
  1749. if (nk&NK_SPLASHSPLIT){ // Divide ATK among targets
  1750. if(wflag>0)
  1751. wd.damage/= wflag;
  1752. else
  1753. ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_num, skill_get_name(skill_num));
  1754. }
  1755.  
  1756. //Add any bonuses that modify the base baseatk+watk (pre-skills)
  1757. if( sd )
  1758. {
  1759. if( sd->atk_rate )
  1760. ATK_ADDRATE(sd->atk_rate);
  1761.  
  1762. if(flag.cri && sd->crit_atk_rate)
  1763. ATK_ADDRATE(sd->crit_atk_rate);
  1764.  
  1765. if( sd->status.party_id && (skill=pc_checkskill(sd,TK_POWER)) > 0 )
  1766. {
  1767. if( (i = party_foreachsamemap(party_sub_count, sd, 0)) > 1 ) // exclude the player himself [Inkfish]
  1768. ATK_ADDRATE(2*skill*i);
  1769. }
  1770. }
  1771. break;
  1772. } //End default case
  1773. } //End switch(skill_num)
  1774.  
  1775. //Skill damage modifiers that stack linearly
  1776. if(sc && skill_num != PA_SACRIFICE)
  1777. {
  1778. if(sc->data[SC_OVERTHRUST])
  1779. skillratio += sc->data[SC_OVERTHRUST]->val3;
  1780. if(sc->data[SC_MAXOVERTHRUST])
  1781. skillratio += sc->data[SC_MAXOVERTHRUST]->val2;
  1782. if(sc->data[SC_BERSERK])
  1783. skillratio += 100;
  1784. }
  1785. if( !skill_num )
  1786. { // Random chance to deal multiplied damage - Consider it as part of skill-based-damage
  1787. if( sd && sd->random_attack_increase_add > 0 && sd->random_attack_increase_per && rand()%100 < sd->random_attack_increase_per )
  1788. skillratio += sd->random_attack_increase_add;
  1789.  
  1790. ATK_RATE(skillratio);
  1791. }
  1792. else
  1793. {
  1794. switch( skill_num )
  1795. {
  1796. case SM_BASH:
  1797. case MS_BASH:
  1798. skillratio += 30*skill_lv;
  1799. break;
  1800. case SM_MAGNUM:
  1801. case MS_MAGNUM:
  1802. skillratio += 20*skill_lv;
  1803. break;
  1804. case MC_MAMMONITE:
  1805. skillratio += 50*skill_lv;
  1806. break;
  1807. case HT_POWER:
  1808. skillratio += -50+8*sstatus->str;
  1809. break;
  1810. case AC_DOUBLE:
  1811. case MA_DOUBLE:
  1812. skillratio += 10*(skill_lv-1);
  1813. break;
  1814. case AC_SHOWER:
  1815. case MA_SHOWER:
  1816. skillratio += 5*skill_lv-25;
  1817. break;
  1818. case AC_CHARGEARROW:
  1819. case MA_CHARGEARROW:
  1820. skillratio += 50;
  1821. break;
  1822. case HT_FREEZINGTRAP:
  1823. case MA_FREEZINGTRAP:
  1824. skillratio += -50+10*skill_lv;
  1825. break;
  1826. case KN_PIERCE:
  1827. case ML_PIERCE:
  1828. skillratio += 10*skill_lv;
  1829. break;
  1830. case MER_CRASH:
  1831. skillratio += 10*skill_lv;
  1832. break;
  1833. case KN_SPEARSTAB:
  1834. skillratio += 15*skill_lv;
  1835. break;
  1836. case KN_SPEARBOOMERANG:
  1837. skillratio += 50*skill_lv;
  1838. break;
  1839. case KN_BRANDISHSPEAR:
  1840. case ML_BRANDISH:
  1841. {
  1842. int ratio = 100+20*skill_lv;
  1843. skillratio += ratio-100;
  1844. if(skill_lv>3 && wflag==1) skillratio += ratio/2;
  1845. if(skill_lv>6 && wflag==1) skillratio += ratio/4;
  1846. if(skill_lv>9 && wflag==1) skillratio += ratio/8;
  1847. if(skill_lv>6 && wflag==2) skillratio += ratio/2;
  1848. if(skill_lv>9 && wflag==2) skillratio += ratio/4;
  1849. if(skill_lv>9 && wflag==3) skillratio += ratio/2;
  1850. if( sc && sc->data[SC_GLOOMYDAY_SK] )
  1851. skillratio += skillratio * (15 + rand()%sc->data[SC_GLOOMYDAY_SK]->val3) / 100;
  1852. break;
  1853. }
  1854. case KN_BOWLINGBASH:
  1855. case MS_BOWLINGBASH:
  1856. skillratio+= 40*skill_lv;
  1857. break;
  1858. case AS_GRIMTOOTH:
  1859. skillratio += 20*skill_lv;
  1860. break;
  1861. case AS_POISONREACT:
  1862. skillratio += 30*skill_lv;
  1863. break;
  1864. case AS_SONICBLOW:
  1865. skillratio += -50+5*skill_lv;
  1866. break;
  1867. case TF_SPRINKLESAND:
  1868. skillratio += 30;
  1869. break;
  1870. case MC_CARTREVOLUTION:
  1871. skillratio += 50;
  1872. if(sd && sd->cart_weight)
  1873. skillratio += 100*sd->cart_weight/battle_config.max_cart_weight; // +1% every 1% weight
  1874. else if (!sd)
  1875. skillratio += 100; //Max damage for non players.
  1876. break;
  1877. case NPC_RANDOMATTACK:
  1878. skillratio += 100 * skill_lv;
  1879. break;
  1880. case NPC_WATERATTACK:
  1881. case NPC_GROUNDATTACK:
  1882. case NPC_FIREATTACK:
  1883. case NPC_WINDATTACK:
  1884. case NPC_POISONATTACK:
  1885. case NPC_HOLYATTACK:
  1886. case NPC_DARKNESSATTACK:
  1887. case NPC_UNDEADATTACK:
  1888. case NPC_TELEKINESISATTACK:
  1889. case NPC_BLOODDRAIN:
  1890. case NPC_ACIDBREATH:
  1891. case NPC_DARKNESSBREATH:
  1892. case NPC_FIREBREATH:
  1893. case NPC_ICEBREATH:
  1894. case NPC_THUNDERBREATH:
  1895. case NPC_HELLJUDGEMENT:
  1896. case NPC_PULSESTRIKE:
  1897. skillratio += 100*(skill_lv-1);
  1898. break;
  1899. case RG_BACKSTAP:
  1900. if(sd && sd->status.weapon == W_BOW && battle_config.backstab_bow_penalty)
  1901. skillratio += (200+40*skill_lv)/2;
  1902. else
  1903. skillratio += 200+40*skill_lv;
  1904. break;
  1905. case RG_RAID:
  1906. skillratio += 40*skill_lv;
  1907. break;
  1908. case RG_INTIMIDATE:
  1909. skillratio += 30*skill_lv;
  1910. break;
  1911. case CR_SHIELDCHARGE:
  1912. skillratio += 20*skill_lv;
  1913. if( sc && sc->data[SC_GLOOMYDAY_SK] )
  1914. skillratio += skillratio * (15 + rand()%sc->data[SC_GLOOMYDAY_SK]->val3) / 100;
  1915. break;
  1916. case CR_SHIELDBOOMERANG:
  1917. skillratio += 30*skill_lv;
  1918. if( sc && sc->data[SC_GLOOMYDAY_SK] )
  1919. skillratio += skillratio * (15 + rand()%sc->data[SC_GLOOMYDAY_SK]->val3) / 100;
  1920. break;
  1921. case NPC_DARKCROSS:
  1922. case CR_HOLYCROSS:
  1923. skillratio += 35*skill_lv;
  1924. break;
  1925. case AM_DEMONSTRATION:
  1926. skillratio += 20*skill_lv;
  1927. break;
  1928. case AM_ACIDTERROR:
  1929. skillratio += 40*skill_lv;
  1930. break;
  1931. case MO_FINGEROFFENSIVE:
  1932. skillratio+= 50 * skill_lv;
  1933. break;
  1934. case MO_INVESTIGATE:
  1935. skillratio += 75*skill_lv;
  1936. flag.pdef = flag.pdef2 = 2;
  1937. break;
  1938. case MO_EXTREMITYFIST:
  1939. { //Overflow check. [Skotlex]
  1940. unsigned int ratio = skillratio + 100*(8 + sstatus->sp/10);
  1941. //You'd need something like 6K SP to reach this max, so should be fine for most purposes.
  1942. if (ratio > 60000) ratio = 60000; //We leave some room here in case skillratio gets further increased.
  1943. skillratio = (unsigned short)ratio;
  1944. status_set_sp(src, 0, 0);
  1945. }
  1946. break;
  1947. case MO_TRIPLEATTACK:
  1948. skillratio += 20*skill_lv;
  1949. break;
  1950. case MO_CHAINCOMBO:
  1951. skillratio += 50+50*skill_lv;
  1952. break;
  1953. case MO_COMBOFINISH:
  1954. skillratio += 140+60*skill_lv;
  1955. break;
  1956. case BA_MUSICALSTRIKE:
  1957. case DC_THROWARROW:
  1958. skillratio += 25+25*skill_lv;
  1959. break;
  1960. case CH_TIGERFIST:
  1961. skillratio += 100*skill_lv-60;
  1962. break;
  1963. case CH_CHAINCRUSH:
  1964. skillratio += 300+100*skill_lv;
  1965. break;
  1966. case CH_PALMSTRIKE:
  1967. skillratio += 100+100*skill_lv;
  1968. break;
  1969. case LK_HEADCRUSH:
  1970. skillratio += 40*skill_lv;
  1971. break;
  1972. case LK_JOINTBEAT:
  1973. i = 10*skill_lv-50;
  1974. // Although not clear, it's being assumed that the 2x damage is only for the break neck ailment.
  1975. if (wflag&BREAK_NECK) i*=2;
  1976. skillratio += i;
  1977. break;
  1978. case ASC_METEORASSAULT:
  1979. skillratio += 40*skill_lv-60;
  1980. break;
  1981. case SN_SHARPSHOOTING:
  1982. case MA_SHARPSHOOTING:
  1983. skillratio += 100 + 50 * skill_lv;
  1984. break;
  1985. case CG_ARROWVULCAN:
  1986. skillratio += 100+100*skill_lv;
  1987. break;
  1988. case AS_SPLASHER:
  1989. skillratio += 400+50*skill_lv;
  1990. if(sd)
  1991. skillratio += 30 * pc_checkskill(sd,AS_POISONREACT);
  1992. break;
  1993. case ASC_BREAKER:
  1994. skillratio += 100*skill_lv-100;
  1995. break;
  1996. case PA_SACRIFICE:
  1997. skillratio += 10*skill_lv-10;
  1998. break;
  1999. case PA_SHIELDCHAIN:
  2000. skillratio += 30*skill_lv;
  2001. if( sc && sc->data[SC_GLOOMYDAY_SK] )
  2002. skillratio += skillratio * (15 + rand()%sc->data[SC_GLOOMYDAY_SK]->val3) / 100;
  2003. break;
  2004. case WS_CARTTERMINATION:
  2005. i = 12 * (16 - skill_lv);
  2006. if (i < 1) i = 1;
  2007. //Preserve damage ratio when max cart weight is changed.
  2008. if(sd && sd->cart_weight)
  2009. skillratio += sd->cart_weight/i * 80000/battle_config.max_cart_weight - 100;
  2010. else if (!sd)
  2011. skillratio += 80000 / i - 100;
  2012. break;
  2013. case TK_DOWNKICK:
  2014. skillratio += 60 + 20*skill_lv;
  2015. break;
  2016. case TK_STORMKICK:
  2017. skillratio += 60 + 20*skill_lv;
  2018. break;
  2019. case TK_TURNKICK:
  2020. skillratio += 90 + 30*skill_lv;
  2021. break;
  2022. case TK_COUNTER:
  2023. skillratio += 90 + 30*skill_lv;
  2024. break;
  2025. case TK_JUMPKICK:
  2026. skillratio += -70 + 10*skill_lv;
  2027. if (sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == skill_num)
  2028. skillratio += 10*s_level/3; //Tumble bonus
  2029. if (wflag)
  2030. {
  2031. skillratio += 10*s_level/3; //Running bonus (TODO: What is the real bonus?
Advertisement
Add Comment
Please, Sign In to add comment