yuhsing

Untitled

Feb 23rd, 2013
72
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 230.84 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. if( !damage )
  811. return 0;
  812.  
  813. if( bl->type == BL_MOB )
  814. {
  815. struct mob_data* md = BL_CAST(BL_MOB, bl);
  816. if( map[bl->m].flag.battleground && (md->class_ == 1914 || md->class_ == 1915) && flag&BF_SKILL )
  817. return 0; // Crystal cannot receive skill damage on battlegrounds
  818.  
  819. // emistry - skill immune + 1 damage only
  820. if(md->class_ == 1084 || md->class_ == 1085){
  821. return (( flag&BF_SKILL )? 0:1 );
  822. }
  823. }
  824.  
  825. switch( skill_num )
  826. {
  827. case PA_PRESSURE:
  828. case HW_GRAVITATION:
  829. case NJ_ZENYNAGE:
  830. //case RK_DRAGONBREATH:
  831. //case GN_HELLS_PLANT_ATK:
  832. //case KO_MUCHANAGE:
  833. break;
  834. default:
  835. if( flag&BF_SKILL )
  836. { //Skills get a different reduction than non-skills. [Skotlex]
  837. if( flag&BF_WEAPON )
  838. damage = damage * battle_config.bg_weapon_damage_rate/100;
  839. if( flag&BF_MAGIC )
  840. damage = damage * battle_config.bg_magic_damage_rate/100;
  841. if( flag&BF_MISC )
  842. damage = damage * battle_config.bg_misc_damage_rate/100;
  843. }
  844. else
  845. { //Normal attacks get reductions based on range.
  846. if( flag&BF_SHORT )
  847. damage = damage * battle_config.bg_short_damage_rate/100;
  848. if( flag&BF_LONG )
  849. damage = damage * battle_config.bg_long_damage_rate/100;
  850. }
  851.  
  852. if( !damage ) damage = 1;
  853. }
  854.  
  855. return damage;
  856. }
  857.  
  858. /*==========================================
  859. * Calculates GVG related damage adjustments.
  860. *------------------------------------------*/
  861. 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)
  862. {
  863. struct mob_data* md = BL_CAST(BL_MOB, bl);
  864. int class_ = status_get_class(bl);
  865.  
  866. // emistry - immune to skills and only receive 1 damage.
  867. if( class_ == 1084 || class_ == 1085 ){
  868. return (( flag&BF_SKILL )? 0:1 );
  869. }
  870.  
  871. if (!damage) //No reductions to make.
  872. return 0;
  873.  
  874. if(md && md->guardian_data) {
  875. if(class_ == MOBID_EMPERIUM && flag&BF_SKILL)
  876. //Skill immunity.
  877. switch (skill_num) {
  878. case MO_TRIPLEATTACK:
  879. case HW_GRAVITATION:
  880. break;
  881. default:
  882. return 0;
  883. }
  884. if(src->type != BL_MOB) {
  885. struct guild *g=guild_search(status_get_guild_id(src));
  886. if (!g) return 0;
  887. if (class_ == MOBID_EMPERIUM && guild_checkskill(g,GD_APPROVAL) <= 0)
  888. return 0;
  889. if (battle_config.guild_max_castles && guild_checkcastles(g)>=battle_config.guild_max_castles)
  890. return 0; // [MouseJstr]
  891. }
  892. }
  893.  
  894. switch (skill_num) {
  895. //Skills with no damage reduction.
  896. case PA_PRESSURE:
  897. case HW_GRAVITATION:
  898. case NJ_ZENYNAGE:
  899. //case RK_DRAGONBREATH:
  900. //case GN_HELLS_PLANT_ATK:
  901. //case KO_MUCHANAGE:
  902. break;
  903. default:
  904. if (md && md->guardian_data) {
  905. damage -= damage * (md->guardian_data->castle->defense/100) * battle_config.castle_defense_rate/100;
  906. }
  907. if (flag & BF_SKILL) { //Skills get a different reduction than non-skills. [Skotlex]
  908. if (flag&BF_WEAPON)
  909. damage = damage * battle_config.gvg_weapon_damage_rate/100;
  910. if (flag&BF_MAGIC)
  911. damage = damage * battle_config.gvg_magic_damage_rate/100;
  912. if (flag&BF_MISC)
  913. damage = damage * battle_config.gvg_misc_damage_rate/100;
  914. } else { //Normal attacks get reductions based on range.
  915. if (flag & BF_SHORT)
  916. damage = damage * battle_config.gvg_short_damage_rate/100;
  917. if (flag & BF_LONG)
  918. damage = damage * battle_config.gvg_long_damage_rate/100;
  919. }
  920. if(!damage) damage = 1;
  921. }
  922. return damage;
  923. }
  924.  
  925. /*==========================================
  926. * HP/SP?z???ì?v?Z
  927. *------------------------------------------*/
  928. static int battle_calc_drain(int damage, int rate, int per)
  929. {
  930. int diff = 0;
  931.  
  932. if (per && rand()%1000 < rate) {
  933. diff = (damage * per) / 100;
  934. if (diff == 0) {
  935. if (per > 0)
  936. diff = 1;
  937. else
  938. diff = -1;
  939. }
  940. }
  941. return diff;
  942. }
  943.  
  944. /*==========================================
  945. * ?C—??_??[?W
  946. *------------------------------------------*/
  947. int battle_addmastery(struct map_session_data *sd,struct block_list *target,int dmg,int type)
  948. {
  949. int damage,skill;
  950. struct status_data *status = status_get_status_data(target);
  951. int weapon;
  952. damage = dmg;
  953.  
  954. nullpo_ret(sd);
  955.  
  956. if((skill = pc_checkskill(sd,AL_DEMONBANE)) > 0 &&
  957. target->type == BL_MOB && //This bonus doesnt work against players.
  958. (battle_check_undead(status->race,status->def_ele) || status->race==RC_DEMON) )
  959. damage += (skill*(int)(3+(sd->status.base_level+1)*0.05)); // submitted by orn
  960. //damage += (skill * 3);
  961.  
  962. if((skill = pc_checkskill(sd,HT_BEASTBANE)) > 0 && (status->race==RC_BRUTE || status->race==RC_INSECT) ) {
  963. damage += (skill * 4);
  964. if (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_HUNTER)
  965. damage += sd->status.str;
  966. }
  967.  
  968. if( (skill = pc_checkskill(sd, RA_RANGERMAIN)) > 0 && (status->race == RC_BRUTE || status->race == RC_PLANT || status->race == RC_FISH) )
  969. damage += (skill * 5);
  970.  
  971. if( (skill = pc_checkskill(sd,NC_RESEARCHFE)) > 0 && (status->def_ele == ELE_FIRE || status->def_ele == ELE_EARTH) )
  972. damage += (skill * 10);
  973.  
  974. if( pc_isriding(sd, OPTION_MADO) )
  975. damage += 15 * pc_checkskill(sd, NC_MADOLICENCE);
  976.  
  977. if(type == 0)
  978. weapon = sd->weapontype1;
  979. else
  980. weapon = sd->weapontype2;
  981. switch(weapon)
  982. {
  983. case W_DAGGER:
  984. case W_1HSWORD:
  985. if((skill = pc_checkskill(sd,SM_SWORD)) > 0)
  986. damage += (skill * 4);
  987. if((skill = pc_checkskill(sd,GN_TRAINING_SWORD)) > 0)
  988. damage += skill * 10;
  989. break;
  990. case W_2HSWORD:
  991. if((skill = pc_checkskill(sd,SM_TWOHAND)) > 0)
  992. damage += (skill * 4);
  993. break;
  994. case W_1HSPEAR:
  995. case W_2HSPEAR:
  996. if((skill = pc_checkskill(sd,KN_SPEARMASTERY)) > 0) {
  997. if(!pc_isriding(sd, OPTION_RIDING|OPTION_RIDING_DRAGON))
  998. damage += skill * 4;
  999. else
  1000. damage += skill * (5 + pc_checkskill(sd,RK_DRAGONTRAINING));//Mastery damage is higher when on a Dragon Mount. [Rytech]
  1001. }
  1002. break;
  1003. case W_1HAXE:
  1004. case W_2HAXE:
  1005. if((skill = pc_checkskill(sd,AM_AXEMASTERY)) > 0)
  1006. damage += (skill * 3);
  1007. if((skill = pc_checkskill(sd,NC_TRAININGAXE)) > 0)
  1008. damage += (skill * 5);
  1009. break;
  1010. case W_MACE:
  1011. case W_2HMACE:
  1012. if((skill = pc_checkskill(sd,PR_MACEMASTERY)) > 0)
  1013. damage += (skill * 3);
  1014. if((skill = pc_checkskill(sd,NC_TRAININGAXE)) > 0)
  1015. damage += (skill * 4);
  1016. break;
  1017. case W_FIST:
  1018. if((skill = pc_checkskill(sd,TK_RUN)) > 0)
  1019. damage += (skill * 10);
  1020. // No break, fallthrough to Knuckles
  1021. case W_KNUCKLE:
  1022. if((skill = pc_checkskill(sd,MO_IRONHAND)) > 0)
  1023. damage += (skill * 3);
  1024. break;
  1025. case W_MUSICAL:
  1026. if((skill = pc_checkskill(sd,BA_MUSICALLESSON)) > 0)
  1027. damage += (skill * 3);
  1028. break;
  1029. case W_WHIP:
  1030. if((skill = pc_checkskill(sd,DC_DANCINGLESSON)) > 0)
  1031. damage += (skill * 3);
  1032. break;
  1033. case W_BOOK:
  1034. if((skill = pc_checkskill(sd,SA_ADVANCEDBOOK)) > 0)
  1035. damage += (skill * 3);
  1036. break;
  1037. case W_KATAR:
  1038. if((skill = pc_checkskill(sd,AS_KATAR)) > 0)
  1039. damage += (skill * 3);
  1040. break;
  1041. }
  1042.  
  1043. return damage;
  1044. }
  1045. /*==========================================
  1046. * Calculates the standard damage of a normal attack assuming it hits,
  1047. * it calculates nothing extra fancy, is needed for magnum break's WATK_ELEMENT bonus. [Skotlex]
  1048. *------------------------------------------
  1049. * Pass damage2 as NULL to not calc it.
  1050. * Flag values:
  1051. * &1: Critical hit
  1052. * &2: Arrow attack
  1053. * &4: Skill is Magic Crasher
  1054. * &8: Skip target size adjustment (Extremity Fist?)
  1055. *&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)
  1056. */
  1057. 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)
  1058. {
  1059. unsigned short atkmin = 0, atkmax = 0;
  1060. short type = 0;
  1061. int damage = 0;
  1062.  
  1063. if( !sd )
  1064. { //Mobs/Pets
  1065. if( flag&4 )
  1066. {
  1067. atkmin = status->matk_min;
  1068. atkmax = status->matk_max;
  1069. } else {
  1070. atkmin = wa->atk;
  1071. atkmax = wa->atk2;
  1072. }
  1073. if (atkmin > atkmax)
  1074. atkmin = atkmax;
  1075. } else { //PCs
  1076. atkmax = wa->atk;
  1077. type = (wa == &status->lhw)?EQI_HAND_L:EQI_HAND_R;
  1078.  
  1079. if (!(flag&1) || (flag&2))
  1080. { //Normal attacks
  1081. atkmin = status->dex;
  1082.  
  1083. if (sd->equip_index[type] >= 0 && sd->inventory_data[sd->equip_index[type]])
  1084. atkmin = atkmin*(80 + sd->inventory_data[sd->equip_index[type]]->wlv*20)/100;
  1085.  
  1086. if (atkmin > atkmax)
  1087. atkmin = atkmax;
  1088.  
  1089. if(flag&2 && !(flag&16))
  1090. { //Bows
  1091. atkmin = atkmin*atkmax/100;
  1092. if (atkmin > atkmax)
  1093. atkmax = atkmin;
  1094. }
  1095. }
  1096. }
  1097.  
  1098. if (sc && sc->data[SC_MAXIMIZEPOWER])
  1099. atkmin = atkmax;
  1100.  
  1101. //Weapon Damage calculation
  1102. if (!(flag&1))
  1103. damage = (atkmax>atkmin? rand()%(atkmax-atkmin):0)+atkmin;
  1104. else
  1105. damage = atkmax;
  1106.  
  1107. if (sd)
  1108. {
  1109. //rodatazone says the range is 0~arrow_atk-1 for non crit
  1110. if (flag&2 && sd->arrow_atk)
  1111. damage += ((flag&1)?sd->arrow_atk:rand()%sd->arrow_atk);
  1112.  
  1113. //SizeFix only for players
  1114. if (!(sd->special_state.no_sizefix || (flag&8)))
  1115. damage = damage*(type==EQI_HAND_L?
  1116. sd->left_weapon.atkmods[t_size]:
  1117. sd->right_weapon.atkmods[t_size])/100;
  1118. }
  1119.  
  1120. //Finally, add baseatk
  1121. if(flag&4)
  1122. damage += status->matk_min;
  1123. else
  1124. damage += status->batk;
  1125.  
  1126. //rodatazone says that Overrefine bonuses are part of baseatk
  1127. //Here we also apply the weapon_atk_rate bonus so it is correctly applied on left/right hands.
  1128. if(sd) {
  1129. if (type == EQI_HAND_L) {
  1130. if(sd->left_weapon.overrefine)
  1131. damage += rand()%sd->left_weapon.overrefine+1;
  1132. if (sd->weapon_atk_rate[sd->weapontype2])
  1133. damage += damage*sd->weapon_atk_rate[sd->weapontype2]/100;;
  1134. } else { //Right hand
  1135. if(sd->right_weapon.overrefine)
  1136. damage += rand()%sd->right_weapon.overrefine+1;
  1137. if (sd->weapon_atk_rate[sd->weapontype1])
  1138. damage += damage*sd->weapon_atk_rate[sd->weapontype1]/100;;
  1139. }
  1140. }
  1141. return damage;
  1142. }
  1143.  
  1144. /*==========================================
  1145. * Consumes ammo for the given skill.
  1146. *------------------------------------------*/
  1147. void battle_consume_ammo(TBL_PC*sd, int skill, int lv)
  1148. {
  1149. int qty=1;
  1150. if (!battle_config.arrow_decrement)
  1151. return;
  1152.  
  1153. if (skill)
  1154. {
  1155. qty = skill_get_ammo_qty(skill, lv);
  1156. if (!qty) qty = 1;
  1157. }
  1158.  
  1159. if(sd->equip_index[EQI_AMMO]>=0) //Qty check should have been done in skill_check_condition
  1160. pc_delitem(sd,sd->equip_index[EQI_AMMO],qty,0,1);
  1161.  
  1162. sd->state.arrow_atk = 0;
  1163. }
  1164.  
  1165. static int battle_range_type(
  1166. struct block_list *src, struct block_list *target,
  1167. int skill_num, int skill_lv)
  1168. { //Skill Range Criteria
  1169. if (battle_config.skillrange_by_distance &&
  1170. (src->type&battle_config.skillrange_by_distance)
  1171. ) { //based on distance between src/target [Skotlex]
  1172. if (check_distance_bl(src, target, 5))
  1173. return BF_SHORT;
  1174. return BF_LONG;
  1175. }
  1176. //based on used skill's range
  1177. if (skill_get_range2(src, skill_num, skill_lv) < 5)
  1178. return BF_SHORT;
  1179. return BF_LONG;
  1180. }
  1181.  
  1182. static int battle_blewcount_bonus(struct map_session_data *sd, int skill_num)
  1183. {
  1184. int i;
  1185. if (!sd->skillblown[0].id)
  1186. return 0;
  1187. //Apply the bonus blewcount. [Skotlex]
  1188. for (i = 0; i < ARRAYLENGTH(sd->skillblown) && sd->skillblown[i].id; i++) {
  1189. if (sd->skillblown[i].id == skill_num)
  1190. return sd->skillblown[i].val;
  1191. }
  1192. return 0;
  1193. }
  1194.  
  1195. struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list *target,int skill_num,int skill_lv,int mflag);
  1196. struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *target,int skill_num,int skill_lv,int mflag);
  1197.  
  1198. //For quick div adjustment.
  1199. #define damage_div_fix(dmg, div) { if (div > 1) (dmg)*=div; else if (div < 0) (div)*=-1; }
  1200. /*==========================================
  1201. * battle_calc_weapon_attack (by Skotlex)
  1202. *------------------------------------------*/
  1203. static struct Damage battle_calc_weapon_attack(struct block_list *src, struct block_list *target, int skill_num, int skill_lv, int wflag)
  1204. {
  1205. unsigned int skillratio = 100; //Skill dmg modifiers.
  1206. short skill=0;
  1207. short s_ele, s_ele_, t_class;
  1208. int i, nk, s_level;
  1209. bool n_ele = false; // non-elemental
  1210. char re_baselv_bonus = battle_config.renewal_baselvl_skill_ratio;//BaseLv config for renewal skills.
  1211. int chorusbonus = 0;//Chorus bonus value for chorus skills. Bonus remains 0 unless 3 or more Minstrel's/Wanderer's are in the party.
  1212.  
  1213. struct map_session_data *sd, *tsd;
  1214. struct Damage wd;
  1215. struct status_change *sc = status_get_sc(src);
  1216. struct status_change *tsc = status_get_sc(target);
  1217. struct status_data *sstatus = status_get_status_data(src);
  1218. struct status_data *tstatus = status_get_status_data(target);
  1219. struct {
  1220. unsigned hit : 1; //the attack Hit? (not a miss)
  1221. unsigned cri : 1; //Critical hit
  1222. unsigned idef : 1; //Ignore defense
  1223. unsigned idef2 : 1; //Ignore defense (left weapon)
  1224. unsigned pdef : 2; //Pierces defense (Investigate/Ice Pick)
  1225. unsigned pdef2 : 2; //1: Use def+def2/100, 2: Use def+def2/50
  1226. unsigned infdef : 1; //Infinite defense (plants)
  1227. unsigned arrow : 1; //Attack is arrow-based
  1228. unsigned rh : 1; //Attack considers right hand (wd.damage)
  1229. unsigned lh : 1; //Attack considers left hand (wd.damage2)
  1230. unsigned weapon : 1; //It's a weapon attack (consider VVS, and all that)
  1231. } flag;
  1232.  
  1233. memset(&wd,0,sizeof(wd));
  1234. memset(&flag,0,sizeof(flag));
  1235.  
  1236. if(src==NULL || target==NULL)
  1237. {
  1238. nullpo_info(NLP_MARK);
  1239. return wd;
  1240. }
  1241.  
  1242. s_level = status_get_lv(src);
  1243. if( skill_num >= RK_ENCHANTBLADE && skill_num <= LG_OVERBRAND_PLUSATK &&
  1244. battle_config.max_highlvl_nerf && s_level > battle_config.max_highlvl_nerf )
  1245. s_level = battle_config.max_highlvl_nerf;
  1246.  
  1247. //Initial flag
  1248. flag.rh = 1;
  1249. flag.weapon = 1;
  1250. flag.infdef =(tstatus->mode&MD_PLANT) ? 1 : 0;
  1251. if( !flag.infdef && (target->type == BL_SKILL && ((TBL_SKILL*)target)->group->unit_id == UNT_REVERBERATION) )
  1252. flag.infdef = 1; // Reberberation takes 1 damage
  1253.  
  1254. //Initial Values
  1255. wd.type = 0; //Normal attack
  1256. wd.div_ = skill_num?skill_get_num(skill_num,skill_lv):1;
  1257. wd.amotion = (skill_num && skill_get_inf(skill_num)&INF_GROUND_SKILL)?0:sstatus->amotion; //Amotion should be 0 for ground skills.
  1258. if( skill_num == KN_AUTOCOUNTER )
  1259. wd.amotion >>= 1;
  1260. wd.dmotion = tstatus->dmotion;
  1261. wd.blewcount = skill_get_blewcount(skill_num,skill_lv);
  1262. wd.flag = BF_WEAPON; //Initial Flag
  1263. wd.flag |= (skill_num||wflag)?BF_SKILL:BF_NORMAL; // Baphomet card's splash damage is counted as a skill. [Inkfish]
  1264. wd.dmg_lv = ATK_DEF; //This assumption simplifies the assignation later
  1265. nk = skill_get_nk(skill_num);
  1266. if( !skill_num && wflag ) //If flag, this is splash damage from Baphomet Card and it always hits.
  1267. nk |= NK_NO_CARDFIX_ATK|NK_IGNORE_FLEE;
  1268. flag.hit = nk&NK_IGNORE_FLEE?1:0;
  1269. flag.idef = flag.idef2 = nk&NK_IGNORE_DEF?1:0;
  1270.  
  1271. if (sc && !sc->count)
  1272. sc = NULL; //Skip checking as there are no status changes active.
  1273. if (tsc && !tsc->count)
  1274. tsc = NULL; //Skip checking as there are no status changes active.
  1275.  
  1276. sd = BL_CAST(BL_PC, src);
  1277. tsd = BL_CAST(BL_PC, target);
  1278.  
  1279. // Minstrel/Wanderer number check for chorus skills.
  1280. // Bonus remains 0 unless 3 or more Minstrel's/Wanderer's are in the party.
  1281. if( sd && sd->status.party_id && party_foreachsamemap(party_sub_count_chorus, sd, 0) > 7)
  1282. chorusbonus = 5;//Maximum effect possiable from 7 or more Minstrel's/Wanderer's
  1283. else if( sd && sd->status.party_id && party_foreachsamemap(party_sub_count_chorus, sd, 0) > 2)
  1284. chorusbonus = party_foreachsamemap(party_sub_count_chorus, sd, 0) - 2;//Effect bonus from additional Minstrel's/Wanderer's if not above the max possiable.
  1285.  
  1286. if(sd)
  1287. wd.blewcount += battle_blewcount_bonus(sd, skill_num);
  1288.  
  1289. //Set miscellaneous data that needs be filled regardless of hit/miss
  1290. if(
  1291. (sd && sd->state.arrow_atk) ||
  1292. (!sd && ((skill_num && skill_get_ammotype(skill_num)) || sstatus->rhw.range>3))
  1293. )
  1294. flag.arrow = 1;
  1295.  
  1296. if(skill_num){
  1297. wd.flag |= battle_range_type(src, target, skill_num, skill_lv);
  1298. switch(skill_num)
  1299. {
  1300. case MO_FINGEROFFENSIVE:
  1301. if(sd) {
  1302. if (battle_config.finger_offensive_type)
  1303. wd.div_ = 1;
  1304. else
  1305. wd.div_ = sd->spiritball_old;
  1306. }
  1307. break;
  1308. case HT_PHANTASMIC:
  1309. //Since these do not consume ammo, they need to be explicitly set as arrow attacks.
  1310. flag.arrow = 1;
  1311. break;
  1312.  
  1313. case CR_SHIELDBOOMERANG:
  1314. case PA_SHIELDCHAIN:
  1315. case LG_SHIELDPRESS:
  1316. case LG_EARTHDRIVE:
  1317. flag.weapon = 0;
  1318. break;
  1319.  
  1320. case KN_PIERCE:
  1321. case ML_PIERCE:
  1322. wd.div_= (wd.div_>0?tstatus->size+1:-(tstatus->size+1));
  1323. break;
  1324.  
  1325. case TF_DOUBLE: //For NPC used skill.
  1326. case GS_CHAINACTION:
  1327. wd.type = 0x08;
  1328. break;
  1329.  
  1330. case GS_GROUNDDRIFT:
  1331. case KN_SPEARSTAB:
  1332. case KN_BOWLINGBASH:
  1333. case MS_BOWLINGBASH:
  1334. case MO_BALKYOUNG:
  1335. case TK_TURNKICK:
  1336. wd.blewcount=0;
  1337. break;
  1338.  
  1339. case KN_AUTOCOUNTER:
  1340. wd.flag=(wd.flag&~BF_SKILLMASK)|BF_NORMAL;
  1341. break;
  1342.  
  1343. case NPC_CRITICALSLASH:
  1344. case LG_PINPOINTATTACK:
  1345. flag.cri = 1; //Always critical skill.
  1346. break;
  1347.  
  1348. case LK_SPIRALPIERCE:
  1349. if (!sd) wd.flag=(wd.flag&~(BF_RANGEMASK|BF_WEAPONMASK))|BF_LONG|BF_MISC;
  1350. break;
  1351.  
  1352. case EL_STONE_RAIN:
  1353. if( !(wflag&1) )
  1354. wd.div_ = 1;
  1355. break;
  1356. }
  1357. } else //Range for normal attacks.
  1358. wd.flag |= flag.arrow?BF_LONG:BF_SHORT;
  1359.  
  1360. if ( (!skill_num || skill_num == PA_SACRIFICE) && tstatus->flee2 && rand()%1000 < tstatus->flee2 )
  1361. { //Check for Lucky Dodge
  1362. wd.type=0x0b;
  1363. wd.dmg_lv=ATK_LUCKY;
  1364. if (wd.div_ < 0) wd.div_*=-1;
  1365. return wd;
  1366. }
  1367.  
  1368. t_class = status_get_class(target);
  1369. s_ele = s_ele_ = skill_get_ele(skill_num, skill_lv);
  1370. if( !skill_num || s_ele == -1 )
  1371. { //Take weapon's element
  1372. s_ele = sstatus->rhw.ele;
  1373. s_ele_ = sstatus->lhw.ele;
  1374. if( flag.arrow && sd && sd->arrow_ele )
  1375. s_ele = sd->arrow_ele;
  1376. if( battle_config.attack_attr_none&src->type )
  1377. n_ele = true; //Weapon's element is "not elemental"
  1378. }
  1379. else if( s_ele == -2 ) //Use enchantment's element
  1380. s_ele = s_ele_ = status_get_attack_sc_element(src,sc);
  1381. else if( s_ele == -3 ) //Use random element
  1382. s_ele = s_ele_ = rand()%ELE_MAX;
  1383. switch( skill_num )
  1384. {
  1385. case GS_GROUNDDRIFT:
  1386. s_ele = s_ele_ = wflag; //element comes in flag.
  1387. break;
  1388. case LK_SPIRALPIERCE:
  1389. if (!sd) n_ele = false; //forced neutral for monsters
  1390. break;
  1391. }
  1392.  
  1393. if(!skill_num)
  1394. { //Skills ALWAYS use ONLY your right-hand weapon (tested on Aegis 10.2)
  1395. if (sd && sd->weapontype1 == 0 && sd->weapontype2 > 0)
  1396. {
  1397. flag.rh=0;
  1398. flag.lh=1;
  1399. }
  1400. if (sstatus->lhw.atk)
  1401. flag.lh=1;
  1402. }
  1403.  
  1404. if( sd && !skill_num )
  1405. { //Check for double attack.
  1406. if( ( ( skill_lv = pc_checkskill(sd,TF_DOUBLE) ) > 0 && sd->weapontype1 == W_DAGGER )
  1407. || ( sd->double_rate > 0 && sd->weapontype1 != W_FIST ) ) //Will fail bare-handed
  1408. { //Success chance is not added, the higher one is used [Skotlex]
  1409. if( rand()%100 < ( 5*skill_lv > sd->double_rate ? 5*skill_lv : sd->double_rate ) )
  1410. {
  1411. wd.div_ = skill_get_num(TF_DOUBLE,skill_lv?skill_lv:1);
  1412. wd.type = 0x08;
  1413. }
  1414. }
  1415. else if( sd->weapontype1 == W_REVOLVER && (skill_lv = pc_checkskill(sd,GS_CHAINACTION)) > 0 && rand()%100 < 5*skill_lv )
  1416. {
  1417. wd.div_ = skill_get_num(GS_CHAINACTION,skill_lv);
  1418. wd.type = 0x08;
  1419. }
  1420. 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 )
  1421. {
  1422. short rate[] = { 12, 12, 21, 27, 30 };
  1423. if( sc->data[SC_FEARBREEZE]->val1 > 0 && sc->data[SC_FEARBREEZE]->val1 < 6 && rand()%100 < rate[sc->data[SC_FEARBREEZE]->val1 - 1] )
  1424. {
  1425. wd.type = 0x08;
  1426. wd.div_ = 2 + (sc->data[SC_FEARBREEZE]->val1 > 2 ? rand()%(sc->data[SC_FEARBREEZE]->val1 - 2) : 0);
  1427. wd.div_ = min(wd.div_,sd->status.inventory[i].amount); // Reduce number of hits if you don't have enough arrows
  1428. sd->state.fearbreeze = wd.div_ - 1;
  1429. }
  1430. }
  1431. }
  1432.  
  1433. //Check for critical
  1434. if( !flag.cri && !(wd.type&0x08) && sstatus->cri &&
  1435. (!skill_num ||
  1436. skill_num == KN_AUTOCOUNTER ||
  1437. skill_num == SN_SHARPSHOOTING || skill_num == MA_SHARPSHOOTING ||
  1438. skill_num == NJ_KIRIKAGE))
  1439. {
  1440. short cri = sstatus->cri;
  1441. if (sd)
  1442. {
  1443. cri+= sd->critaddrace[tstatus->race];
  1444. if(flag.arrow)
  1445. cri += sd->arrow_cri;
  1446. if(sd->status.weapon == W_KATAR)
  1447. cri <<=1;
  1448. }
  1449. //The official equation is *2, but that only applies when sd's do critical.
  1450. //Therefore, we use the old value 3 on cases when an sd gets attacked by a mob
  1451. cri -= tstatus->luk*(!sd&&tsd?3:2);
  1452.  
  1453. if(tsc)
  1454. {
  1455. if (tsc->data[SC_SLEEP])
  1456. cri <<=1;
  1457. }
  1458. switch (skill_num)
  1459. {
  1460. case KN_AUTOCOUNTER:
  1461. if(battle_config.auto_counter_type &&
  1462. (battle_config.auto_counter_type&src->type))
  1463. flag.cri = 1;
  1464. else
  1465. cri <<= 1;
  1466. break;
  1467. case SN_SHARPSHOOTING:
  1468. case MA_SHARPSHOOTING:
  1469. cri += 200;
  1470. break;
  1471. case NJ_KIRIKAGE:
  1472. cri += 250 + 50*skill_lv;
  1473. break;
  1474. }
  1475. if(tsd && tsd->critical_def)
  1476. cri = cri*(100-tsd->critical_def)/100;
  1477. if (rand()%1000 < cri) // Steel need confirm if critical def reduce it.
  1478. flag.cri= 1;
  1479. }
  1480. if (flag.cri)
  1481. {
  1482. wd.type = 0x0a;
  1483. flag.idef = flag.idef2 = flag.hit = 1;
  1484. } else { //Check for Perfect Hit
  1485. if(sd && sd->perfect_hit > 0 && rand()%100 < sd->perfect_hit)
  1486. flag.hit = 1;
  1487. if (sc && sc->data[SC_FUSION]) {
  1488. flag.hit = 1; //SG_FUSION always hit [Komurka]
  1489. flag.idef = flag.idef2 = 1; //def ignore [Komurka]
  1490. }
  1491. if( !flag.hit )
  1492. switch(skill_num)
  1493. {
  1494. case AS_SPLASHER:
  1495. if( !wflag ) // Always hits the one exploding.
  1496. flag.hit = 1;
  1497. break;
  1498. case CR_SHIELDBOOMERANG:
  1499. if( sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_CRUSADER )
  1500. flag.hit = 1;
  1501. break;
  1502. }
  1503. if (tsc && !flag.hit && tsc->opt1 && tsc->opt1 != OPT1_STONEWAIT)
  1504. flag.hit = 1;
  1505. }
  1506.  
  1507. if (!flag.hit)
  1508. { //Hit/Flee calculation
  1509. short flee = tstatus->flee, hitrate=80; //Default hitrate
  1510.  
  1511. if( tsc && tsc->data[SC_NEUTRALBARRIER] && (wd.flag&(BF_SHORT|BF_MAGIC)) == BF_SHORT )
  1512. hitrate = 5; // Currently Neutral Barrier just do this
  1513. else
  1514. {
  1515. if(battle_config.agi_penalty_type &&
  1516. battle_config.agi_penalty_target&target->type)
  1517. {
  1518. unsigned char attacker_count; //256 max targets should be a sane max
  1519. attacker_count = unit_counttargeted(target,battle_config.agi_penalty_count_lv);
  1520. if(attacker_count >= battle_config.agi_penalty_count)
  1521. {
  1522. if (battle_config.agi_penalty_type == 1)
  1523. flee = (flee * (100 - (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num))/100;
  1524. else //asume type 2: absolute reduction
  1525. flee -= (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num;
  1526. if(flee < 1) flee = 1;
  1527. }
  1528. }
  1529.  
  1530. hitrate+= sstatus->hit - flee;
  1531.  
  1532. if(wd.flag&BF_LONG && !skill_num && //Fogwall's hit penalty is only for normal ranged attacks.
  1533. tsc && tsc->data[SC_FOGWALL])
  1534. hitrate -= 50;
  1535.  
  1536. if(sd && flag.arrow)
  1537. hitrate += sd->arrow_hit;
  1538. if(skill_num)
  1539. switch(skill_num)
  1540. { //Hit skill modifiers
  1541. //It is proven that bonus is applied on final hitrate, not hit.
  1542. case SM_BASH:
  1543. case MS_BASH:
  1544. hitrate += hitrate * 5 * skill_lv / 100;
  1545. break;
  1546. case MS_MAGNUM:
  1547. case SM_MAGNUM:
  1548. hitrate += hitrate * 10 * skill_lv / 100;
  1549. break;
  1550. case KN_AUTOCOUNTER:
  1551. case PA_SHIELDCHAIN:
  1552. case NPC_WATERATTACK:
  1553. case NPC_GROUNDATTACK:
  1554. case NPC_FIREATTACK:
  1555. case NPC_WINDATTACK:
  1556. case NPC_POISONATTACK:
  1557. case NPC_HOLYATTACK:
  1558. case NPC_DARKNESSATTACK:
  1559. case NPC_UNDEADATTACK:
  1560. case NPC_TELEKINESISATTACK:
  1561. case NPC_BLEEDING:
  1562. hitrate += hitrate * 20 / 100;
  1563. break;
  1564. case KN_PIERCE:
  1565. case ML_PIERCE:
  1566. hitrate += hitrate * 5 * skill_lv / 100;
  1567. break;
  1568. case AS_SONICBLOW:
  1569. if( sd && pc_checkskill(sd,AS_SONICACCEL) > 0 )
  1570. hitrate += hitrate * 50 / 100;
  1571. break;
  1572. case MC_CARTREVOLUTION:
  1573. case GN_CART_TORNADO:
  1574. case GN_CARTCANNON:
  1575. if( sd && pc_checkskill(sd, GN_REMODELING_CART) )
  1576. hitrate += pc_checkskill(sd, GN_REMODELING_CART) * 4;
  1577. break;
  1578. case GC_VENOMPRESSURE:
  1579. hitrate += 10 + 4 * skill_lv;
  1580. break;
  1581. case SC_FATALMENACE:
  1582. hitrate -= (35 - skill_lv * 5);
  1583. break;
  1584. case LG_BANISHINGPOINT:
  1585. hitrate += 3 * skill_lv;
  1586. break;
  1587. }
  1588.  
  1589. // Weaponry Research hidden bonus
  1590. if (sd && (skill = pc_checkskill(sd,BS_WEAPONRESEARCH)) > 0)
  1591. hitrate += hitrate * ( 2 * skill ) / 100;
  1592.  
  1593. if( sd && (sd->status.weapon == W_1HSWORD || sd->status.weapon == W_DAGGER) &&
  1594. (skill = pc_checkskill(sd, GN_TRAINING_SWORD))>0 )
  1595. hitrate += 3 * skill;
  1596. }
  1597.  
  1598. hitrate = cap_value(hitrate, battle_config.min_hitrate, battle_config.max_hitrate);
  1599.  
  1600. if(rand()%100 >= hitrate)
  1601. wd.dmg_lv = ATK_FLEE;
  1602. else
  1603. flag.hit = 1;
  1604. } //End hit/miss calculation
  1605.  
  1606. if (flag.hit && !flag.infdef) //No need to do the math for plants
  1607. { //Hitting attack
  1608.  
  1609. //Assuming that 99% of the cases we will not need to check for the flag.rh... we don't.
  1610. //ATK_RATE scales the damage. 100 = no change. 50 is halved, 200 is doubled, etc
  1611. #define ATK_RATE( a ) { wd.damage= wd.damage*(a)/100 ; if(flag.lh) wd.damage2= wd.damage2*(a)/100; }
  1612. #define ATK_RATE2( a , b ) { wd.damage= wd.damage*(a)/100 ; if(flag.lh) wd.damage2= wd.damage2*(b)/100; }
  1613. //Adds dmg%. 100 = +100% (double) damage. 10 = +10% damage
  1614. #define ATK_ADDRATE( a ) { wd.damage+= wd.damage*(a)/100 ; if(flag.lh) wd.damage2+= wd.damage2*(a)/100; }
  1615. #define ATK_ADDRATE2( a , b ) { wd.damage+= wd.damage*(a)/100 ; if(flag.lh) wd.damage2+= wd.damage2*(b)/100; }
  1616. //Adds an absolute value to damage. 100 = +100 damage
  1617. #define ATK_ADD( a ) { wd.damage+= a; if (flag.lh) wd.damage2+= a; }
  1618. #define ATK_ADD2( a , b ) { wd.damage+= a; if (flag.lh) wd.damage2+= b; }
  1619.  
  1620. switch (skill_num)
  1621. { //Calc base damage according to skill
  1622. // Below renewal multi hit Final Strike , MyRO
  1623. case NJ_ISSEN:
  1624. wd.div_ = 1;
  1625. if (sc && sc->data[SC_BUNSINJYUTSU] && sc->data[SC_BUNSINJYUTSU]->val2>0)
  1626. wd.div_ = (sc->data[SC_BUNSINJYUTSU]->val2)+2;
  1627. //[(ATK*40) + (HP*80%)] * (1+(0.25*Mirror illusion))
  1628. //wd.damage = 40*sstatus->batk +(skill_lv*8/100)*sstatus->hp;
  1629. wd.damage = 40*sstatus->batk +skill_lv*(sstatus->hp/10 + 35);
  1630. if(wd.div_!=1)
  1631. wd.damage = wd.damage *(1+sc->data[SC_BUNSINJYUTSU]->val2*25/100);
  1632. wd.damage = (wd.damage/wd.div_)/2;
  1633. // wd.damage = wd.damage/wd.div_;
  1634.  
  1635. wd.damage2 = 0;
  1636. status_set_hp(src, sstatus->max_hp/100, 0);
  1637. break;
  1638. case PA_SACRIFICE:
  1639. wd.damage = sstatus->max_hp* 9/100;
  1640. wd.damage2 = 0;
  1641. break;
  1642. // below edited for MyRO (below orig)
  1643. //case LK_SPIRALPIERCE:
  1644. //case ML_SPIRALPIERCE:
  1645. // if (sd) {
  1646. // short index = sd->equip_index[EQI_HAND_R];
  1647.  
  1648. // if (index >= 0 &&
  1649. // sd->inventory_data[index] &&
  1650. // sd->inventory_data[index]->type == IT_WEAPON)
  1651. // wd.damage = sd->inventory_data[index]->weight*8/100; //80% of weight
  1652. // } else
  1653. // wd.damage = sstatus->rhw.atk2*8/10; //Else use Atk2
  1654.  
  1655. // ATK_ADDRATE(50*skill_lv); //Skill modifier applies to weight only.
  1656. // i = sstatus->str/10;
  1657. // i*=i;
  1658. // ATK_ADD(i); //Add str bonus.
  1659. // if( sc && sc->data[SC_GLOOMYDAY_SK] && skill_num == LK_SPIRALPIERCE )
  1660. // ATK_ADD(50 + 5 * sc->data[SC_GLOOMYDAY_SK]->val1);
  1661. // switch (tstatus->size) { //Size-fix. Is this modified by weapon perfection?
  1662. // case 0: //Small: 125%
  1663. // ATK_RATE(125);
  1664. // break;
  1665. // //case 1: //Medium: 100%
  1666. // case 2: //Large: 75%
  1667. // ATK_RATE(75);
  1668. // break;
  1669. // }
  1670. // break;
  1671.  
  1672. // new spiral pierce formula below (MyRO) (based on wieght) (May 30, 2011)
  1673. case LK_SPIRALPIERCE:
  1674. case ML_SPIRALPIERCE:
  1675. wd.damage = sstatus->batk;
  1676. if (sd) {
  1677. short index = sd->equip_index[EQI_HAND_R];
  1678.  
  1679. if (index >= 0 &&
  1680. sd->inventory_data[index] &&
  1681. sd->inventory_data[index]->type == IT_WEAPON)
  1682. ATK_ADD(sd->inventory_data[index]->weight*5/100*skill_lv); //50% of weight * skill level [ADVENT]
  1683. /*wd.damage = sd->inventory_data[index]->weight*8/100; //80% of weight*/
  1684. } else
  1685. /*wd.damage = sstatus->rhw.atk2*8/10; //Else use Atk2*/
  1686. ATK_ADD((sstatus->rhw.atk2*5/10)*skill_lv);
  1687.  
  1688. skillratio += (150+(40*skill_lv));
  1689. if( sc && sc->data[SC_GLOOMYDAY_SK] && skill_num == LK_SPIRALPIERCE )
  1690. ATK_ADDRATE(100+25*(sc->data[SC_GLOOMYDAY_SK]->val1-1));
  1691. //wd.damage = wd.damage*(2 + (sc->data[SC_GLOOMYDAY_SK]->val1-(sc->data[SC_GLOOMYDAY_SK]->val1-1)));
  1692. //ATK_ADD(50 + 5 * sc->data[SC_GLOOMYDAY_SK]->val1);
  1693. switch (tstatus->size) { //Size-fix. Is this modified by weapon perfection?
  1694. case 0: //Small: 125%
  1695. ATK_RATE(125);
  1696. break;
  1697. //case 1: //Medium: 100%
  1698. case 2: //Large: 75%
  1699. ATK_RATE(75);
  1700. break;
  1701. }
  1702. break;
  1703. case CR_SHIELDBOOMERANG:
  1704. case PA_SHIELDCHAIN:
  1705. wd.damage = sstatus->batk;
  1706. if( sd )
  1707. {
  1708. int damagevalue = 0;
  1709. short index = sd->equip_index[EQI_HAND_L];
  1710. if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR )
  1711. damagevalue = sd->inventory_data[index]->weight/10;
  1712. if( sc && sc->data[SC_GLOOMYDAY_SK] )
  1713. damagevalue += damagevalue * (15 + rand()%sc->data[SC_GLOOMYDAY_SK]->val3) / 100;
  1714. ATK_ADD(damagevalue);
  1715. }
  1716. else
  1717. ATK_ADD(sstatus->rhw.atk2); //Else use Atk2
  1718. break;
  1719. case HFLI_SBR44: //[orn]
  1720. if(src->type == BL_HOM) {
  1721. wd.damage = ((TBL_HOM*)src)->homunculus.intimacy ;
  1722. break;
  1723. }
  1724. default:
  1725. {
  1726. i = (flag.cri?1:0)|
  1727. (flag.arrow?2:0)|
  1728. (skill_num == HW_MAGICCRASHER?4:0)|
  1729. (!skill_num && sc && sc->data[SC_CHANGE]?4:0)|
  1730. (skill_num == MO_EXTREMITYFIST?8:0)|
  1731. (sc && sc->data[SC_WEAPONPERFECTION]?8:0);
  1732. if (flag.arrow && sd)
  1733. switch(sd->status.weapon) {
  1734. case W_BOW:
  1735. case W_REVOLVER:
  1736. case W_GATLING:
  1737. case W_SHOTGUN:
  1738. case W_GRENADE:
  1739. break;
  1740. default:
  1741. i |= 16; // for ex. shuriken must not be influenced by DEX
  1742. }
  1743. wd.damage = battle_calc_base_damage(sstatus, &sstatus->rhw, sc, tstatus->size, sd, i);
  1744. if (flag.lh)
  1745. wd.damage2 = battle_calc_base_damage(sstatus, &sstatus->lhw, sc, tstatus->size, sd, i);
  1746.  
  1747. if (nk&NK_SPLASHSPLIT){ // Divide ATK among targets
  1748. if(wflag>0)
  1749. wd.damage/= wflag;
  1750. else
  1751. ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_num, skill_get_name(skill_num));
  1752. }
  1753.  
  1754. //Add any bonuses that modify the base baseatk+watk (pre-skills)
  1755. if( sd )
  1756. {
  1757. if( sd->atk_rate )
  1758. ATK_ADDRATE(sd->atk_rate);
  1759.  
  1760. if(flag.cri && sd->crit_atk_rate)
  1761. ATK_ADDRATE(sd->crit_atk_rate);
  1762.  
  1763. if( sd->status.party_id && (skill=pc_checkskill(sd,TK_POWER)) > 0 )
  1764. {
  1765. if( (i = party_foreachsamemap(party_sub_count, sd, 0)) > 1 ) // exclude the player himself [Inkfish]
  1766. ATK_ADDRATE(2*skill*i);
  1767. }
  1768. }
  1769. break;
  1770. } //End default case
  1771. } //End switch(skill_num)
  1772.  
  1773. //Skill damage modifiers that stack linearly
  1774. if(sc && skill_num != PA_SACRIFICE)
  1775. {
  1776. if(sc->data[SC_OVERTHRUST])
  1777. skillratio += sc->data[SC_OVERTHRUST]->val3;
  1778. if(sc->data[SC_MAXOVERTHRUST])
  1779. skillratio += sc->data[SC_MAXOVERTHRUST]->val2;
  1780. if(sc->data[SC_BERSERK])
  1781. skillratio += 100;
  1782. }
  1783. if( !skill_num )
  1784. { // Random chance to deal multiplied damage - Consider it as part of skill-based-damage
  1785. if( sd && sd->random_attack_increase_add > 0 && sd->random_attack_increase_per && rand()%100 < sd->random_attack_increase_per )
  1786. skillratio += sd->random_attack_increase_add;
  1787.  
  1788. ATK_RATE(skillratio);
  1789. }
  1790. else
  1791. {
  1792. switch( skill_num )
  1793. {
  1794. case SM_BASH:
  1795. case MS_BASH:
  1796. skillratio += 30*skill_lv;
  1797. break;
  1798. case SM_MAGNUM:
  1799. case MS_MAGNUM:
  1800. skillratio += 20*skill_lv;
  1801. break;
  1802. case MC_MAMMONITE:
  1803. skillratio += 50*skill_lv;
  1804. break;
  1805. case HT_POWER:
  1806. skillratio += -50+8*sstatus->str;
  1807. break;
  1808. case AC_DOUBLE:
  1809. case MA_DOUBLE:
  1810. skillratio += 10*(skill_lv-1);
  1811. break;
  1812. case AC_SHOWER:
  1813. case MA_SHOWER:
  1814. skillratio += 5*skill_lv-25;
  1815. break;
  1816. case AC_CHARGEARROW:
  1817. case MA_CHARGEARROW:
  1818. skillratio += 50;
  1819. break;
  1820. case HT_FREEZINGTRAP:
  1821. case MA_FREEZINGTRAP:
  1822. skillratio += -50+10*skill_lv;
  1823. break;
  1824. case KN_PIERCE:
  1825. case ML_PIERCE:
  1826. skillratio += 10*skill_lv;
  1827. break;
  1828. case MER_CRASH:
  1829. skillratio += 10*skill_lv;
  1830. break;
  1831. case KN_SPEARSTAB:
  1832. skillratio += 15*skill_lv;
  1833. break;
  1834. case KN_SPEARBOOMERANG:
  1835. skillratio += 50*skill_lv;
  1836. break;
  1837. case KN_BRANDISHSPEAR:
  1838. case ML_BRANDISH:
  1839. {
  1840. int ratio = 100+20*skill_lv;
  1841. skillratio += ratio-100;
  1842. if(skill_lv>3 && wflag==1) skillratio += ratio/2;
  1843. if(skill_lv>6 && wflag==1) skillratio += ratio/4;
  1844. if(skill_lv>9 && wflag==1) skillratio += ratio/8;
  1845. if(skill_lv>6 && wflag==2) skillratio += ratio/2;
  1846. if(skill_lv>9 && wflag==2) skillratio += ratio/4;
  1847. if(skill_lv>9 && wflag==3) skillratio += ratio/2;
  1848. if( sc && sc->data[SC_GLOOMYDAY_SK] )
  1849. skillratio += skillratio * (15 + rand()%sc->data[SC_GLOOMYDAY_SK]->val3) / 100;
  1850. break;
  1851. }
  1852. case KN_BOWLINGBASH:
  1853. case MS_BOWLINGBASH:
  1854. skillratio+= 40*skill_lv;
  1855. break;
  1856. case AS_GRIMTOOTH:
  1857. skillratio += 20*skill_lv;
  1858. break;
  1859. case AS_POISONREACT:
  1860. skillratio += 30*skill_lv;
  1861. break;
  1862. case AS_SONICBLOW:
  1863. skillratio += -50+5*skill_lv;
  1864. break;
  1865. case TF_SPRINKLESAND:
  1866. skillratio += 30;
  1867. break;
  1868. case MC_CARTREVOLUTION:
  1869. skillratio += 50;
  1870. if(sd && sd->cart_weight)
  1871. skillratio += 100*sd->cart_weight/battle_config.max_cart_weight; // +1% every 1% weight
  1872. else if (!sd)
  1873. skillratio += 100; //Max damage for non players.
  1874. break;
  1875. case NPC_RANDOMATTACK:
  1876. skillratio += 100 * skill_lv;
  1877. break;
  1878. case NPC_WATERATTACK:
  1879. case NPC_GROUNDATTACK:
  1880. case NPC_FIREATTACK:
  1881. case NPC_WINDATTACK:
  1882. case NPC_POISONATTACK:
  1883. case NPC_HOLYATTACK:
  1884. case NPC_DARKNESSATTACK:
  1885. case NPC_UNDEADATTACK:
  1886. case NPC_TELEKINESISATTACK:
  1887. case NPC_BLOODDRAIN:
  1888. case NPC_ACIDBREATH:
  1889. case NPC_DARKNESSBREATH:
  1890. case NPC_FIREBREATH:
  1891. case NPC_ICEBREATH:
  1892. case NPC_THUNDERBREATH:
  1893. case NPC_HELLJUDGEMENT:
  1894. case NPC_PULSESTRIKE:
  1895. skillratio += 100*(skill_lv-1);
  1896. break;
  1897. case RG_BACKSTAP:
  1898. if(sd && sd->status.weapon == W_BOW && battle_config.backstab_bow_penalty)
  1899. skillratio += (200+40*skill_lv)/2;
  1900. else
  1901. skillratio += 200+40*skill_lv;
  1902. break;
  1903. case RG_RAID:
  1904. skillratio += 40*skill_lv;
  1905. break;
  1906. case RG_INTIMIDATE:
  1907. skillratio += 30*skill_lv;
  1908. break;
  1909. case CR_SHIELDCHARGE:
  1910. skillratio += 20*skill_lv;
  1911. if( sc && sc->data[SC_GLOOMYDAY_SK] )
  1912. skillratio += skillratio * (15 + rand()%sc->data[SC_GLOOMYDAY_SK]->val3) / 100;
  1913. break;
  1914. case CR_SHIELDBOOMERANG:
  1915. skillratio += 30*skill_lv;
  1916. if( sc && sc->data[SC_GLOOMYDAY_SK] )
  1917. skillratio += skillratio * (15 + rand()%sc->data[SC_GLOOMYDAY_SK]->val3) / 100;
  1918. break;
  1919. case NPC_DARKCROSS:
  1920. case CR_HOLYCROSS:
  1921. skillratio += 35*skill_lv;
  1922. break;
  1923. case AM_DEMONSTRATION:
  1924. skillratio += 20*skill_lv;
  1925. break;
  1926. case AM_ACIDTERROR:
  1927. skillratio += 40*skill_lv;
  1928. break;
  1929. case MO_FINGEROFFENSIVE:
  1930. skillratio+= 50 * skill_lv;
  1931. break;
  1932. case MO_INVESTIGATE:
  1933. skillratio += 75*skill_lv;
  1934. flag.pdef = flag.pdef2 = 2;
  1935. break;
  1936. case MO_EXTREMITYFIST:
  1937. { //Overflow check. [Skotlex]
  1938. unsigned int ratio = skillratio + 100*(8 + sstatus->sp/10);
  1939. //You'd need something like 6K SP to reach this max, so should be fine for most purposes.
  1940. if (ratio > 60000) ratio = 60000; //We leave some room here in case skillratio gets further increased.
  1941. skillratio = (unsigned short)ratio;
  1942. status_set_sp(src, 0, 0);
  1943. }
  1944. break;
  1945. case MO_TRIPLEATTACK:
  1946. skillratio += 20*skill_lv;
  1947. break;
  1948. case MO_CHAINCOMBO:
  1949. skillratio += 50+50*skill_lv;
  1950. break;
  1951. case MO_COMBOFINISH:
  1952. skillratio += 140+60*skill_lv;
  1953. break;
  1954. case BA_MUSICALSTRIKE:
  1955. case DC_THROWARROW:
  1956. skillratio += 25+25*skill_lv;
  1957. break;
  1958. case CH_TIGERFIST:
  1959. skillratio += 100*skill_lv-60;
  1960. break;
  1961. case CH_CHAINCRUSH:
  1962. skillratio += 300+100*skill_lv;
  1963. break;
  1964. case CH_PALMSTRIKE:
  1965. skillratio += 100+100*skill_lv;
  1966. break;
  1967. case LK_HEADCRUSH:
  1968. skillratio += 40*skill_lv;
  1969. break;
  1970. case LK_JOINTBEAT:
  1971. i = 10*skill_lv-50;
  1972. // Although not clear, it's being assumed that the 2x damage is only for the break neck ailment.
  1973. if (wflag&BREAK_NECK) i*=2;
  1974. skillratio += i;
  1975. break;
  1976. case ASC_METEORASSAULT:
  1977. skillratio += 40*skill_lv-60;
  1978. break;
  1979. case SN_SHARPSHOOTING:
  1980. case MA_SHARPSHOOTING:
  1981. skillratio += 100 + 50 * skill_lv;
  1982. break;
  1983. case CG_ARROWVULCAN:
  1984. skillratio += 100+100*skill_lv;
  1985. break;
  1986. case AS_SPLASHER:
  1987. skillratio += 400+50*skill_lv;
  1988. if(sd)
  1989. skillratio += 30 * pc_checkskill(sd,AS_POISONREACT);
  1990. break;
  1991. case ASC_BREAKER:
  1992. skillratio += 100*skill_lv-100;
  1993. break;
  1994. case PA_SACRIFICE:
  1995. skillratio += 10*skill_lv-10;
  1996. break;
  1997. case PA_SHIELDCHAIN:
  1998. skillratio += 30*skill_lv;
  1999. if( sc && sc->data[SC_GLOOMYDAY_SK] )
  2000. skillratio += skillratio * (15 + rand()%sc->data[SC_GLOOMYDAY_SK]->val3) / 100;
  2001. break;
  2002. case WS_CARTTERMINATION:
  2003. i = 12 * (16 - skill_lv);
  2004. if (i < 1) i = 1;
  2005. //Preserve damage ratio when max cart weight is changed.
  2006. if(sd && sd->cart_weight)
  2007. skillratio += sd->cart_weight/i * 80000/battle_config.max_cart_weight - 100;
  2008. else if (!sd)
  2009. skillratio += 80000 / i - 100;
  2010. break;
  2011. case TK_DOWNKICK:
  2012. skillratio += 60 + 20*skill_lv;
  2013. break;
  2014. case TK_STORMKICK:
  2015. skillratio += 60 + 20*skill_lv;
  2016. break;
  2017. case TK_TURNKICK:
  2018. skillratio += 90 + 30*skill_lv;
  2019. break;
  2020. case TK_COUNTER:
  2021. skillratio += 90 + 30*skill_lv;
  2022. break;
  2023. case TK_JUMPKICK:
  2024. skillratio += -70 + 10*skill_lv;
  2025. if (sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == skill_num)
  2026. skillratio += 10*s_level/3; //Tumble bonus
  2027. if (wflag)
  2028. {
  2029. skillratio += 10*s_level/3; //Running bonus (TODO: What is the real bonus?)
  2030. if( sc && sc->data[SC_SPURT] ) // Spurt bonus
  2031. skillratio *= 2;
  2032. }
  2033. break;
  2034. case GS_TRIPLEACTION:
  2035. skillratio += 50*skill_lv;
  2036. break;
  2037. case GS_BULLSEYE:
  2038. //Only works well against brute/demihumans non bosses.
  2039. if((tstatus->race == RC_BRUTE || tstatus->race == RC_DEMIHUMAN)
  2040. && !(tstatus->mode&MD_BOSS))
  2041. skillratio += 400;
  2042. break;
  2043. case GS_TRACKING:
  2044. skillratio += 100 *(skill_lv+1);
  2045. break;
  2046. case GS_PIERCINGSHOT:
  2047. skillratio += 20*skill_lv;
  2048. break;
  2049. case GS_RAPIDSHOWER:
  2050. skillratio += 10*skill_lv;
  2051. break;
  2052. case GS_DESPERADO:
  2053. skillratio += 50*(skill_lv-1);
  2054. break;
  2055. case GS_DUST:
  2056. skillratio += 50*skill_lv;
  2057. break;
  2058. case GS_FULLBUSTER:
  2059. skillratio += 100*(skill_lv+2);
  2060. break;
  2061. case GS_SPREADATTACK:
  2062. skillratio += 20*(skill_lv-1);
  2063. break;
  2064. case NJ_HUUMA:
  2065. skillratio += 50 + 150*skill_lv;
  2066. break;
  2067. case NJ_TATAMIGAESHI:
  2068. skillratio += 10*skill_lv;
  2069. break;
  2070. case NJ_KASUMIKIRI:
  2071. skillratio += 10*skill_lv;
  2072. break;
  2073. case NJ_KIRIKAGE:
  2074. skillratio += 100*(skill_lv-1);
  2075. break;
  2076. case KN_CHARGEATK:
  2077. {
  2078. int k = (wflag-1)/3; //+100% every 3 cells of distance
  2079. if( k > 2 ) k = 2; // ...but hard-limited to 300%.
  2080. skillratio += 100 * k;
  2081. }
  2082. break;
  2083. case HT_PHANTASMIC:
  2084. skillratio += 50;
  2085. break;
  2086. case MO_BALKYOUNG:
  2087. skillratio += 200;
  2088. break;
  2089. case HFLI_MOON: //[orn]
  2090. skillratio += 10+110*skill_lv;
  2091. break;
  2092. case HFLI_SBR44: //[orn]
  2093. skillratio += 100 *(skill_lv-1);
  2094. break;
  2095. case NPC_VAMPIRE_GIFT:
  2096. skillratio += ((skill_lv-1)%5+1)*100;
  2097. break;
  2098. case RK_SONICWAVE:
  2099. skillratio += 400 + 100 * skill_lv;
  2100. if( re_baselv_bonus == 1 && s_level >= 100 )
  2101. skillratio += skillratio * (s_level - 100) / 200; // Base level bonus.
  2102. break;
  2103. case RK_HUNDREDSPEAR:
  2104. skillratio += 500 + 80 * skill_lv + 50 * pc_checkskill(sd,LK_SPIRALPIERCE);
  2105. if( sd )
  2106. {
  2107. short index = sd->equip_index[EQI_HAND_R];
  2108. if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON )
  2109. {
  2110. short spearwbd = 1000 - sd->inventory_data[index]->weight / 10;// Spear Weight Bonus Damage.
  2111. if ( spearwbd < 0 )
  2112. spearwbd = 0;// If weight of weapon is more then 1000, bonus is set to 0 to prevent negative value. [Rytech]
  2113. skillratio += spearwbd;
  2114. }
  2115. }
  2116. if( re_baselv_bonus == 1 && s_level >= 100 )
  2117. skillratio += skillratio * (s_level - 100) / 200; // Base level bonus.
  2118. if( sc && sc->data[SC_GLOOMYDAY_SK] )
  2119. skillratio += skillratio * (15 + rand()%sc->data[SC_GLOOMYDAY_SK]->val3) / 100;
  2120. break;
  2121. case RK_WINDCUTTER:
  2122. skillratio += 50 * skill_lv;
  2123. if( re_baselv_bonus == 1 && s_level >= 100 )
  2124. skillratio = skillratio * s_level / 100; // Base level bonus.
  2125. break;
  2126. case RK_IGNITIONBREAK:
  2127. i = distance_bl(src,target);
  2128. if( i < 2 ) skillratio = 300 * skill_lv;
  2129. else
  2130. if( i < 4 ) skillratio = 250 * skill_lv;
  2131. else
  2132. skillratio = 200 * skill_lv;
  2133. if( sstatus->rhw.ele == ELE_FIRE ) skillratio += 100 * skill_lv; // Bonus by fire element endow.
  2134. if( re_baselv_bonus == 1 && s_level >= 100 )
  2135. skillratio += skillratio * (s_level - 100) / 100; // Base level bonus.
  2136. break;
  2137. case RK_CRUSHSTRIKE:
  2138. if( sd )
  2139. {
  2140. short index = sd->equip_index[EQI_HAND_R];
  2141. if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON )
  2142. // MyRO, further reduced damage by less 60% below skillratio = sstatus->rhw.atk + sd->inventory_data[index]->weight / 10 + sd->inventory_data[index]->wlv * (sd->status.inventory[index].refine + 6) * 100;
  2143. skillratio = sstatus->rhw.atk + sd->inventory_data[index]->weight / 10 + sd->inventory_data[index]->wlv * (sd->status.inventory[index].refine + 6) * 60;
  2144. }
  2145. break;
  2146. case RK_STORMBLAST:
  2147. skillratio = 100 * (sstatus->int_ / 8 + (sd ? pc_checkskill(sd,RK_RUNEMASTERY) : 1));
  2148. break;
  2149. case RK_PHANTOMTHRUST:
  2150. skillratio = 50 * skill_lv + 10 * pc_checkskill(sd,KN_SPEARMASTERY);
  2151. if( re_baselv_bonus == 1 && s_level >= 100 )
  2152. skillratio = skillratio * s_level / 150;
  2153. break;
  2154. case GC_CROSSIMPACT:
  2155. skillratio += 900 + 100 * skill_lv;
  2156. if( re_baselv_bonus == 1 && s_level >= 100 )
  2157. skillratio = skillratio * s_level / 120;
  2158. break;
  2159. case GC_COUNTERSLASH:
  2160. skillratio += 200 + 100 * skill_lv;
  2161. if( re_baselv_bonus == 1 && s_level >= 100 )
  2162. skillratio = skillratio * s_level / 120;
  2163. if( re_baselv_bonus == 1 && s_level >= 100 )
  2164. skillratio += sstatus->agi * 2 + sd->status.job_level * 4;
  2165. else
  2166. skillratio += sstatus->agi * 2 + 200;
  2167. break;
  2168. case GC_PHANTOMMENACE:
  2169. skillratio += 200;
  2170. break;
  2171. case GC_ROLLINGCUTTER:
  2172. skillratio = 50 + 50 * skill_lv;
  2173. if( re_baselv_bonus == 1 && s_level >= 100 )
  2174. skillratio = skillratio * s_level / 100;
  2175. break;
  2176. case GC_CROSSRIPPERSLASHER:
  2177. skillratio += 300 + 80 * skill_lv;
  2178. if( re_baselv_bonus == 1 && s_level >= 100 )
  2179. skillratio = skillratio * s_level / 100;
  2180. if( sc && sc->data[SC_ROLLINGCUTTER] )
  2181. skillratio += sc->data[SC_ROLLINGCUTTER]->val1 * sstatus->agi;
  2182. break;
  2183. case AB_DUPLELIGHT_MELEE:
  2184. skillratio += 10 * skill_lv;
  2185. break;
  2186. case RA_ARROWSTORM:
  2187. skillratio += 900 + 80 * skill_lv;
  2188. if( re_baselv_bonus == 1 && s_level >= 100 )
  2189. skillratio = skillratio * s_level / 100; // Base level bonus.
  2190. break;
  2191. case RA_AIMEDBOLT:
  2192. skillratio += 400 + 50 * skill_lv;
  2193. if( re_baselv_bonus == 1 && s_level >= 100 )
  2194. skillratio = skillratio * s_level / 100; // Base level bonus.
  2195. if( tsc && (tsc->data[SC_BITE] || tsc->data[SC_ANKLE] || tsc->data[SC_ELECTRICSHOCKER]) )
  2196. wd.div_ = tstatus->size + 2 + rand()%2;
  2197. break;
  2198. case RA_CLUSTERBOMB:
  2199. skillratio += 100 + 100 * skill_lv;
  2200. break;
  2201. case RA_WUGDASH:
  2202. skillratio = 300;
  2203. if( sc && sc->data[SC_DANCEWITHWUG] )
  2204. skillratio += 10 * sc->data[SC_DANCEWITHWUG]->val1 * (2 + chorusbonus);
  2205. break;
  2206. case RA_WUGSTRIKE:
  2207. skillratio = 200 * skill_lv;
  2208. if( sc && sc->data[SC_DANCEWITHWUG] )
  2209. skillratio += 10 * sc->data[SC_DANCEWITHWUG]->val1 * (2 + chorusbonus);
  2210. break;
  2211. case RA_WUGBITE:
  2212. skillratio += 300 + 200 * skill_lv;
  2213. if ( skill_lv == 5 ) skillratio += 100;
  2214. if( sc && sc->data[SC_DANCEWITHWUG] )
  2215. skillratio += 10 * sc->data[SC_DANCEWITHWUG]->val1 * (2 + chorusbonus);
  2216. break;
  2217. case RA_SENSITIVEKEEN:
  2218. skillratio += 50 * skill_lv;
  2219. break;
  2220. case NC_BOOSTKNUCKLE:
  2221. // MyRO edited to have more damage skillratio += 100 + 100 * skill_lv + sstatus->dex;
  2222. skillratio += 100 + 175 * skill_lv + sstatus->dex;
  2223. if( re_baselv_bonus == 1 && s_level >= 100 )
  2224. skillratio = skillratio * s_level / 120; // Base level bonus.
  2225. break;
  2226. case NC_PILEBUNKER:
  2227. skillratio += 200 + 100 * skill_lv + sstatus->str;
  2228. if( re_baselv_bonus == 1 && s_level >= 100 )
  2229. skillratio = skillratio * s_level / 100; // Base level bonus.
  2230. break;
  2231. case NC_VULCANARM:
  2232. skillratio = 70 * skill_lv + sstatus->dex;
  2233. if( re_baselv_bonus == 1 && s_level >= 100 )
  2234. skillratio = skillratio * s_level / 120; // Base level bonus.
  2235. break;
  2236. case NC_FLAMELAUNCHER:
  2237. case NC_COLDSLOWER:
  2238. skillratio += 200 + 300 * skill_lv;
  2239. if( re_baselv_bonus == 1 && s_level >= 100 )
  2240. skillratio = skillratio * s_level / 150; // Base level bonus.
  2241. break;
  2242. case NC_ARMSCANNON:
  2243. switch( tstatus->size )
  2244. {
  2245. case 0: skillratio += 200 + 400 * skill_lv; break;// Small
  2246. case 1: skillratio += 200 + 350 * skill_lv; break;// Medium
  2247. case 2: skillratio += 200 + 300 * skill_lv; break;// Large
  2248. }
  2249. if( re_baselv_bonus == 1 && s_level >= 100 )
  2250. skillratio = skillratio * s_level / 120; // Base level bonus.
  2251. //NOTE: Their's some other factors that affects damage, but not sure how exactly. Will recheck one day. [Rytech]
  2252. break;
  2253. case NC_AXEBOOMERANG:
  2254. skillratio += 150 + 50 * skill_lv;
  2255. if( sd )
  2256. {
  2257. short index = sd->equip_index[EQI_HAND_R];
  2258. if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON )
  2259. skillratio += sd->inventory_data[index]->weight / 10;// Weight is divided by 10 since 10 weight in coding make 1 whole actural weight. [Rytech]
  2260. }
  2261. if( re_baselv_bonus == 1 && s_level >= 100 )
  2262. skillratio = skillratio * s_level / 100; // Base level bonus.
  2263. break;
  2264. case NC_POWERSWING:
  2265. skillratio += 200 + 100 * skill_lv;
  2266. if( re_baselv_bonus == 1 && s_level >= 100 )
  2267. skillratio += (sstatus->str + sstatus->dex) * s_level / 100; // Base level bonus.
  2268. else
  2269. skillratio += sstatus->str + sstatus->dex;
  2270. break;
  2271. case NC_AXETORNADO:
  2272. skillratio += 100 + 100 * skill_lv + sstatus->vit;
  2273. if( re_baselv_bonus == 1 && s_level >= 100 )
  2274. skillratio = skillratio * s_level / 100; // Base level bonus.
  2275. if( sstatus->rhw.ele == ELE_WIND ) skillratio += skillratio * 25 / 100; // 1.25x Damage if the weapon is wind element. [Rytech]
  2276. i = distance_bl(src,target);
  2277. if( i > 2 ) skillratio = skillratio * 75 / 100;
  2278. break;
  2279. case SC_FATALMENACE:
  2280. skillratio += 100 * skill_lv;
  2281. break;
  2282. case SC_TRIANGLESHOT:
  2283. skillratio += 270 + 30 * skill_lv; // Note: Isn't the formula outdated? [Xazax]
  2284. break;
  2285. case SC_FEINTBOMB:
  2286. skillratio += 100 + 100 * skill_lv;
  2287. break;
  2288. case LG_CANNONSPEAR:
  2289. skillratio = (50 + sstatus->str) * skill_lv;
  2290. if( re_baselv_bonus == 1 && s_level >= 100 )
  2291. skillratio = skillratio * s_level / 100; // Base level bonus.
  2292. break;
  2293. case LG_BANISHINGPOINT:
  2294. skillratio = (50 * skill_lv) + 30 * (sd ? pc_checkskill(sd,SM_BASH) : 1);
  2295. if( re_baselv_bonus == 1 && s_level >= 100 )
  2296. skillratio = skillratio * s_level / 100; // Base level bonus.
  2297. break;
  2298. case LG_SHIELDPRESS:
  2299. skillratio = 150 * skill_lv + sstatus->str;
  2300. if( sd )
  2301. {
  2302. short index = sd->equip_index[EQI_HAND_L];
  2303. if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR )
  2304. skillratio += sd->inventory_data[index]->weight / 10;
  2305. }
  2306. if( re_baselv_bonus == 1 && s_level >= 100 )
  2307. skillratio = skillratio * s_level / 100; // Base level bonus.
  2308. if( sc && sc->data[SC_GLOOMYDAY_SK] )
  2309. skillratio += skillratio * (15 + rand()%sc->data[SC_GLOOMYDAY_SK]->val3) / 100;
  2310. break;
  2311. case LG_PINPOINTATTACK:
  2312. skillratio = 100 * skill_lv + 5 * sstatus->agi;
  2313. if( re_baselv_bonus == 1 && s_level >= 100 )
  2314. skillratio = skillratio * s_level / 120; // Base level bonus.
  2315. break;
  2316. case LG_RAGEBURST:
  2317. if( sd && sd->rageball_old )
  2318. skillratio = 200 * sd->rageball_old + (sstatus->max_hp - sstatus->hp) / 100;
  2319. else//If your a GM
  2320. skillratio = 3000 + (sstatus->max_hp - sstatus->hp) / 100;
  2321. if( re_baselv_bonus == 1 && s_level >= 100 )
  2322. skillratio = skillratio * s_level / 100; // Base level bonus.
  2323. break;
  2324. case LG_SHIELDSPELL:
  2325. if ( sd && skill_lv == 1 )
  2326. {
  2327. struct item_data *shield_data = sd->inventory_data[sd->equip_index[EQI_HAND_L]];
  2328. if( shield_data )
  2329. if( battle_config.renewal_baselvl_skill_effect == 1 && status_get_lv(src) >= 100 )
  2330. skillratio = 4 * s_level + 100 * shield_data->def + 2 * sstatus->vit;
  2331. else
  2332. skillratio = 600 + 100 * shield_data->def + 2 * sstatus->vit;
  2333. }
  2334. else
  2335. skillratio = 0;//Prevents ATK damage from being done on LV 2 usage since LV 2 us MATK. [Rytech]
  2336. break;
  2337. case LG_OVERBRAND:
  2338. skillratio = 200 * skill_lv + 50 * pc_checkskill(sd,CR_SPEARQUICKEN);
  2339. if( re_baselv_bonus == 1 && s_level >= 100 )
  2340. skillratio = skillratio * s_level / 100; // Base level bonus.
  2341. break;
  2342. case LG_OVERBRAND_BRANDISH:
  2343. skillratio = 100 * skill_lv + sstatus->str + sstatus->dex;
  2344. if( re_baselv_bonus == 1 && s_level >= 100 )
  2345. skillratio = skillratio * s_level / 100; // Base level bonus.
  2346. break;
  2347. case LG_OVERBRAND_PLUSATK:
  2348. skillratio = 100 * skill_lv;
  2349. break;
  2350. case LG_MOONSLASHER:
  2351. skillratio = 120 * skill_lv + 80 * pc_checkskill(sd,LG_OVERBRAND);
  2352. if( re_baselv_bonus == 1 && s_level >= 100 )
  2353. skillratio = skillratio * s_level / 100; // Base level bonus.
  2354. break;
  2355. case LG_RAYOFGENESIS:
  2356. skillratio += 200 + 300 * skill_lv;
  2357. if( re_baselv_bonus == 1 && s_level >= 100 )
  2358. skillratio = skillratio * s_level / 100; // Base level bonus.
  2359. break;
  2360. case LG_EARTHDRIVE:
  2361. if( sd )
  2362. {
  2363. short index = sd->equip_index[EQI_HAND_L];
  2364. if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR )
  2365. skillratio = (1 + skill_lv) * sd->inventory_data[index]->weight / 10;
  2366. }
  2367. if( re_baselv_bonus == 1 && s_level >= 100 )
  2368. skillratio = skillratio * s_level / 100; // Base level bonus.
  2369. break;
  2370. case LG_HESPERUSLIT:
  2371. skillratio = 120 * skill_lv;
  2372. // Banding check needed here.
  2373. if( sc && sc->data[SC_INSPIRATION] )
  2374. skillratio += 600;
  2375. if( re_baselv_bonus == 1 && s_level >= 100 )
  2376. skillratio = skillratio * s_level / 100; // Base level bonus.
  2377. break;
  2378. case SR_DRAGONCOMBO:
  2379. skillratio += 40 * skill_lv;
  2380. break;
  2381. case SR_SKYNETBLOW:
  2382. skillratio += 80 * skill_lv - 100 + ( sstatus->agi * 4 );
  2383. break;
  2384. case SR_EARTHSHAKER:
  2385. skillratio += 50 * skill_lv - 50;// Need to code a check to make the ratio 3x when hitting a hidden player. [Rytech]
  2386. break;
  2387. case SR_FALLENEMPIRE:
  2388. skillratio += 150 * skill_lv; // Need official on how much enemy players weight affects damage. [Rytech]
  2389. //if( tsd && tsd->weight )
  2390. // skillratio = (100 + 150 * skill_lv) * tsd->weight / 10000;
  2391. //else
  2392. // skillratio = (100 + 150 * skill_lv) * 600 / 100;
  2393. break;
  2394. case SR_TIGERCANNON:
  2395. if( battle_config.skillsbonus_maxhp_SR && sstatus->hp > battle_config.skillsbonus_maxhp_SR )
  2396. skillratio = 2000 + ( battle_config.skillsbonus_maxhp_SR * ( 10 + 2 * skill_lv ) / 100 );
  2397. else
  2398. // skillratio = 2000 + ( sstatus->hp * ( 10 + 2 * skill_lv ) / 100 );
  2399. skillratio = 2000; // Its appears the sacrificed HP is added as fixed damage (reduceable) Will have to do later. [Rytech]
  2400. break;
  2401. case SR_RAMPAGEBLASTER:
  2402. if( sc && sc->data[SC_EXPLOSIONSPIRITS] )
  2403. skillratio += 40 * skill_lv * (sd?sd->spiritball_old:5) - 100;
  2404. else
  2405. skillratio += 20 * skill_lv * (sd?sd->spiritball_old:5) - 100;
  2406. break;
  2407. case SR_KNUCKLEARROW:
  2408. if( wflag&4 )
  2409. skillratio = 150 * skill_lv; //+Knockback Damage (Must check and test. [Rytech])
  2410. else
  2411. skillratio += 400 + (100 * skill_lv);
  2412. break;
  2413. case SR_WINDMILL:
  2414. skillratio += 150;
  2415. break;
  2416. case SR_GATEOFHELL:
  2417. skillratio += 500 * skill_lv -100;
  2418. break;
  2419. case SR_GENTLETOUCH_QUIET:
  2420. skillratio += 100 * skill_lv - 100 + sstatus->dex;
  2421. break;
  2422. case SR_HOWLINGOFLION:
  2423. skillratio += 300 * skill_lv - 100;
  2424. break;
  2425. case SR_RIDEINLIGHTNING:
  2426. skillratio += 200 * skill_lv -100;
  2427. break;
  2428. case WM_REVERBERATION_MELEE:
  2429. skillratio += 200 + 100 * skill_lv;
  2430. if( re_baselv_bonus == 1 && s_level >= 100 )
  2431. skillratio = skillratio * s_level / 100; // Base level bonus.
  2432. break;
  2433. case WM_SEVERE_RAINSTORM_MELEE:
  2434. skillratio = (sstatus->agi + sstatus->dex) * skill_lv / 5;
  2435. if( re_baselv_bonus == 1 && s_level >= 100 )
  2436. skillratio = skillratio * s_level / 100; // Base level bonus.
  2437. break;
  2438. case WM_GREAT_ECHO:
  2439. skillratio += 300 + 200 * skill_lv;
  2440. if ( chorusbonus == 1 )//Chorus bonus dont count the first 2 Minstrel's/Wanderer's and only increases when their's 3 or more. [Rytech]
  2441. skillratio += 100;
  2442. else if ( chorusbonus == 2 )
  2443. skillratio += 200;
  2444. else if ( chorusbonus == 3 )
  2445. skillratio += 400;
  2446. else if ( chorusbonus == 4 )
  2447. skillratio += 800;
  2448. else if ( chorusbonus == 5 )
  2449. skillratio += 1600;
  2450. if( re_baselv_bonus == 1 && s_level >= 100 )
  2451. skillratio = skillratio * s_level / 100; // Base level bonus.
  2452. break;
  2453. case SO_VARETYR_SPEAR:
  2454. skillratio = 50 * skill_lv + 50 * pc_checkskill(sd, SO_STRIKING);
  2455. if( re_baselv_bonus == 1 && s_level >= 100 )
  2456. skillratio = skillratio * s_level / 100; // Base level bonus.
  2457. if( sc && sc->data[SC_BLAST_OPTION] )
  2458. skillratio += skillratio * sc->data[SC_BLAST_OPTION]->val2 / 100;
  2459. break;
  2460. case GN_CART_TORNADO:
  2461. skillratio += 50 * skill_lv + pc_checkskill(sd, GN_REMODELING_CART) * 100 - 100;
  2462. if( re_baselv_bonus == 1 && s_level >= 100 )
  2463. skillratio += skillratio * (s_level - 100) / 200; // Base level bonus.
  2464. if( sc && sc->data[SC_GN_CARTBOOST] )
  2465. skillratio += 10 * sc->data[SC_GN_CARTBOOST]->val1;
  2466. break;
  2467. case GN_CARTCANNON:
  2468. skillratio += 250 + 50 * skill_lv + pc_checkskill(sd, GN_REMODELING_CART) * (sstatus->int_ / 2);
  2469. if( sc && sc->data[SC_GN_CARTBOOST] )
  2470. skillratio += 10 * sc->data[SC_GN_CARTBOOST]->val1;
  2471. break;
  2472. case GN_SPORE_EXPLOSION:
  2473. skillratio += 200 + 100 * skill_lv;
  2474. break;
  2475. case GN_CRAZYWEED_ATK:
  2476. skillratio += 400 + 100 * skill_lv;
  2477. break;
  2478. case GN_SLINGITEM_RANGEMELEEATK:
  2479. if( sd )
  2480. {
  2481. switch( sd->itemid )
  2482. {
  2483. case 13260: // Apple Bomob
  2484. case 13261: // Coconut Bomb
  2485. case 13262: // Melon Bomb
  2486. case 13263: // Pinapple Bomb
  2487. skillratio += 400; // Unconfirded
  2488. break;
  2489. case 13264: // Banana Bomb 2000%
  2490. skillratio += 1900;
  2491. break;
  2492. case 13265: skillratio -= 75; break; // Black Lump 25%
  2493. case 13266: skillratio -= 25; break; // Hard Black Lump 75%
  2494. case 13267: skillratio += 100; break; // Extremely Hard Black Lump 200%
  2495. }
  2496. }
  2497. else
  2498. skillratio += 300; // Bombs
  2499. break;
  2500. case KO_JYUMONJIKIRI:
  2501. skillratio = 150 * skill_lv;
  2502. {
  2503. struct status_change *tsc = status_get_sc(target);
  2504. if( tsc && tsc->data[SC_JYUMONJIKIRI] )// Bonus damage added when attacking target with Cross Slasher status. [Rytech]
  2505. skillratio += 75 * skill_lv;// Need official bonus damage formula.
  2506. }
  2507. break;
  2508. case KO_SETSUDAN:
  2509. skillratio = 100 * skill_lv;
  2510. {
  2511. struct status_change *tsc = status_get_sc(target);
  2512. if( tsc && tsc->data[SC_SPIRIT] )// Bonus damage added when target is soul linked. [Rytech]
  2513. skillratio += 100 * skill_lv * tsc->data[SC_SPIRIT]->val1;// Deals higher damage depending on level of soul link. Need official bonus damage formula.
  2514. }
  2515. break;
  2516. case KO_BAKURETSU:
  2517. skillratio = 10 * skill_lv * pc_checkskill(sd, NJ_TOBIDOUGU);
  2518. break;
  2519. case KO_HAPPOKUNAI:
  2520. if( sd )
  2521. {
  2522. short index = sd->equip_index[EQI_AMMO];
  2523. if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_AMMO )
  2524. skillratio = (50 + 10 * skill_lv) * sd->inventory_data[index]->atk;
  2525. }
  2526. break;
  2527. case KO_HUUMARANKA:
  2528. skillratio = 150 * skill_lv + (sstatus->agi + sstatus->dex) * pc_checkskill(sd, NJ_HUUMA);
  2529. break;
  2530. // Physical Elemantal Spirits Attack Skills
  2531. case EL_CIRCLE_OF_FIRE:
  2532. case EL_FIRE_BOMB_ATK:
  2533. case EL_STONE_RAIN:
  2534. skillratio += 200;
  2535. break;
  2536. case EL_FIRE_WAVE_ATK:
  2537. skillratio += 500;
  2538. break;
  2539. case EL_TIDAL_WEAPON:
  2540. skillratio += 1400;
  2541. break;
  2542. case EL_WIND_SLASH:
  2543. skillratio += 100;
  2544. break;
  2545. case EL_HURRICANE:
  2546. skillratio += 600;
  2547. break;
  2548. case EL_TYPOON_MIS:
  2549. case EL_WATER_SCREW_ATK:
  2550. skillratio += 900;
  2551. break;
  2552. case EL_STONE_HAMMER:
  2553. skillratio += 400;
  2554. break;
  2555. case EL_ROCK_CRUSHER:
  2556. skillratio += 700;
  2557. break;
  2558. }
  2559. // Some skill under EDP status have been nerfed. http://www.eathena.ws/board/index.php?showtopic=234419&hl=enchant+deadly
  2560. if( battle_config.renewal_edp && sc && sc->data[SC_EDP] )
  2561. {
  2562. switch( skill_num )
  2563. {
  2564. case AS_SONICBLOW:
  2565. case ASC_BREAKER:
  2566. if( battle_config.renewal_edp&1 )
  2567. skillratio = skillratio * 3 / 4;
  2568. break;
  2569. case GC_CROSSIMPACT:
  2570. case GC_COUNTERSLASH:
  2571. if( battle_config.renewal_edp&2 )
  2572. // skillratio = skillratio * 3 / 4; (MyRO Below)
  2573. skillratio = skillratio * 19 / 10;
  2574. break;
  2575. }
  2576. }
  2577. ATK_RATE(skillratio);
  2578.  
  2579. //Constant/misc additions from skills
  2580. switch (skill_num) {
  2581. case MO_EXTREMITYFIST:
  2582. ATK_ADD(250 + 150*skill_lv);
  2583. break;
  2584. case TK_DOWNKICK:
  2585. case TK_STORMKICK:
  2586. case TK_TURNKICK:
  2587. case TK_COUNTER:
  2588. case TK_JUMPKICK:
  2589. //TK_RUN kick damage bonus.
  2590. if(sd && sd->weapontype1 == W_FIST && sd->weapontype2 == W_FIST)
  2591. ATK_ADD(10*pc_checkskill(sd, TK_RUN));
  2592. break;
  2593. case GS_MAGICALBULLET:
  2594. if(sstatus->matk_max>sstatus->matk_min) {
  2595. ATK_ADD(sstatus->matk_min+rand()%(sstatus->matk_max-sstatus->matk_min));
  2596. } else {
  2597. ATK_ADD(sstatus->matk_min);
  2598. }
  2599. break;
  2600. case NJ_SYURIKEN:
  2601. ATK_ADD(4*skill_lv);
  2602. break;
  2603. case RA_WUGDASH:
  2604. if(sd)
  2605. ATK_ADD(sd->weight / 8);//Dont need to divide weight here since official formula takes current weight * 10. [Rytech]
  2606. if( sc && sc->data[SC_DANCEWITHWUG] )
  2607. skillratio += 2 * sc->data[SC_DANCEWITHWUG]->val1 * (2 + chorusbonus);
  2608. case RA_WUGSTRIKE:
  2609. case RA_WUGBITE:
  2610. if(sd)
  2611. ATK_ADD(30*pc_checkskill(sd, RA_TOOTHOFWUG));
  2612. if( sc && sc->data[SC_DANCEWITHWUG] )
  2613. skillratio += 2 * sc->data[SC_DANCEWITHWUG]->val1 * (2 + chorusbonus);
  2614. break;
  2615. case LG_SHIELDPRESS:
  2616. if( sd )
  2617. {
  2618. int damagevalue = 0;
  2619. short index = sd->equip_index[EQI_HAND_L];
  2620. if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR )
  2621. damagevalue = sstatus->vit * sd->status.inventory[index].refine;
  2622. if( sc && sc->data[SC_GLOOMYDAY_SK] )
  2623. damagevalue += damagevalue * (15 + rand()%sc->data[SC_GLOOMYDAY_SK]->val3) / 100;
  2624. ATK_ADD(damagevalue);
  2625. }
  2626. break;
  2627. //case LG_RAYOFGENESIS:
  2628. // if( sc && sc->data[SC_BANDING] )
  2629. // {// Increase only if the RG is under Banding.
  2630. // short lv = (short)skill_lv;
  2631. // ATK_ADDRATE( 190 * ((sd) ? skill_check_pc_partner(sd,(short)skill_num,&lv,skill_get_splash(skill_num,skill_lv),0) : 1));
  2632. // }
  2633. // break;
  2634. case SR_GATEOFHELL:
  2635. ATK_ADD (sstatus->max_hp - sstatus->hp);//Will have to add the consumed SP part to the formula in the future. [Rytech]
  2636. break;
  2637. }
  2638. }
  2639. //Div fix.
  2640. damage_div_fix(wd.damage, wd.div_);
  2641.  
  2642. //The following are applied on top of current damage and are stackable.
  2643. if (sc) {
  2644. if(sc->data[SC_TRUESIGHT])
  2645. ATK_ADDRATE(2*sc->data[SC_TRUESIGHT]->val1);
  2646.  
  2647. if(sc->data[SC_EDP] )
  2648. {
  2649. switch( skill_num )
  2650. {
  2651. case ASC_METEORASSAULT:
  2652. case AS_SPLASHER:
  2653. case AS_VENOMKNIFE:
  2654. case ASC_BREAKER:
  2655. break;
  2656. case AS_GRIMTOOTH: // Grimtooth skill no longer takes the effect of Enchant Deadly Poison.
  2657. // Skill effects nerfed, don't add EDP effects.
  2658. case AS_SONICBLOW:
  2659. if( !(battle_config.renewal_edp&1) )
  2660. ATK_ADDRATE(sc->data[SC_EDP]->val3);
  2661. break;
  2662. case GC_CROSSIMPACT:
  2663. case GC_COUNTERSLASH:
  2664. if( !(battle_config.renewal_edp&2) )
  2665. ATK_ADDRATE(sc->data[SC_EDP]->val3);
  2666. break;
  2667. default:
  2668. ATK_ADDRATE(sc->data[SC_EDP]->val3);
  2669. break;
  2670. }
  2671. }
  2672.  
  2673. }
  2674.  
  2675. switch (skill_num) {
  2676. case AS_SONICBLOW:
  2677. if (sc && sc->data[SC_SPIRIT] &&
  2678. sc->data[SC_SPIRIT]->val2 == SL_ASSASIN)
  2679. ATK_ADDRATE(map_flag_gvg(src->m)?25:100); //+25% dmg on woe/+100% dmg on nonwoe
  2680.  
  2681. if(sd && pc_checkskill(sd,AS_SONICACCEL)>0)
  2682. ATK_ADDRATE(10);
  2683. break;
  2684. case CR_SHIELDBOOMERANG:
  2685. if(sc && sc->data[SC_SPIRIT] &&
  2686. sc->data[SC_SPIRIT]->val2 == SL_CRUSADER)
  2687. ATK_ADDRATE(100);
  2688. break;
  2689. case SR_EARTHSHAKER:
  2690. if( tsc && (tsc->data[SC_HIDING] || tsc->data[SC_CLOAKING] || tsc->data[SC_CHASEWALK] || tsc->data[SC_CLOAKINGEXCEED]) )
  2691. ATK_ADDRATE(150+150*skill_lv);
  2692. break;
  2693. case SR_RIDEINLIGHTNING:
  2694. if( (sstatus->rhw.ele) == ELE_WIND || (sstatus->lhw.ele) == ELE_WIND )
  2695. ATK_ADDRATE(skill_lv*5);
  2696. break;
  2697. }
  2698.  
  2699. if( sd )
  2700. {
  2701. if (skill_num && (i = pc_skillatk_bonus(sd, skill_num)))
  2702. ATK_ADDRATE(i);
  2703. // MyRO added Spiral Peirce not to work with thanatos card-- if( skill_num != PA_SACRIFICE && skill_num != MO_INVESTIGATE && skill_num != CR_GRANDCROSS && skill_num != NPC_GRANDDARKNESS && skill_num != PA_SHIELDCHAIN && !flag.cri )
  2704. if( skill_num != LK_SPIRALPIERCE && skill_num != PA_SACRIFICE && skill_num != MO_INVESTIGATE && skill_num != CR_GRANDCROSS && skill_num != NPC_GRANDDARKNESS && skill_num != PA_SHIELDCHAIN && !flag.cri )
  2705.  
  2706. { //Elemental/Racial adjustments
  2707. if( sd->right_weapon.def_ratio_atk_ele & (1<<tstatus->def_ele) ||
  2708. sd->right_weapon.def_ratio_atk_race & (1<<tstatus->race) ||
  2709. sd->right_weapon.def_ratio_atk_race & (1<<(is_boss(target)?RC_BOSS:RC_NONBOSS))
  2710. )
  2711. flag.pdef = 1;
  2712.  
  2713. if( sd->left_weapon.def_ratio_atk_ele & (1<<tstatus->def_ele) ||
  2714. sd->left_weapon.def_ratio_atk_race & (1<<tstatus->race) ||
  2715. sd->left_weapon.def_ratio_atk_race & (1<<(is_boss(target)?RC_BOSS:RC_NONBOSS))
  2716. )
  2717. { //Pass effect onto right hand if configured so. [Skotlex]
  2718. if (battle_config.left_cardfix_to_right && flag.rh)
  2719. flag.pdef = 1;
  2720. else
  2721. flag.pdef2 = 1;
  2722. }
  2723. }
  2724.  
  2725. if (skill_num != CR_GRANDCROSS && skill_num != NPC_GRANDDARKNESS)
  2726. { //Ignore Defense?
  2727. if (!flag.idef && (
  2728. sd->right_weapon.ignore_def_ele & (1<<tstatus->def_ele) ||
  2729. sd->right_weapon.ignore_def_race & (1<<tstatus->race) ||
  2730. sd->right_weapon.ignore_def_race & (is_boss(target)?1<<RC_BOSS:1<<RC_NONBOSS)
  2731. ))
  2732. flag.idef = 1;
  2733.  
  2734. if (!flag.idef2 && (
  2735. sd->left_weapon.ignore_def_ele & (1<<tstatus->def_ele) ||
  2736. sd->left_weapon.ignore_def_race & (1<<tstatus->race) ||
  2737. sd->left_weapon.ignore_def_race & (is_boss(target)?1<<RC_BOSS:1<<RC_NONBOSS)
  2738. )) {
  2739. if(battle_config.left_cardfix_to_right && flag.rh) //Move effect to right hand. [Skotlex]
  2740. flag.idef = 1;
  2741. else
  2742. flag.idef2 = 1;
  2743. }
  2744. }
  2745. }
  2746.  
  2747. if (!flag.idef || !flag.idef2)
  2748. { //Defense reduction
  2749. short vit_def;
  2750. signed char def1 = status_get_def(target); //Don't use tstatus->def1 due to skill timer reductions.
  2751. short def2 = (short)tstatus->def2;
  2752.  
  2753. if( sc && sc->data[SC_EXPIATIO] )
  2754. { // Deffense bypass 5 * skilllv
  2755. def1 -= def1 * 5 * sc->data[SC_EXPIATIO]->val1 / 100;
  2756. def2 -= def2 * 5 * sc->data[SC_EXPIATIO]->val1 / 100;
  2757. }
  2758.  
  2759. if( sd )
  2760. {
  2761. i = sd->ignore_def[is_boss(target)?RC_BOSS:RC_NONBOSS];
  2762. i += sd->ignore_def[tstatus->race];
  2763. if( i )
  2764. {
  2765. if( i > 100 ) i = 100;
  2766. def1 -= def1 * i / 100;
  2767. def2 -= def2 * i / 100;
  2768. }
  2769. }
  2770.  
  2771. if( battle_config.vit_penalty_type && battle_config.vit_penalty_target&target->type )
  2772. {
  2773. unsigned char target_count; //256 max targets should be a sane max
  2774. target_count = unit_counttargeted(target,battle_config.vit_penalty_count_lv);
  2775. if(target_count >= battle_config.vit_penalty_count) {
  2776. if(battle_config.vit_penalty_type == 1) {
  2777. if( !tsc || !tsc->data[SC_STEELBODY] )
  2778. def1 = (def1 * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100;
  2779. def2 = (def2 * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100;
  2780. } else { //Assume type 2
  2781. if( !tsc || !tsc->data[SC_STEELBODY] )
  2782. def1 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num;
  2783. def2 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num;
  2784. }
  2785. }
  2786. if(skill_num == AM_ACIDTERROR) def1 = 0; //Acid Terror ignores only armor defense. [Skotlex]
  2787. if(def2 < 1) def2 = 1;
  2788. }
  2789. //Vitality reduction from rodatazone: http://rodatazone.simgaming.net/mechanics/substats.php#def
  2790. if (tsd) //Sd vit-eq
  2791. { //[VIT*0.5] + rnd([VIT*0.3], max([VIT*0.3],[VIT^2/150]-1))
  2792. vit_def = def2*(def2-15)/150;
  2793. vit_def = def2/2 + (vit_def>0?rand()%vit_def:0);
  2794.  
  2795. if((battle_check_undead(sstatus->race,sstatus->def_ele) || sstatus->race==RC_DEMON) && //This bonus already doesnt work vs players
  2796. src->type == BL_MOB && (skill=pc_checkskill(tsd,AL_DP)) > 0)
  2797. vit_def += skill*(int)(3 +(tsd->status.base_level+1)*0.04); // submitted by orn
  2798. if( src->type == BL_MOB && (skill=pc_checkskill(tsd,RA_RANGERMAIN))>0 &&
  2799. (sstatus->race == RC_BRUTE || sstatus->race == RC_FISH || sstatus->race == RC_PLANT) )
  2800. vit_def += skill*5;
  2801. } else { //Mob-Pet vit-eq
  2802. //VIT + rnd(0,[VIT/20]^2-1)
  2803. vit_def = (def2/20)*(def2/20);
  2804. vit_def = def2 + (vit_def>0?rand()%vit_def:0);
  2805. }
  2806.  
  2807. if (battle_config.weapon_defense_type) {
  2808. vit_def += def1*battle_config.weapon_defense_type;
  2809. def1 = 0;
  2810. }
  2811. if (def1 > 100) def1 = 100;
  2812. ATK_RATE2(
  2813. flag.idef ?100:(flag.pdef ?(int)(flag.pdef *(def1+vit_def)):(100-def1)),
  2814. flag.idef2?100:(flag.pdef2?(int)(flag.pdef2*(def1+vit_def)):(100-def1))
  2815. );
  2816. ATK_ADD2(
  2817. flag.idef ||flag.pdef ?0:-vit_def,
  2818. flag.idef2||flag.pdef2?0:-vit_def
  2819. );
  2820. }
  2821.  
  2822. //Post skill/vit reduction damage increases
  2823. if( sc && skill_num != LK_SPIRALPIERCE && skill_num != ML_SPIRALPIERCE )
  2824. { //SC skill damages
  2825. if(sc->data[SC_AURABLADE])
  2826. ATK_ADD(20*sc->data[SC_AURABLADE]->val1);
  2827. }
  2828.  
  2829. //Refine bonus
  2830. if( sd && flag.weapon && skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST )
  2831. { // Counts refine bonus multiple times
  2832. if( skill_num == MO_FINGEROFFENSIVE )
  2833. {
  2834. ATK_ADD2(wd.div_*sstatus->rhw.atk2, wd.div_*sstatus->lhw.atk2);
  2835. } else {
  2836. ATK_ADD2(sstatus->rhw.atk2, sstatus->lhw.atk2);
  2837. }
  2838. }
  2839.  
  2840. //Set to min of 1
  2841. if (flag.rh && wd.damage < 1) wd.damage = 1;
  2842. if (flag.lh && wd.damage2 < 1) wd.damage2 = 1;
  2843.  
  2844. if (sd && flag.weapon &&
  2845. skill_num != MO_INVESTIGATE &&
  2846. skill_num != MO_EXTREMITYFIST &&
  2847. skill_num != CR_GRANDCROSS)
  2848. { //Add mastery damage
  2849. if(skill_num != ASC_BREAKER && sd->status.weapon == W_KATAR &&
  2850. (skill=pc_checkskill(sd,ASC_KATAR)) > 0)
  2851. { //Adv Katar Mastery is does not applies to ASC_BREAKER,
  2852. // but other masteries DO apply >_>
  2853. ATK_ADDRATE(10+ 2*skill);
  2854. }
  2855.  
  2856. wd.damage = battle_addmastery(sd,target,wd.damage,0);
  2857. if (flag.lh)
  2858. wd.damage2 = battle_addmastery(sd,target,wd.damage2,1);
  2859.  
  2860. if (sc && sc->data[SC_MIRACLE]) i = 2; //Star anger
  2861. else
  2862. ARR_FIND(0, MAX_PC_FEELHATE, i, t_class == sd->hate_mob[i]);
  2863. if (i < MAX_PC_FEELHATE && (skill=pc_checkskill(sd,sg_info[i].anger_id)))
  2864. {
  2865. skillratio = sd->status.base_level + sstatus->dex + sstatus->luk;
  2866. if (i == 2) skillratio += sstatus->str; //Star Anger
  2867. if (skill<4)
  2868. skillratio /= 12-3*skill;
  2869. ATK_ADDRATE(skillratio);
  2870. }
  2871. if (skill_num == NJ_SYURIKEN && (skill = pc_checkskill(sd,NJ_TOBIDOUGU)) > 0)
  2872. ATK_ADD(3*skill);
  2873. if (skill_num == NJ_KUNAI)
  2874. ATK_ADD(60);
  2875. }
  2876. } //Here ends flag.hit section, the rest of the function applies to both hitting and missing attacks
  2877. else if(wd.div_ < 0) //Since the attack missed...
  2878. wd.div_ *= -1;
  2879.  
  2880. if(sd && (skill=pc_checkskill(sd,BS_WEAPONRESEARCH)) > 0)
  2881. ATK_ADD(skill*2);
  2882.  
  2883. if(skill_num==TF_POISON)
  2884. ATK_ADD(15*skill_lv);
  2885.  
  2886. if( !(nk&NK_NO_ELEFIX) && !n_ele )
  2887. { //Elemental attribute fix
  2888. if( wd.damage > 0 )
  2889. {
  2890. wd.damage=battle_attr_fix(src,target,wd.damage,s_ele,tstatus->def_ele, tstatus->ele_lv);
  2891. if( skill_num == MC_CARTREVOLUTION ) //Cart Revolution applies the element fix once more with neutral element
  2892. wd.damage = battle_attr_fix(src,target,wd.damage,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv);
  2893. if( skill_num== GS_GROUNDDRIFT ) //Additional 50*lv Neutral damage.
  2894. wd.damage += battle_attr_fix(src,target,50*skill_lv,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv);
  2895. }
  2896. if( flag.lh && wd.damage2 > 0 )
  2897. wd.damage2 = battle_attr_fix(src,target,wd.damage2,s_ele_,tstatus->def_ele, tstatus->ele_lv);
  2898. if( sc && sc->data[SC_WATK_ELEMENT] )
  2899. { // Descriptions indicate this means adding a percent of a normal attack in another element. [Skotlex]
  2900. int damage = battle_calc_base_damage(sstatus, &sstatus->rhw, sc, tstatus->size, sd, (flag.arrow?2:0)) * sc->data[SC_WATK_ELEMENT]->val2 / 100;
  2901. wd.damage += battle_attr_fix(src, target, damage, sc->data[SC_WATK_ELEMENT]->val1, tstatus->def_ele, tstatus->ele_lv);
  2902.  
  2903. if( flag.lh )
  2904. {
  2905. damage = battle_calc_base_damage(sstatus, &sstatus->lhw, sc, tstatus->size, sd, (flag.arrow?2:0)) * sc->data[SC_WATK_ELEMENT]->val2 / 100;
  2906. wd.damage2 += battle_attr_fix(src, target, damage, sc->data[SC_WATK_ELEMENT]->val1, tstatus->def_ele, tstatus->ele_lv);
  2907. }
  2908. }
  2909. }
  2910.  
  2911. if(skill_num == CR_GRANDCROSS || skill_num == NPC_GRANDDARKNESS)
  2912. return wd; //Enough, rest is not needed.
  2913.  
  2914. if (sd)
  2915. {
  2916. if (skill_num != CR_SHIELDBOOMERANG) //Only Shield boomerang doesn't takes the Star Crumbs bonus.
  2917. ATK_ADD2(wd.div_*sd->right_weapon.star, wd.div_*sd->left_weapon.star);
  2918. if (skill_num==MO_FINGEROFFENSIVE) { //The finger offensive spheres on moment of attack do count. [Skotlex]
  2919. ATK_ADD(wd.div_*sd->spiritball_old*3);
  2920. } else {
  2921. ATK_ADD(wd.div_*sd->spiritball*3);
  2922. }
  2923.  
  2924. //Card Fix, sd side
  2925. if( (wd.damage || wd.damage2) && !(nk&NK_NO_CARDFIX_ATK) )
  2926. {
  2927. int cardfix = 1000, cardfix_ = 1000;
  2928. int t_race2 = status_get_race2(target);
  2929. if(sd->state.arrow_atk)
  2930. {
  2931. cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race]+sd->arrow_addrace[tstatus->race])/100;
  2932. if (!(nk&NK_NO_ELEFIX))
  2933. {
  2934. int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->arrow_addele[tstatus->def_ele];
  2935. for (i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++) {
  2936. if (sd->right_weapon.addele2[i].ele != tstatus->def_ele) continue;
  2937. if(!(sd->right_weapon.addele2[i].flag&wd.flag&BF_WEAPONMASK &&
  2938. sd->right_weapon.addele2[i].flag&wd.flag&BF_RANGEMASK &&
  2939. sd->right_weapon.addele2[i].flag&wd.flag&BF_SKILLMASK))
  2940. continue;
  2941. ele_fix += sd->right_weapon.addele2[i].rate;
  2942. }
  2943. cardfix=cardfix*(100+ele_fix)/100;
  2944. }
  2945. cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size]+sd->arrow_addsize[tstatus->size])/100;
  2946. cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2])/100;
  2947. 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;
  2948. if( tstatus->race != RC_DEMIHUMAN )
  2949. cardfix=cardfix*(100+sd->right_weapon.addrace[RC_NONDEMIHUMAN]+sd->arrow_addrace[RC_NONDEMIHUMAN])/100;
  2950. }
  2951. else
  2952. { // Melee attack
  2953. if( !battle_config.left_cardfix_to_right )
  2954. {
  2955. cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race])/100;
  2956. if (!(nk&NK_NO_ELEFIX)) {
  2957. int ele_fix = sd->right_weapon.addele[tstatus->def_ele];
  2958. for (i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++) {
  2959. if (sd->right_weapon.addele2[i].ele != tstatus->def_ele) continue;
  2960. if(!(sd->right_weapon.addele2[i].flag&wd.flag&BF_WEAPONMASK &&
  2961. sd->right_weapon.addele2[i].flag&wd.flag&BF_RANGEMASK &&
  2962. sd->right_weapon.addele2[i].flag&wd.flag&BF_SKILLMASK))
  2963. continue;
  2964. ele_fix += sd->right_weapon.addele2[i].rate;
  2965. }
  2966. cardfix=cardfix*(100+ele_fix)/100;
  2967. }
  2968. cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size])/100;
  2969. cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2])/100;
  2970. cardfix=cardfix*(100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100;
  2971. if( tstatus->race != RC_DEMIHUMAN )
  2972. cardfix=cardfix*(100+sd->right_weapon.addrace[RC_NONDEMIHUMAN])/100;
  2973.  
  2974. if( flag.lh )
  2975. {
  2976. cardfix_=cardfix_*(100+sd->left_weapon.addrace[tstatus->race])/100;
  2977. if (!(nk&NK_NO_ELEFIX)) {
  2978. int ele_fix_lh = sd->left_weapon.addele[tstatus->def_ele];
  2979. for (i = 0; ARRAYLENGTH(sd->left_weapon.addele2) > i && sd->left_weapon.addele2[i].rate != 0; i++) {
  2980. if (sd->left_weapon.addele2[i].ele != tstatus->def_ele) continue;
  2981. if(!(sd->left_weapon.addele2[i].flag&wd.flag&BF_WEAPONMASK &&
  2982. sd->left_weapon.addele2[i].flag&wd.flag&BF_RANGEMASK &&
  2983. sd->left_weapon.addele2[i].flag&wd.flag&BF_SKILLMASK))
  2984. continue;
  2985. ele_fix_lh += sd->left_weapon.addele2[i].rate;
  2986. }
  2987. cardfix=cardfix*(100+ele_fix_lh)/100;
  2988. }
  2989. cardfix_=cardfix_*(100+sd->left_weapon.addsize[tstatus->size])/100;
  2990. cardfix_=cardfix_*(100+sd->left_weapon.addrace2[t_race2])/100;
  2991. cardfix_=cardfix_*(100+sd->left_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100;
  2992. if( tstatus->race != RC_DEMIHUMAN )
  2993. cardfix_=cardfix_*(100+sd->left_weapon.addrace[RC_NONDEMIHUMAN])/100;
  2994. }
  2995. }
  2996. else
  2997. {
  2998. int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->left_weapon.addele[tstatus->def_ele];
  2999. for (i = 0; ARRAYLENGTH(sd->right_weapon.addele2) > i && sd->right_weapon.addele2[i].rate != 0; i++) {
  3000. if (sd->right_weapon.addele2[i].ele != tstatus->def_ele) continue;
  3001. if(!(sd->right_weapon.addele2[i].flag&wd.flag&BF_WEAPONMASK &&
  3002. sd->right_weapon.addele2[i].flag&wd.flag&BF_RANGEMASK &&
  3003. sd->right_weapon.addele2[i].flag&wd.flag&BF_SKILLMASK))
  3004. continue;
  3005. ele_fix += sd->right_weapon.addele2[i].rate;
  3006. }
  3007. for (i = 0; ARRAYLENGTH(sd->left_weapon.addele2) > i && sd->left_weapon.addele2[i].rate != 0; i++) {
  3008. if (sd->left_weapon.addele2[i].ele != tstatus->def_ele) continue;
  3009. if(!(sd->left_weapon.addele2[i].flag&wd.flag&BF_WEAPONMASK &&
  3010. sd->left_weapon.addele2[i].flag&wd.flag&BF_RANGEMASK &&
  3011. sd->left_weapon.addele2[i].flag&wd.flag&BF_SKILLMASK))
  3012. continue;
  3013. ele_fix += sd->left_weapon.addele2[i].rate;
  3014. }
  3015.  
  3016. cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race]+sd->left_weapon.addrace[tstatus->race])/100;
  3017. cardfix=cardfix*(100+ele_fix)/100;
  3018. cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size]+sd->left_weapon.addsize[tstatus->size])/100;
  3019. cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2]+sd->left_weapon.addrace2[t_race2])/100;
  3020. 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;
  3021. if( tstatus->race != RC_DEMIHUMAN )
  3022. cardfix=cardfix*(100+sd->right_weapon.addrace[RC_NONDEMIHUMAN]+sd->left_weapon.addrace[RC_NONDEMIHUMAN])/100;
  3023. }
  3024. }
  3025.  
  3026. for( i = 0; i < ARRAYLENGTH(sd->right_weapon.add_dmg) && sd->right_weapon.add_dmg[i].rate; i++ )
  3027. {
  3028. if( sd->right_weapon.add_dmg[i].class_ == t_class )
  3029. {
  3030. cardfix=cardfix*(100+sd->right_weapon.add_dmg[i].rate)/100;
  3031. break;
  3032. }
  3033. }
  3034.  
  3035. if( flag.lh )
  3036. {
  3037. for( i = 0; i < ARRAYLENGTH(sd->left_weapon.add_dmg) && sd->left_weapon.add_dmg[i].rate; i++ )
  3038. {
  3039. if( sd->left_weapon.add_dmg[i].class_ == t_class )
  3040. {
  3041. cardfix_=cardfix_*(100+sd->left_weapon.add_dmg[i].rate)/100;
  3042. break;
  3043. }
  3044. }
  3045. }
  3046.  
  3047. if( wd.flag&BF_LONG )
  3048. cardfix=cardfix*(100+sd->long_attack_atk_rate)/100;
  3049.  
  3050. if( cardfix != 1000 || cardfix_ != 1000 )
  3051. ATK_RATE2(cardfix/10, cardfix_/10); //What happens if you use right-to-left and there's no right weapon, only left?
  3052. }
  3053.  
  3054. if( skill_num == CR_SHIELDBOOMERANG || skill_num == PA_SHIELDCHAIN )
  3055. { //Refine bonus applies after cards and elements.
  3056. int damagevalue = 0;
  3057. short index= sd->equip_index[EQI_HAND_L];
  3058. if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR )
  3059. damagevalue = 10 * sd->status.inventory[index].refine;
  3060. if( sc && sc->data[SC_GLOOMYDAY_SK] )
  3061. damagevalue += damagevalue * (15 + rand()%sc->data[SC_GLOOMYDAY_SK]->val3) / 100;
  3062. ATK_ADD(damagevalue);
  3063. }
  3064. } //if (sd)
  3065.  
  3066. //Card Fix, tsd sid
  3067. if( tsd && !(nk&NK_NO_CARDFIX_DEF) )
  3068. {
  3069. short s_race2,s_class;
  3070. short cardfix=1000;
  3071.  
  3072. s_race2 = status_get_race2(src);
  3073. s_class = status_get_class(src);
  3074.  
  3075. if( !(nk&NK_NO_ELEFIX) )
  3076. {
  3077. int ele_fix = tsd->subele[s_ele];
  3078. for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++)
  3079. {
  3080. if(tsd->subele2[i].ele != s_ele) continue;
  3081. if(!(tsd->subele2[i].flag&wd.flag&BF_WEAPONMASK &&
  3082. tsd->subele2[i].flag&wd.flag&BF_RANGEMASK &&
  3083. tsd->subele2[i].flag&wd.flag&BF_SKILLMASK))
  3084. continue;
  3085. ele_fix += tsd->subele2[i].rate;
  3086. }
  3087. cardfix=cardfix*(100-ele_fix)/100;
  3088. if( flag.lh && s_ele_ != s_ele )
  3089. {
  3090. int ele_fix_lh = tsd->subele[s_ele_];
  3091. for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++)
  3092. {
  3093. if(tsd->subele2[i].ele != s_ele_) continue;
  3094. if(!(tsd->subele2[i].flag&wd.flag&BF_WEAPONMASK &&
  3095. tsd->subele2[i].flag&wd.flag&BF_RANGEMASK &&
  3096. tsd->subele2[i].flag&wd.flag&BF_SKILLMASK))
  3097. continue;
  3098. ele_fix_lh += tsd->subele2[i].rate;
  3099. }
  3100. cardfix=cardfix*(100-ele_fix_lh)/100;
  3101. }
  3102. }
  3103. cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100;
  3104. cardfix=cardfix*(100-tsd->subrace2[s_race2])/100;
  3105. cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100;
  3106. cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100;
  3107. if( sstatus->race != RC_DEMIHUMAN )
  3108. cardfix=cardfix*(100-tsd->subrace[RC_NONDEMIHUMAN])/100;
  3109.  
  3110. for( i = 0; i < ARRAYLENGTH(tsd->add_def) && tsd->add_def[i].rate;i++ )
  3111. {
  3112. if( tsd->add_def[i].class_ == s_class )
  3113. {
  3114. cardfix=cardfix*(100-tsd->add_def[i].rate)/100;
  3115. break;
  3116. }
  3117. }
  3118.  
  3119. if( wd.flag&BF_SHORT )
  3120. cardfix=cardfix*(100-tsd->near_attack_def_rate)/100;
  3121. else // BF_LONG (there's no other choice)
  3122. cardfix=cardfix*(100-tsd->long_attack_def_rate)/100;
  3123.  
  3124. if( tsd->sc.data[SC_DEF_RATE] )
  3125. cardfix=cardfix*(100-tsd->sc.data[SC_DEF_RATE]->val1)/100;
  3126.  
  3127. if( cardfix != 1000 )
  3128. ATK_RATE(cardfix/10);
  3129. }
  3130.  
  3131. if( flag.infdef )
  3132. { //Plants receive 1 damage when hit
  3133. if( flag.hit || wd.damage > 0 )
  3134. wd.damage = wd.div_; // In some cases, right hand no need to have a weapon to increase damage
  3135. if( flag.lh && (flag.hit || wd.damage2 > 0) )
  3136. wd.damage2 = wd.div_;
  3137. if( !(battle_config.skill_min_damage&1) )
  3138. //Do not return if you are supposed to deal greater damage to plants than 1. [Skotlex]
  3139. return wd;
  3140. }
  3141.  
  3142. if( sd )
  3143. {
  3144. if( !flag.rh && flag.lh )
  3145. { //Move lh damage to the rh
  3146. wd.damage = wd.damage2;
  3147. wd.damage2 = 0;
  3148. flag.rh = 1;
  3149. flag.lh = 0;
  3150. }
  3151. else if( flag.rh && flag.lh )
  3152. { //Dual-wield
  3153. if( wd.damage )
  3154. {
  3155. if ((sd->class_&MAPID_UPPERMASK) == MAPID_ASSASSIN)
  3156. {skill = pc_checkskill(sd,AS_RIGHT);
  3157. wd.damage = wd.damage * (50 + (skill * 10)) / 100;
  3158. if( wd.damage < 1 )
  3159. wd.damage = 1;}
  3160. else
  3161. {skill = pc_checkskill(sd,KO_RIGHT);
  3162. wd.damage = wd.damage * (70 + (skill * 10)) / 100;
  3163. if( wd.damage < 1 )
  3164. wd.damage = 1;}
  3165. }
  3166. if( wd.damage2 )
  3167. {
  3168. if ((sd->class_&MAPID_UPPERMASK) == MAPID_ASSASSIN)
  3169. {skill = pc_checkskill(sd,AS_LEFT);
  3170. wd.damage2 = wd.damage2 * (30 + (skill * 10)) / 100;
  3171. if( wd.damage2 < 1 )
  3172. wd.damage2 = 1;}
  3173. else
  3174. {skill = pc_checkskill(sd,KO_LEFT);
  3175. wd.damage2 = wd.damage2 * (50 + (skill * 10)) / 100;
  3176. if( wd.damage2 < 1 )
  3177. wd.damage2 = 1;}
  3178. }
  3179. }
  3180. else if( sd->status.weapon == W_KATAR && !skill_num )
  3181. { //Katars (offhand damage only applies to normal attacks, tested on Aegis 10.2)
  3182. skill = pc_checkskill(sd,TF_DOUBLE);
  3183. wd.damage2 = wd.damage * (1 + (skill * 2)) / 100;
  3184.  
  3185. if( wd.damage && !wd.damage2 )
  3186. wd.damage2 = 1;
  3187.  
  3188. flag.lh = 1;
  3189. }
  3190. }
  3191.  
  3192. if( !flag.rh && wd.damage )
  3193. wd.damage = 0;
  3194.  
  3195. if( !flag.lh && wd.damage2 )
  3196. wd.damage2 = 0;
  3197.  
  3198. if( wd.damage + wd.damage2 )
  3199. { //There is a total damage value
  3200. if( wd.damage )
  3201. {
  3202. wd.damage = battle_calc_damage(src,target,&wd,wd.damage,skill_num,skill_lv,s_ele);
  3203. if( map_flag_gvg2(target->m) )
  3204. wd.damage = battle_calc_gvg_damage(src,target,wd.damage,wd.div_,skill_num,skill_lv,wd.flag);
  3205. else if( map[target->m].flag.battleground )
  3206. wd.damage = battle_calc_bg_damage(src,target,wd.damage,wd.div_,skill_num,skill_lv,wd.flag);
  3207. }
  3208. if( wd.damage2 )
  3209. {
  3210. wd.damage2 = battle_calc_damage(src,target,&wd,wd.damage2,skill_num,skill_lv,s_ele_);
  3211. if( map_flag_gvg2(target->m) )
  3212. wd.damage2 = battle_calc_gvg_damage(src,target,wd.damage2,wd.div_,skill_num,skill_lv,wd.flag);
  3213. else if( map[target->m].flag.battleground )
  3214. wd.damage = battle_calc_bg_damage(src,target,wd.damage2,wd.div_,skill_num,skill_lv,wd.flag);
  3215. }
  3216. }
  3217.  
  3218. if(skill_num==ASC_BREAKER)
  3219. { //Breaker's int-based damage (a misc attack?)
  3220. struct Damage md = battle_calc_misc_attack(src, target, skill_num, skill_lv, wflag);
  3221. wd.damage += md.damage;
  3222. }
  3223.  
  3224. //SG_FUSION hp penalty [Komurka]
  3225. if( sc && sc->data[SC_FUSION] )
  3226. {
  3227. int hp = sstatus->max_hp;
  3228. if( sd && tsd )
  3229. {
  3230. hp = 8 * hp / 100;
  3231. if( 100 * sstatus->hp <= 20 * sstatus->max_hp )
  3232. hp = sstatus->hp;
  3233. }
  3234. else
  3235. hp = 2 * hp / 100; //2% hp loss per hit
  3236. status_zap(src, hp, 0);
  3237. }
  3238.  
  3239. if( sc && sc->data[SC_ENCHANTBLADE] && !skill_num && sd && ((flag.rh && sd->weapontype1) || (flag.lh && sd->weapontype2)) ) // Only regular melee attacks are increased. A weapon must be equiped. [pakpil]
  3240. { // Magic damage from Enchant Blade
  3241. struct Damage md = battle_calc_magic_attack(src, target, RK_ENCHANTBLADE, ((TBL_PC*)src)->status.skill[RK_ENCHANTBLADE].lv, wflag);
  3242. wd.damage += md.damage;
  3243. wd.flag |= md.flag;
  3244. }
  3245. if( skill_num == LG_RAYOFGENESIS )
  3246. {
  3247. struct Damage md = battle_calc_magic_attack(src, target, skill_num, skill_lv, wflag);
  3248. wd.damage += md.damage;
  3249. }
  3250.  
  3251. return wd;
  3252. }
  3253.  
  3254. /*==========================================
  3255. * battle_calc_magic_attack [DracoRPG]
  3256. *------------------------------------------*/
  3257. struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list *target,int skill_num,int skill_lv,int mflag)
  3258. {
  3259. int i, nk, s_level, s_job_level = 50;
  3260. short s_ele = skill_get_ele(skill_num, skill_lv);
  3261. unsigned int skillratio = 100; //Skill dmg modifiers.
  3262. char re_baselv_bonus = battle_config.renewal_baselvl_skill_ratio;//BaseLv config for renewal skills.
  3263.  
  3264. struct map_session_data *sd, *tsd;
  3265. struct Damage ad;
  3266. struct status_data *sstatus = status_get_status_data(src);
  3267. struct status_data *tstatus = status_get_status_data(target);
  3268. struct status_change *sc = status_get_sc(src);
  3269.  
  3270. struct
  3271. {
  3272. unsigned imdef : 1;
  3273. unsigned infdef : 1;
  3274. }flag;
  3275.  
  3276. memset(&ad,0,sizeof(ad));
  3277. memset(&flag,0,sizeof(flag));
  3278.  
  3279. if( src == NULL || target == NULL )
  3280. {
  3281. nullpo_info(NLP_MARK);
  3282. return ad;
  3283. }
  3284. sd = BL_CAST(BL_PC, src);
  3285. tsd = BL_CAST(BL_PC, target);
  3286.  
  3287. s_level = status_get_lv(src);
  3288. if( skill_num >= RK_ENCHANTBLADE && skill_num <= LG_OVERBRAND_PLUSATK &&
  3289. battle_config.max_highlvl_nerf && s_level > battle_config.max_highlvl_nerf )
  3290. s_level = battle_config.max_highlvl_nerf;
  3291.  
  3292. // Max Job Level bonus that skills should receive. Acording to battle_config.max_joblvl_nerf [Pinky]
  3293. if( sd && battle_config.max_joblvl_nerf)
  3294. s_job_level = min(sd->status.job_level,battle_config.max_joblvl_nerf);
  3295. else if ( sd )
  3296. s_job_level = sd->status.job_level;
  3297.  
  3298. //Initial Values
  3299. ad.damage = 1;
  3300. ad.amotion=skill_get_inf(skill_num)&INF_GROUND_SKILL?0:sstatus->amotion; //Amotion should be 0 for ground skills.
  3301. ad.dmotion=tstatus->dmotion;
  3302. ad.flag=BF_MAGIC|BF_SKILL;
  3303. ad.dmg_lv=ATK_DEF;
  3304. nk = skill_get_nk(skill_num);
  3305. flag.imdef = nk&NK_IGNORE_DEF?1:0;
  3306.  
  3307. // Skill Element Definition// I dont understand why were checking for skill level here. [Rytech]
  3308. if( skill_num == WL_HELLINFERNO )
  3309. {
  3310. if( skill_lv >= 0 )
  3311. s_ele = ELE_FIRE;
  3312. else
  3313. {
  3314. s_ele = ELE_DARK;
  3315. skill_lv = -skill_lv;
  3316. }
  3317. }
  3318. else if( skill_num == SO_PSYCHIC_WAVE && sc && (sc->data[SC_HEATER_OPTION] || sc->data[SC_COOLER_OPTION] ||
  3319. sc->data[SC_BLAST_OPTION] || sc->data[SC_CURSED_SOIL_OPTION]) )
  3320. { // Status change from Elemental Spirits that change Psychic Wave damage element.
  3321. if( sc->data[SC_HEATER_OPTION] ) s_ele = sc->data[SC_HEATER_OPTION]->val4;
  3322. else if( sc->data[SC_COOLER_OPTION] ) s_ele = sc->data[SC_COOLER_OPTION]->val4;
  3323. else if( sc->data[SC_BLAST_OPTION] ) s_ele = sc->data[SC_BLAST_OPTION]->val3;
  3324. else if( sc->data[SC_CURSED_SOIL_OPTION] ) s_ele = sc->data[SC_CURSED_SOIL_OPTION]->val4;
  3325. }
  3326. else
  3327. {
  3328. s_ele = skill_get_ele(skill_num, skill_lv);
  3329. if( s_ele == -1 )
  3330. s_ele = sstatus->rhw.ele;
  3331. else if( s_ele == -2 )
  3332. s_ele = status_get_attack_sc_element(src,sc);
  3333. else if( s_ele == -3 ) //Use random element
  3334. s_ele = rand()%ELE_MAX;
  3335. }
  3336.  
  3337. ad.div_=skill_get_num(skill_num,skill_lv);
  3338. ad.blewcount = skill_get_blewcount(skill_num,skill_lv);
  3339.  
  3340. //Set miscellaneous data that needs be filled
  3341. if(sd) {
  3342. sd->state.arrow_atk = 0;
  3343. ad.blewcount += battle_blewcount_bonus(sd, skill_num);
  3344. }
  3345.  
  3346. //Skill Range Criteria
  3347. ad.flag |= battle_range_type(src, target, skill_num, skill_lv);
  3348. flag.infdef = (tstatus->mode&MD_PLANT?1:0);
  3349. if( !flag.infdef && (target->type == BL_SKILL && ((TBL_SKILL*)target)->group->unit_id == UNT_REVERBERATION) )
  3350. flag.infdef = 1; // Reberberation takes 1 damage
  3351.  
  3352.  
  3353. switch(skill_num)
  3354. {
  3355. case MG_FIREWALL:
  3356. case NJ_KAENSIN:
  3357. case EL_FIRE_MANTLE:
  3358. ad.dmotion = 0; //No flinch animation.
  3359. if ( tstatus->def_ele == ELE_FIRE || battle_check_undead(tstatus->race, tstatus->def_ele) )
  3360. ad.blewcount = 0; //No knockback
  3361. break;
  3362. case PR_SANCTUARY:
  3363. ad.dmotion = 0; //No flinch animation.
  3364. break;
  3365. }
  3366.  
  3367. if (!flag.infdef) //No need to do the math for plants
  3368. {
  3369.  
  3370. //MATK_RATE scales the damage. 100 = no change. 50 is halved, 200 is doubled, etc
  3371. #define MATK_RATE( a ) { ad.damage= ad.damage*(a)/100; }
  3372. //Adds dmg%. 100 = +100% (double) damage. 10 = +10% damage
  3373. #define MATK_ADDRATE( a ) { ad.damage+= ad.damage*(a)/100; }
  3374. //Adds an absolute value to damage. 100 = +100 damage
  3375. #define MATK_ADD( a ) { ad.damage+= a; }
  3376.  
  3377. switch (skill_num)
  3378. { //Calc base damage according to skill
  3379. case AL_HEAL:
  3380. case PR_BENEDICTIO:
  3381. case PR_SANCTUARY:
  3382. case AB_HIGHNESSHEAL:
  3383. ad.damage = skill_calc_heal(src, target, skill_num, skill_lv, false);
  3384. break;
  3385. case PR_ASPERSIO:
  3386. ad.damage = 40;
  3387. break;
  3388. case ALL_RESURRECTION:
  3389. case PR_TURNUNDEAD:
  3390. //Undead check is on skill_castend_damageid code.
  3391. i = 20*skill_lv + sstatus->luk + sstatus->int_ + s_level
  3392. + 200 - 200*tstatus->hp/tstatus->max_hp;
  3393. if(i > 700) i = 700;
  3394. if(rand()%1000 < i && !(tstatus->mode&MD_BOSS))
  3395. ad.damage = tstatus->hp;
  3396. else
  3397. ad.damage = s_level + sstatus->int_ + skill_lv * 10;
  3398. break;
  3399. case PF_SOULBURN:
  3400. ad.damage = tstatus->sp * 2;
  3401. break;
  3402. /* Enable this if kRO fix the current skill. Currently no damage to undead or demons. [Jobbie]
  3403. case AB_EPICLESIS:
  3404. ad.damage = ??;
  3405. break;*/
  3406. case AB_RENOVATIO://Changed to a official formula, but this damage will later be applied differently through a duration. [Rytech]
  3407. ad.damage = 10 * s_level + sstatus->int_;
  3408. break;
  3409. default:
  3410. {
  3411. if( skill_num == RK_ENCHANTBLADE )
  3412. {
  3413. if( sc && sc->data[SC_ENCHANTBLADE] )
  3414. ad.damage += sc->data[SC_ENCHANTBLADE]->val2;
  3415. else
  3416. return ad;
  3417. }
  3418. if(sc && sc->data[SC_RECOGNIZEDSPELL]) {
  3419. MATK_ADD(sstatus->matk_max);
  3420. }
  3421. else if (sstatus->matk_max > sstatus->matk_min) {
  3422. MATK_ADD(sstatus->matk_min+rand()%(1+sstatus->matk_max-sstatus->matk_min));
  3423. } else {
  3424. MATK_ADD(sstatus->matk_min);
  3425. }
  3426.  
  3427. if(nk&NK_SPLASHSPLIT){ // Divide MATK in case of multiple targets skill
  3428. if(mflag>0)
  3429. ad.damage/= mflag;
  3430. else
  3431. ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_num, skill_get_name(skill_num));
  3432. }
  3433.  
  3434. switch( skill_num )
  3435. {
  3436. case MG_NAPALMBEAT:
  3437. case MG_FIREBALL:
  3438. skillratio += skill_lv*10-30;
  3439. break;
  3440. case MG_SOULSTRIKE:
  3441. if (battle_check_undead(tstatus->race,tstatus->def_ele))
  3442. skillratio += 5*skill_lv;
  3443. break;
  3444. case MG_COLDBOLT:
  3445. if ( sc )
  3446. {
  3447. if ( sc->data[SC_SPELLFIST] && (!sd || !sd->state.autocast))
  3448. {
  3449. skillratio = sc->data[SC_SPELLFIST]->val2 * 50 + sc->data[SC_SPELLFIST]->val4 * 100;//val2 = used spellfist level and val4 = used bolt level. [Rytech]
  3450. ad.div_ = 1;// ad mods, to make it work similar to regular hits [Xazax]
  3451. ad.flag = BF_WEAPON|BF_SHORT;
  3452. ad.type = 0;
  3453. }
  3454. if( sc->data[SC_AQUAPLAY_OPTION] )
  3455. skillratio += skillratio * sc->data[SC_AQUAPLAY_OPTION]->val3 / 100;
  3456. }
  3457. break;
  3458. case MG_FIREWALL:
  3459. skillratio -= 50;
  3460. if( sc && sc->data[SC_PYROTECHNIC_OPTION] )
  3461. skillratio += skillratio * sc->data[SC_PYROTECHNIC_OPTION]->val3 / 100;
  3462. break;
  3463. case MG_FIREBOLT:
  3464. if ( sc )
  3465. {
  3466. if ( sc->data[SC_SPELLFIST] && (!sd || !sd->state.autocast))
  3467. {
  3468. skillratio = sc->data[SC_SPELLFIST]->val2 * 50 + sc->data[SC_SPELLFIST]->val4 * 100;
  3469. ad.div_ = 1;
  3470. ad.flag = BF_WEAPON|BF_SHORT;
  3471. ad.type = 0;
  3472. }
  3473. if( sc->data[SC_PYROTECHNIC_OPTION] )
  3474. skillratio += skillratio * sc->data[SC_PYROTECHNIC_OPTION]->val3 / 100;
  3475. }
  3476. break;
  3477. case MG_LIGHTNINGBOLT:
  3478. if ( sc )
  3479. {
  3480. if ( sc->data[SC_SPELLFIST] && (!sd || !sd->state.autocast))
  3481. {
  3482. skillratio = sc->data[SC_SPELLFIST]->val2 * 50 + sc->data[SC_SPELLFIST]->val4 * 100;
  3483. ad.div_ = 1;
  3484. ad.flag = BF_WEAPON|BF_SHORT;
  3485. ad.type = 0;
  3486. }
  3487. if( sc->data[SC_GUST_OPTION] )
  3488. skillratio += skillratio * sc->data[SC_GUST_OPTION]->val2 / 100;
  3489. }
  3490. break;
  3491. case MG_THUNDERSTORM:
  3492. skillratio -= 20;
  3493. if( sc && sc->data[SC_GUST_OPTION] )
  3494. skillratio += skillratio * sc->data[SC_GUST_OPTION]->val2 / 100;
  3495. break;
  3496. case MG_FROSTDIVER:
  3497. skillratio += 10*skill_lv;
  3498. if( sc && sc->data[SC_AQUAPLAY_OPTION] )
  3499. skillratio += skillratio * sc->data[SC_AQUAPLAY_OPTION]->val3 / 100;
  3500. break;
  3501. case AL_HOLYLIGHT:
  3502. skillratio += 25;
  3503. if (sd && sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_PRIEST)
  3504. skillratio *= 5; //Does 5x damage include bonuses from other skills?
  3505. break;
  3506. case AL_RUWACH:
  3507. skillratio += 45;
  3508. break;
  3509. case WZ_FROSTNOVA:
  3510. skillratio += (100+skill_lv*10)*2/3-100;
  3511. break;
  3512. case WZ_FIREPILLAR:
  3513. if (skill_lv > 10)
  3514. skillratio += 100;
  3515. else
  3516. skillratio -= 80;
  3517. break;
  3518. case WZ_SIGHTRASHER:
  3519. skillratio += 20*skill_lv;
  3520. break;
  3521. case WZ_VERMILION:
  3522. skillratio += 20*skill_lv-20;
  3523. break;
  3524. case WZ_WATERBALL:
  3525. skillratio += 30*skill_lv;
  3526. break;
  3527. case WZ_EARTHSPIKE:
  3528. case WZ_HEAVENDRIVE:
  3529. if( sc && sc->data[SC_PETROLOGY_OPTION] )
  3530. skillratio += skillratio * sc->data[SC_PETROLOGY_OPTION]->val3 / 100;
  3531. break;
  3532. case WZ_STORMGUST:
  3533. skillratio += 40*skill_lv;
  3534. break;
  3535. case HW_NAPALMVULCAN:
  3536. skillratio += 10*skill_lv-30;
  3537. break;
  3538. case SL_STIN:
  3539. skillratio += (tstatus->size?-99:10*skill_lv); //target size must be small (0) for full damage.
  3540. break;
  3541. case SL_STUN:
  3542. skillratio += (tstatus->size!=2?5*skill_lv:-99); //Full damage is dealt on small/medium targets
  3543. break;
  3544. case SL_SMA:
  3545. skillratio += -60 + s_level; //Base damage is 40% + lv%
  3546. break;
  3547. case NJ_KOUENKA:
  3548. skillratio -= 10;
  3549. break;
  3550. case NJ_KAENSIN:
  3551. skillratio -= 50;
  3552. break;
  3553. case NJ_BAKUENRYU:
  3554. skillratio += 50*(skill_lv-1);
  3555. break;
  3556. case NJ_HYOUSYOURAKU:
  3557. skillratio += 50*skill_lv;
  3558. break;
  3559. case NJ_RAIGEKISAI:
  3560. skillratio += 60 + 40*skill_lv;
  3561. break;
  3562. case NJ_KAMAITACHI:
  3563. case NPC_ENERGYDRAIN:
  3564. skillratio += 100*skill_lv;
  3565. break;
  3566. case NPC_EARTHQUAKE:
  3567. skillratio += 100 + 100*skill_lv + 100*(skill_lv/2);
  3568. break;
  3569. case AB_JUDEX:
  3570. skillratio += 180 + 20 * skill_lv;
  3571. if (skill_lv > 4) skillratio += 20;
  3572. if( re_baselv_bonus == 1 && s_level >= 100 )
  3573. skillratio = skillratio * s_level / 100; // Base level bonus.
  3574. break;
  3575. case AB_ADORAMUS:
  3576. skillratio += 400 + 100 * skill_lv;
  3577. if( re_baselv_bonus == 1 && s_level >= 100 )
  3578. skillratio = skillratio * s_level / 100; // Base level bonus.
  3579. break;
  3580. case AB_DUPLELIGHT_MAGIC:
  3581. skillratio += 100 + 20 * skill_lv;
  3582. break;
  3583. case WL_SOULEXPANSION:
  3584. skillratio += 300 + 100 * skill_lv + sstatus->int_;
  3585. if( re_baselv_bonus == 1 && s_level >= 100 )
  3586. skillratio = skillratio * s_level / 100; // Base level bonus.
  3587. break;
  3588. case WL_FROSTMISTY:
  3589. skillratio += 100 + 100 * skill_lv;
  3590. if( re_baselv_bonus == 1 && s_level >= 100 )
  3591. skillratio = skillratio * s_level / 100; // Base level bonus.
  3592. break;
  3593. case WL_JACKFROST:
  3594. {
  3595. struct status_change *tsc = status_get_sc(target);
  3596. if( tsc && tsc->data[SC_FREEZING] )
  3597. {
  3598. skillratio += 900 + 300 * skill_lv;
  3599. if( re_baselv_bonus == 1 && s_level >= 100 )
  3600. skillratio = skillratio * s_level / 100; // Base level bonus.
  3601. }
  3602. else
  3603. skillratio += 400 + 100 * skill_lv;
  3604. if( re_baselv_bonus == 1 && s_level >= 100 )
  3605. skillratio = skillratio * s_level / 150; // Base level bonus.
  3606. }
  3607. break;
  3608. case WL_DRAINLIFE:
  3609. skillratio = 200 * skill_lv + sstatus->int_;
  3610. if( re_baselv_bonus == 1 && s_level >= 100 )
  3611. skillratio = skillratio * s_level / 100; // Base level bonus.
  3612. break;
  3613. case WL_CRIMSONROCK:
  3614. skillratio += 1200 + 300 * skill_lv;//2011 document says the 1300+ is applied after the base level bonus. Must confirm. [Rytech]
  3615. if( re_baselv_bonus == 1 && s_level >= 100 )
  3616. skillratio = skillratio * s_level / 100; // Base level bonus.
  3617. break;
  3618. case WL_HELLINFERNO:
  3619. if( s_ele == ELE_FIRE )
  3620. skillratio = 60 * skill_lv;
  3621. else
  3622. skillratio = 240 * skill_lv;
  3623. if( re_baselv_bonus == 1 && s_level >= 100 )
  3624. skillratio = skillratio * s_level / 100; // Base level bonus.
  3625. break;
  3626. case WL_COMET:
  3627. i = distance_xy(target->x, target->y, sc->comet_x, sc->comet_y);
  3628. if( i < 4 ) skillratio = 2500 + 500 * skill_lv;
  3629. else
  3630. if( i < 6 ) skillratio = 2000 + 500 * skill_lv;
  3631. else
  3632. if( i < 8 ) skillratio = 1500 + 500 * skill_lv;
  3633. else
  3634. skillratio = 1000 + 500 * skill_lv;
  3635. break;
  3636. case WL_CHAINLIGHTNING_ATK:
  3637. skillratio += 400 + 100 * skill_lv + 500;//Will replace the 500 with the bounce part to the formula soon. [Rytech]
  3638. if( re_baselv_bonus == 1 && s_level >= 100 )
  3639. skillratio = skillratio * s_level / 100; // Base level bonus.
  3640. break;
  3641. case WL_EARTHSTRAIN:
  3642. skillratio += 1900 + 100 * skill_lv;
  3643. if( re_baselv_bonus == 1 && s_level >= 100 )
  3644. skillratio = skillratio * s_level / 100; // Base level bonus.
  3645. break;
  3646. case WL_TETRAVORTEX_FIRE:
  3647. case WL_TETRAVORTEX_WATER:
  3648. case WL_TETRAVORTEX_WIND:
  3649. case WL_TETRAVORTEX_GROUND:
  3650. skillratio += 400 + 500 * skill_lv;
  3651. break;
  3652. case WL_SUMMON_ATK_FIRE:
  3653. case WL_SUMMON_ATK_WATER:
  3654. case WL_SUMMON_ATK_WIND:
  3655. case WL_SUMMON_ATK_GROUND:
  3656. if( re_baselv_bonus == 1 && s_level >= 100 )
  3657. skillratio = skill_lv * (s_level + s_job_level);// This is close to official, but lacking a little info to finalize. [Rytech]
  3658. else
  3659. skillratio = skill_lv * 200;
  3660. if( re_baselv_bonus == 1 && s_level >= 100 )
  3661. skillratio += skillratio * (s_level - 100) / 200; // Base level bonus.
  3662. break;
  3663. case LG_SHIELDSPELL:
  3664. if ( sd && skill_lv == 2 )
  3665. if( battle_config.renewal_baselvl_skill_effect == 1 && status_get_lv(src) >= 100 )
  3666. skillratio = 4 * s_level + 100 * sd->shieldmdef + 2 * sstatus->int_;
  3667. else
  3668. skillratio = 600 + 100 * sd->shieldmdef + 2 * sstatus->int_;
  3669. else
  3670. skillratio = 0;//Prevents MATK damage from being done on LV 1 usage since LV 1 us ATK. [Rytech]
  3671. break;
  3672. case LG_RAYOFGENESIS:
  3673. skillratio = 300 * skill_lv;
  3674. // 200 * Number of Royal Guards in banding status check needed here.
  3675. //if( sc && sc->data[SC_BANDING] )
  3676. if( re_baselv_bonus == 1 && s_level >= 100 )
  3677. skillratio = skillratio * s_job_level / 25; // Job level bonus.
  3678. break;
  3679. case WM_METALICSOUND:
  3680. skillratio = 120 * skill_lv + 60 * pc_checkskill(sd, WM_LESSON);
  3681. if( re_baselv_bonus == 1 && s_level >= 100 )
  3682. skillratio = skillratio * s_level / 100; // Base level bonus.
  3683. break;
  3684. case WM_REVERBERATION_MAGIC:
  3685. skillratio += 100 * skill_lv;
  3686. if( re_baselv_bonus == 1 && s_level >= 100 )
  3687. skillratio = skillratio * s_level / 100; // Base level bonus.
  3688. break;
  3689. case SO_FIREWALK:
  3690. skillratio = 60 * skill_lv;
  3691. if( re_baselv_bonus == 1 && s_level >= 100 )
  3692. skillratio = skillratio * s_level / 100; // Base level bonus.
  3693. if( sc && sc->data[SC_HEATER_OPTION] )
  3694. skillratio += skillratio * sc->data[SC_HEATER_OPTION]->val3 / 100;
  3695. break;
  3696. case SO_ELECTRICWALK:
  3697. skillratio = 60 * skill_lv;
  3698. if( re_baselv_bonus == 1 && s_level >= 100 )
  3699. skillratio = skillratio * s_level / 100; // Base level bonus.
  3700. if( sc && sc->data[SC_BLAST_OPTION] )
  3701. skillratio += skillratio * sc->data[SC_BLAST_OPTION]->val2 / 100;
  3702. break;
  3703. case SO_EARTHGRAVE:
  3704. skillratio = sstatus->int_ * skill_lv + 200 * pc_checkskill(sd, SA_SEISMICWEAPON);
  3705. if( re_baselv_bonus == 1 && s_level >= 100 )
  3706. skillratio = skillratio * s_level/ 100; // Base level bonus.
  3707. if( sc && sc->data[SC_CURSED_SOIL_OPTION] )
  3708. skillratio += skillratio * sc->data[SC_CURSED_SOIL_OPTION]->val2 / 100;
  3709. break;
  3710. case SO_DIAMONDDUST:
  3711. skillratio = sstatus->int_ * skill_lv + 200 * pc_checkskill(sd, SA_FROSTWEAPON);
  3712. if( re_baselv_bonus == 1 && s_level >= 100 )
  3713. skillratio = skillratio * s_level / 100; // Base level bonus.
  3714. if( sc && sc->data[SC_COOLER_OPTION] )
  3715. skillratio += skillratio * sc->data[SC_COOLER_OPTION]->val3 / 100;
  3716. break;
  3717. case SO_POISON_BUSTER:
  3718. skillratio += 900 + 300 * skill_lv;
  3719. if( re_baselv_bonus == 1 && s_level >= 100 )
  3720. skillratio = skillratio * s_level / 120; // Base level bonus.
  3721. if( sc && sc->data[SC_CURSED_SOIL_OPTION] )
  3722. skillratio += skillratio * sc->data[SC_CURSED_SOIL_OPTION]->val2 / 100;
  3723. break;
  3724. case SO_PSYCHIC_WAVE:
  3725. skillratio = 70 * skill_lv + 3 * sstatus->int_;
  3726. if( re_baselv_bonus == 1 && s_level >= 100 )
  3727. skillratio = skillratio * s_level / 100; // Base level bonus.
  3728. if( sc )
  3729. {
  3730. if( sc->data[SC_HEATER_OPTION] )
  3731. skillratio += skillratio * sc->data[SC_HEATER_OPTION]->val3 / 100;
  3732. else if(sc->data[SC_COOLER_OPTION] )
  3733. skillratio += skillratio * sc->data[SC_COOLER_OPTION]->val3 / 100;
  3734. else if(sc->data[SC_BLAST_OPTION] )
  3735. skillratio += skillratio * sc->data[SC_BLAST_OPTION]->val2 / 100;
  3736. else if(sc->data[SC_CURSED_SOIL_OPTION] )
  3737. skillratio += skillratio * sc->data[SC_CURSED_SOIL_OPTION]->val3 / 100;
  3738. }
  3739. break;
  3740. case SO_CLOUD_KILL:
  3741. skillratio = 40 * skill_lv;
  3742. if( re_baselv_bonus == 1 && s_level >= 100 )
  3743. skillratio = skillratio * s_level / 100; // Base level bonus.
  3744. if( sc && sc->data[SC_CURSED_SOIL_OPTION] )
  3745. skillratio += skillratio * sc->data[SC_CURSED_SOIL_OPTION]->val2 / 100;
  3746. break;
  3747. case SO_VARETYR_SPEAR:
  3748. skillratio = sstatus->int_ * skill_lv + 50 * pc_checkskill(sd, SA_LIGHTNINGLOADER);
  3749. if( re_baselv_bonus == 1 && s_level >= 100 )
  3750. skillratio = skillratio * s_level / 100; // Base level bonus.
  3751. if( sc && sc->data[SC_BLAST_OPTION] )
  3752. skillratio += skillratio * sc->data[SC_BLAST_OPTION]->val2 / 100;
  3753. break;
  3754. case GN_DEMONIC_FIRE:
  3755. if( skill_lv > 20)
  3756. { // Fire expansion Lv.2
  3757. skillratio += 110 + 20 * (skill_lv - 20) + status_get_int(src) * 3; // Need official INT bonus. [LimitLine]
  3758. }
  3759. else if( skill_lv > 10 )
  3760. { // Fire expansion Lv.1
  3761. skillratio += 110 + 20 * (skill_lv - 10) / 2;
  3762. }
  3763. else
  3764. skillratio += 110 + 20 * skill_lv;
  3765. break;
  3766. // Magical Elemental Spirits Attack Skills
  3767. case EL_FIRE_MANTLE:
  3768. case EL_WATER_SCREW:
  3769. skillratio += 900;
  3770. break;
  3771. case EL_FIRE_ARROW:
  3772. case EL_ROCK_CRUSHER_ATK:
  3773. skillratio += 200;
  3774. break;
  3775. case EL_FIRE_BOMB:
  3776. case EL_ICE_NEEDLE:
  3777. case EL_HURRICANE_ATK:
  3778. skillratio += 400;
  3779. break;
  3780. case EL_FIRE_WAVE:
  3781. case EL_TYPOON_MIS_ATK:
  3782. skillratio += 1100;
  3783. break;
  3784. }
  3785.  
  3786. MATK_RATE(skillratio);
  3787.  
  3788. //Constant/misc additions from skills
  3789. if (skill_num == WZ_FIREPILLAR)
  3790. MATK_ADD(50);
  3791. }
  3792. }
  3793.  
  3794. if(sd) {
  3795. //Damage bonuses
  3796. if ((i = pc_skillatk_bonus(sd, skill_num)))
  3797. ad.damage += ad.damage*i/100;
  3798.  
  3799. //Ignore Defense?
  3800. if (!flag.imdef && (
  3801. sd->ignore_mdef_ele & (1<<tstatus->def_ele) ||
  3802. sd->ignore_mdef_race & (1<<tstatus->race) ||
  3803. sd->ignore_mdef_race & (is_boss(target)?1<<RC_BOSS:1<<RC_NONBOSS)
  3804. ))
  3805. flag.imdef = 1;
  3806. }
  3807.  
  3808. if(!flag.imdef){
  3809. char mdef = tstatus->mdef;
  3810. int mdef2= tstatus->mdef2;
  3811. if(sd) {
  3812. i = sd->ignore_mdef[is_boss(target)?RC_BOSS:RC_NONBOSS];
  3813. i+= sd->ignore_mdef[tstatus->race];
  3814. if (i)
  3815. {
  3816. if (i > 100) i = 100;
  3817. mdef -= mdef * i/100;
  3818. //mdef2-= mdef2* i/100;
  3819. }
  3820. }
  3821. if(battle_config.magic_defense_type)
  3822. ad.damage = ad.damage - mdef*battle_config.magic_defense_type - mdef2;
  3823. else
  3824. ad.damage = ad.damage * (100-mdef)/100 - mdef2;
  3825. }
  3826.  
  3827. if (skill_num == NPC_EARTHQUAKE)
  3828. { //Adds atk2 to the damage, should be influenced by number of hits and skill-ratio, but not mdef reductions. [Skotlex]
  3829. //Also divide the extra bonuses from atk2 based on the number in range [Kevin]
  3830. if(mflag>0)
  3831. ad.damage+= (sstatus->rhw.atk2*skillratio/100)/mflag;
  3832. else
  3833. ShowError("Zero range by %d:%s, divide per 0 avoided!\n", skill_num, skill_get_name(skill_num));
  3834. }
  3835.  
  3836. if(ad.damage<1)
  3837. ad.damage=1;
  3838.  
  3839. if (!(nk&NK_NO_ELEFIX))
  3840. ad.damage=battle_attr_fix(src, target, ad.damage, s_ele, tstatus->def_ele, tstatus->ele_lv);
  3841.  
  3842. if( skill_num == CR_GRANDCROSS || skill_num == NPC_GRANDDARKNESS )
  3843. { //Apply the physical part of the skill's damage. [Skotlex]
  3844. struct Damage wd = battle_calc_weapon_attack(src,target,skill_num,skill_lv,mflag);
  3845. ad.damage = battle_attr_fix(src, target, wd.damage + ad.damage, s_ele, tstatus->def_ele, tstatus->ele_lv) * (100 + 40*skill_lv)/100;
  3846. if( src == target )
  3847. {
  3848. if( src->type == BL_PC )
  3849. ad.damage = ad.damage/2;
  3850. else
  3851. ad.damage = 0;
  3852. }
  3853. }
  3854.  
  3855. if (sd && !(nk&NK_NO_CARDFIX_ATK)) {
  3856. short t_class = status_get_class(target);
  3857. short cardfix=1000;
  3858.  
  3859. cardfix=cardfix*(100+sd->magic_addrace[tstatus->race])/100;
  3860. if (!(nk&NK_NO_ELEFIX))
  3861. cardfix=cardfix*(100+sd->magic_addele[tstatus->def_ele])/100;
  3862. cardfix=cardfix*(100+sd->magic_addsize[tstatus->size])/100;
  3863. cardfix=cardfix*(100+sd->magic_addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100;
  3864. for(i=0; i< ARRAYLENGTH(sd->add_mdmg) && sd->add_mdmg[i].rate;i++) {
  3865. if(sd->add_mdmg[i].class_ == t_class) {
  3866. cardfix=cardfix*(100+sd->add_mdmg[i].rate)/100;
  3867. continue;
  3868. }
  3869. }
  3870. if (cardfix != 1000)
  3871. MATK_RATE(cardfix/10);
  3872. }
  3873.  
  3874. if( tsd && !(nk&NK_NO_CARDFIX_DEF) )
  3875. { // Target cards.
  3876. short s_race2 = status_get_race2(src);
  3877. short s_class= status_get_class(src);
  3878. int cardfix=1000;
  3879.  
  3880. if (!(nk&NK_NO_ELEFIX))
  3881. {
  3882. int ele_fix = tsd->subele[s_ele];
  3883. for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++)
  3884. {
  3885. if(tsd->subele2[i].ele != s_ele) continue;
  3886. if(!(tsd->subele2[i].flag&ad.flag&BF_WEAPONMASK &&
  3887. tsd->subele2[i].flag&ad.flag&BF_RANGEMASK &&
  3888. tsd->subele2[i].flag&ad.flag&BF_SKILLMASK))
  3889. continue;
  3890. ele_fix += tsd->subele2[i].rate;
  3891. }
  3892. cardfix=cardfix*(100-ele_fix)/100;
  3893. }
  3894. cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100;
  3895. cardfix=cardfix*(100-tsd->subrace2[s_race2])/100;
  3896. cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100;
  3897. cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100;
  3898. if( sstatus->race != RC_DEMIHUMAN )
  3899. cardfix=cardfix*(100-tsd->subrace[RC_NONDEMIHUMAN])/100;
  3900.  
  3901. for(i=0; i < ARRAYLENGTH(tsd->add_mdef) && tsd->add_mdef[i].rate;i++) {
  3902. if(tsd->add_mdef[i].class_ == s_class) {
  3903. cardfix=cardfix*(100-tsd->add_mdef[i].rate)/100;
  3904. break;
  3905. }
  3906. }
  3907. //It was discovered that ranged defense also counts vs magic! [Skotlex]
  3908. if (ad.flag&BF_SHORT)
  3909. cardfix=cardfix*(100-tsd->near_attack_def_rate)/100;
  3910. else
  3911. cardfix=cardfix*(100-tsd->long_attack_def_rate)/100;
  3912.  
  3913. cardfix=cardfix*(100-tsd->magic_def_rate)/100;
  3914.  
  3915. if( tsd->sc.data[SC_MDEF_RATE] )
  3916. cardfix=cardfix*(100-tsd->sc.data[SC_MDEF_RATE]->val1)/100;
  3917.  
  3918. if (cardfix != 1000)
  3919. MATK_RATE(cardfix/10);
  3920. }
  3921. }
  3922.  
  3923. damage_div_fix(ad.damage, ad.div_);
  3924.  
  3925. if (flag.infdef && ad.damage)
  3926. {
  3927. ad.damage = ad.damage>0?1:-1;
  3928. if( skill_num == WL_JACKFROST || skill_num == WL_FROSTMISTY )
  3929. {
  3930. ad.damage = 0;
  3931. ad.dmg_lv = ATK_MISS;
  3932. }
  3933. }
  3934.  
  3935. ad.damage = battle_calc_damage(src,target,&ad,ad.damage,skill_num,skill_lv,s_ele);
  3936. if( map_flag_gvg2(target->m) )
  3937. ad.damage = battle_calc_gvg_damage(src,target,ad.damage,ad.div_,skill_num,skill_lv,ad.flag);
  3938. else if( map[target->m].flag.battleground )
  3939. ad.damage = battle_calc_bg_damage(src,target,ad.damage,ad.div_,skill_num,skill_lv,ad.flag);
  3940.  
  3941. if( skill_num == WL_HELLINFERNO && s_ele == ELE_FIRE )
  3942. { // Calculates Shadow Element Extra
  3943. struct Damage md = battle_calc_magic_attack(src,target,skill_num,-skill_lv,mflag);
  3944. ad.damage += md.damage;
  3945. }
  3946.  
  3947. if( skill_num == SO_VARETYR_SPEAR )
  3948. { // Physical damage.
  3949. struct Damage wd = battle_calc_weapon_attack(src,target,skill_num,skill_lv,mflag);
  3950. ad.damage += wd.damage;
  3951. }
  3952.  
  3953. return ad;
  3954. }
  3955.  
  3956. /*==========================================
  3957. * ???ì‘??_??[?W?v?Z
  3958. *------------------------------------------*/
  3959. struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *target,int skill_num,int skill_lv,int mflag)
  3960. {
  3961. int skill, s_level;
  3962. short i, nk;
  3963. short s_ele;
  3964. char re_baselv_bonus = battle_config.renewal_baselvl_skill_ratio;//BaseLv config for renewal skills.
  3965. int chorusbonus = 0;//Chorus bonus value for chorus skills. Bonus remains 0 unless 3 or more Minstrel's/Wanderer's are in the party.
  3966.  
  3967. struct map_session_data *sd, *tsd;
  3968. struct Damage md; //DO NOT CONFUSE with md of mob_data!
  3969. struct status_data *sstatus = status_get_status_data(src);
  3970. struct status_data *tstatus = status_get_status_data(target);
  3971.  
  3972. memset(&md,0,sizeof(md));
  3973.  
  3974. if( src == NULL || target == NULL ){
  3975. nullpo_info(NLP_MARK);
  3976. return md;
  3977. }
  3978.  
  3979. //Some initial values
  3980. md.amotion=skill_get_inf(skill_num)&INF_GROUND_SKILL?0:sstatus->amotion;
  3981. md.dmotion=tstatus->dmotion;
  3982. md.div_=skill_get_num( skill_num,skill_lv );
  3983. md.blewcount=skill_get_blewcount(skill_num,skill_lv);
  3984. md.dmg_lv=ATK_DEF;
  3985. md.flag=BF_MISC|BF_SKILL;
  3986.  
  3987. nk = skill_get_nk(skill_num);
  3988.  
  3989. sd = BL_CAST(BL_PC, src);
  3990. tsd = BL_CAST(BL_PC, target);
  3991.  
  3992. // Minstrel/Wanderer number check for chorus skills.
  3993. // Bonus remains 0 unless 3 or more Minstrel's/Wanderer's are in the party.
  3994. if( sd && sd->status.party_id && party_foreachsamemap(party_sub_count_chorus, sd, 0) > 7)
  3995. chorusbonus = 5;//Maximum effect possiable from 7 or more Minstrel's/Wanderer's
  3996. else if( sd && sd->status.party_id && party_foreachsamemap(party_sub_count_chorus, sd, 0) > 2)
  3997. chorusbonus = party_foreachsamemap(party_sub_count_chorus, sd, 0) - 2;//Effect bonus from additional Minstrel's/Wanderer's if not above the max possiable.
  3998.  
  3999. if(sd) {
  4000. sd->state.arrow_atk = 0;
  4001. md.blewcount += battle_blewcount_bonus(sd, skill_num);
  4002. }
  4003.  
  4004. s_ele = skill_get_ele(skill_num, skill_lv);
  4005. if (s_ele < 0 && s_ele != -3) //Attack that takes weapon's element for misc attacks? Make it neutral [Skotlex]
  4006. s_ele = ELE_NEUTRAL;
  4007. else if (s_ele == -3) //Use random element
  4008. s_ele = rand()%ELE_MAX;
  4009.  
  4010. //Skill Range Criteria
  4011. md.flag |= battle_range_type(src, target, skill_num, skill_lv);
  4012. s_level = status_get_lv(src);
  4013.  
  4014. switch( skill_num )
  4015. {
  4016. case HT_LANDMINE:
  4017. case MA_LANDMINE:
  4018. md.damage = skill_lv * (sstatus->dex + 75) * (100 + sstatus->int_) / 100;
  4019. break;
  4020. case HT_BLASTMINE:
  4021. md.damage = skill_lv * (sstatus->dex / 2 + 50)*(100 + sstatus->int_) / 100;
  4022. break;
  4023. case HT_CLAYMORETRAP:
  4024. md.damage = skill_lv * (sstatus->dex / 2 + 75)*(100 + sstatus->int_) / 100;
  4025. break;
  4026. case HT_BLITZBEAT:
  4027. case SN_FALCONASSAULT:
  4028. //Blitz-beat Damage.
  4029. if(!sd || (skill = pc_checkskill(sd,HT_STEELCROW)) <= 0)
  4030. skill=0;
  4031. md.damage=(sstatus->dex/10+sstatus->int_/2+skill*3+40)*2;
  4032. if(mflag > 1) //Autocasted Blitz.
  4033. nk|=NK_SPLASHSPLIT;
  4034.  
  4035. if (skill_num == SN_FALCONASSAULT)
  4036. {
  4037. //Div fix of Blitzbeat
  4038. skill = skill_get_num(HT_BLITZBEAT, 5);
  4039. damage_div_fix(md.damage, skill);
  4040.  
  4041. //Falcon Assault Modifier
  4042. md.damage=md.damage*(150+70*skill_lv)/100;
  4043. }
  4044. break;
  4045. case TF_THROWSTONE:
  4046. md.damage=50;
  4047. break;
  4048. case BA_DISSONANCE:
  4049. md.damage=30+skill_lv*10;
  4050. if (sd)
  4051. md.damage+= 3*pc_checkskill(sd,BA_MUSICALLESSON);
  4052. break;
  4053. case NPC_SELFDESTRUCTION:
  4054. md.damage = sstatus->hp;
  4055. break;
  4056. case NPC_SMOKING:
  4057. md.damage=3;
  4058. break;
  4059. case NPC_DARKBREATH:
  4060. md.damage = 500 + (skill_lv-1)*1000 + rand()%1000;
  4061. if(md.damage > 9999) md.damage = 9999;
  4062. break;
  4063. case PA_PRESSURE:
  4064. md.damage=500+300*skill_lv;
  4065. break;
  4066. case PA_GOSPEL:
  4067. md.damage = 1+rand()%9999;
  4068. break;
  4069. case CR_ACIDDEMONSTRATION: // updated the formula based on a Japanese formula found to be exact [Reddozen]
  4070. if(tstatus->vit+sstatus->int_) //crash fix
  4071. md.damage = (int)((int64)7*tstatus->vit*sstatus->int_*sstatus->int_ / (10*(tstatus->vit+sstatus->int_)));
  4072. else
  4073. md.damage = 0;
  4074. if (tsd) md.damage>>=1;
  4075. if (md.damage < 0 || md.damage > INT_MAX>>1)
  4076. //Overflow prevention, will anyone whine if I cap it to a few billion?
  4077. //Not capped to INT_MAX to give some room for further damage increase.
  4078. md.damage = INT_MAX>>1;
  4079. break;
  4080. case NJ_ZENYNAGE:
  4081. md.damage = skill_get_zeny(skill_num ,skill_lv);
  4082. if (!md.damage) md.damage = 2;
  4083. md.damage = md.damage + rand()%md.damage;
  4084. if (is_boss(target))
  4085. md.damage=md.damage/3;
  4086. else if (tsd)
  4087. md.damage=md.damage/2;
  4088. break;
  4089. case GS_FLING:
  4090. md.damage = sd ? sd->status.job_level : status_get_lv(src);
  4091. break;
  4092. case HVAN_EXPLOSION: //[orn]
  4093. md.damage = sstatus->max_hp * (50 + 50 * skill_lv) / 100 ;
  4094. break ;
  4095. case ASC_BREAKER:
  4096. md.damage = 500 + rand()%500 + 5 * skill_lv * sstatus->int_;
  4097. nk|=NK_IGNORE_FLEE|NK_NO_ELEFIX; //These two are not properties of the weapon based part.
  4098. break;
  4099. case HW_GRAVITATION:
  4100. md.damage = 200 + 200 * skill_lv;
  4101. md.dmotion = 0; //No flinch animation.
  4102. break;
  4103. case NPC_EVILLAND:
  4104. md.damage = skill_calc_heal(src,target,skill_num,skill_lv,false);
  4105. break;
  4106. case RK_DRAGONBREATH:
  4107. if( battle_config.skillsbonus_maxhp_RK && sstatus->hp > battle_config.skillsbonus_maxhp_RK ) // [Pinky]
  4108. md.damage = ((battle_config.skillsbonus_maxhp_RK / 50) + (status_get_max_sp(src) / 4)) * skill_lv;
  4109. else
  4110. md.damage = ((sstatus->hp / 50) + (status_get_max_sp(src) / 4)) * skill_lv;
  4111. if ( re_baselv_bonus == 1 && s_level >= 100 )
  4112. md.damage = md.damage * s_level / 150;// Base level bonus.
  4113. if (sd) md.damage = md.damage * (100 + 5 * (pc_checkskill(sd,RK_DRAGONTRAINING) - 1)) / 100;
  4114. break;
  4115. case RA_CLUSTERBOMB:
  4116. case RA_FIRINGTRAP:
  4117. case RA_ICEBOUNDTRAP:
  4118. md.damage = skill_lv * sstatus->dex + 5 * sstatus->int_;
  4119. if ( re_baselv_bonus == 1 && s_level >= 100 )
  4120. md.damage = md.damage * 150 / 100 + md.damage * s_level / 100;// Base level bonus.
  4121. else
  4122. md.damage = md.damage * 250 / 100;
  4123. md.damage = md.damage * (20 * pc_checkskill(sd,RA_RESEARCHTRAP)) / 50;
  4124. break;
  4125. case NC_SELFDESTRUCTION:
  4126. md.damage = (1 + skill_lv) * (8 + pc_checkskill(sd,NC_MAINFRAME)) * (status_get_sp(src) + sstatus->vit);
  4127. if ( re_baselv_bonus == 1 && s_level >= 100 )
  4128. md.damage = md.damage * s_level / 100;// Base level bonus.
  4129. md.damage = md.damage + sstatus->hp;
  4130. if (sd) status_set_sp(src, 0, 0);
  4131. break;
  4132. case WM_SOUND_OF_DESTRUCTION:
  4133. md.damage = 1000 * skill_lv + sstatus->int_ * pc_checkskill(sd,WM_LESSON);
  4134. md.damage += md.damage * ( 10 * chorusbonus ) / 100;
  4135. break;
  4136. //case WM_SATURDAY_NIGHT_FEVER://Test me in official if possiable.
  4137. // md.damage = 9999;//To enable when I figure how it exactly applies the damage. For now clif damage will deal 9999 damage and display it. [Rytech]
  4138. // break;
  4139. case GN_THORNS_TRAP:
  4140. md.damage = 100 + 200 * skill_lv + sstatus->int_;
  4141. break;
  4142. case GN_BLOOD_SUCKER:
  4143. md.damage = 200 + 100 * skill_lv + sstatus->int_;
  4144. break;
  4145. case GN_HELLS_PLANT_ATK:
  4146. // -- edited MyRO md.damage = sstatus->int_ * 4 * skill_lv * (10 / (10 - pc_checkskill(sd,AM_CANNIBALIZE)));//Need accurate official formula. [Rytech]
  4147. md.damage = ((sstatus->int_ * 25) + (status_get_lv(target) * 15) * skill_lv) + (10 / (10 - pc_checkskill(sd,AM_CANNIBALIZE)));
  4148. break;
  4149. case KO_MUCHANAGE:
  4150. md.damage = skill_get_zeny(skill_num ,skill_lv) / 2;
  4151. if (!md.damage) md.damage = 10;
  4152. md.damage = md.damage + rand()%md.damage;
  4153. if (is_boss(target) || (tsd))
  4154. md.damage = md.damage / 2;
  4155. break;
  4156. }
  4157.  
  4158. if (nk&NK_SPLASHSPLIT){ // Divide ATK among targets
  4159. if(mflag>0)
  4160. md.damage/= mflag;
  4161. else
  4162. ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_num, skill_get_name(skill_num));
  4163. }
  4164.  
  4165. damage_div_fix(md.damage, md.div_);
  4166.  
  4167. if (!(nk&NK_IGNORE_FLEE))
  4168. {
  4169. struct status_change *sc = status_get_sc(target);
  4170. i = 0; //Temp for "hit or no hit"
  4171. if(sc && sc->opt1 && sc->opt1 != OPT1_STONEWAIT)
  4172. i = 1;
  4173. else {
  4174. short
  4175. flee = tstatus->flee,
  4176. hitrate=80; //Default hitrate
  4177.  
  4178. if(battle_config.agi_penalty_type &&
  4179. battle_config.agi_penalty_target&target->type)
  4180. {
  4181. unsigned char attacker_count; //256 max targets should be a sane max
  4182. attacker_count = unit_counttargeted(target,battle_config.agi_penalty_count_lv);
  4183. if(attacker_count >= battle_config.agi_penalty_count)
  4184. {
  4185. if (battle_config.agi_penalty_type == 1)
  4186. flee = (flee * (100 - (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num))/100;
  4187. else //asume type 2: absolute reduction
  4188. flee -= (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num;
  4189. if(flee < 1) flee = 1;
  4190. }
  4191. }
  4192.  
  4193. hitrate+= sstatus->hit - flee;
  4194. hitrate = cap_value(hitrate, battle_config.min_hitrate, battle_config.max_hitrate);
  4195.  
  4196. if(rand()%100 < hitrate)
  4197. i = 1;
  4198. }
  4199. if (!i) {
  4200. md.damage = 0;
  4201. md.dmg_lv=ATK_FLEE;
  4202. }
  4203. }
  4204.  
  4205. if( md.damage && tsd && !(nk&NK_NO_CARDFIX_DEF) )
  4206. {// misc damage reduction from equipment
  4207. int cardfix = 10000;
  4208. int race2 = status_get_race2(src);
  4209. if (!(nk&NK_NO_ELEFIX))
  4210. {
  4211. int ele_fix = tsd->subele[s_ele];
  4212. for (i = 0; ARRAYLENGTH(tsd->subele2) > i && tsd->subele2[i].rate != 0; i++)
  4213. {
  4214. if(tsd->subele2[i].ele != s_ele) continue;
  4215. if(!(tsd->subele2[i].flag&md.flag&BF_WEAPONMASK &&
  4216. tsd->subele2[i].flag&md.flag&BF_RANGEMASK &&
  4217. tsd->subele2[i].flag&md.flag&BF_SKILLMASK))
  4218. continue;
  4219. ele_fix += tsd->subele2[i].rate;
  4220. }
  4221. cardfix=cardfix*(100-ele_fix)/100;
  4222. }
  4223. cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100;
  4224. cardfix=cardfix*(100-tsd->subrace2[race2])/100;
  4225. cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100;
  4226. cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100;
  4227. if( sstatus->race != RC_DEMIHUMAN )
  4228. cardfix=cardfix*(100-tsd->subrace[RC_NONDEMIHUMAN])/100;
  4229.  
  4230. cardfix=cardfix*(100-tsd->misc_def_rate)/100;
  4231. if(md.flag&BF_SHORT)
  4232. cardfix=cardfix*(100-tsd->near_attack_def_rate)/100;
  4233. else // BF_LONG (there's no other choice)
  4234. cardfix=cardfix*(100-tsd->long_attack_def_rate)/100;
  4235.  
  4236. if (cardfix != 10000)
  4237. md.damage=(int)((int64)md.damage*cardfix/10000);
  4238. }
  4239.  
  4240. if (sd && (i = pc_skillatk_bonus(sd, skill_num)))
  4241. md.damage += md.damage*i/100;
  4242.  
  4243. if(md.damage < 0)
  4244. md.damage = 0;
  4245. else if(md.damage && tstatus->mode&MD_PLANT)
  4246. md.damage = 1;
  4247.  
  4248. if(!(nk&NK_NO_ELEFIX))
  4249. md.damage=battle_attr_fix(src, target, md.damage, s_ele, tstatus->def_ele, tstatus->ele_lv);
  4250.  
  4251. md.damage = battle_calc_damage(src,target,&md,md.damage,skill_num,skill_lv,s_ele);
  4252. if( map_flag_gvg2(target->m) )
  4253. md.damage = battle_calc_gvg_damage(src,target,md.damage,md.div_,skill_num,skill_lv,md.flag);
  4254. else if( map[target->m].flag.battleground )
  4255. md.damage = battle_calc_bg_damage(src,target,md.damage,md.div_,skill_num,skill_lv,md.flag);
  4256.  
  4257. switch( skill_num )
  4258. {
  4259. case RA_CLUSTERBOMB:
  4260. case RA_FIRINGTRAP:
  4261. case RA_ICEBOUNDTRAP:
  4262. {
  4263. struct Damage wd;
  4264.  
  4265. wd = battle_calc_weapon_attack(src,target,skill_num,skill_lv,mflag);
  4266. md.damage += wd.damage;
  4267. }
  4268. break;
  4269. case NJ_ZENYNAGE:
  4270. if( sd )
  4271. {
  4272. if ( md.damage > sd->status.zeny )
  4273. md.damage = sd->status.zeny;
  4274. pc_payzeny(sd, md.damage);
  4275. }
  4276. break;
  4277. }
  4278.  
  4279. return md;
  4280. }
  4281. /*==========================================
  4282. * ?_??[?W?v?Z?ê????—?—p
  4283. *------------------------------------------*/
  4284. struct Damage battle_calc_attack(int attack_type,struct block_list *bl,struct block_list *target,int skill_num,int skill_lv,int count)
  4285. {
  4286. struct Damage d;
  4287. switch( attack_type )
  4288. {
  4289. case BF_WEAPON: d = battle_calc_weapon_attack(bl,target,skill_num,skill_lv,count); break;
  4290. case BF_MAGIC: d = battle_calc_magic_attack(bl,target,skill_num,skill_lv,count); break;
  4291. case BF_MISC: d = battle_calc_misc_attack(bl,target,skill_num,skill_lv,count); break;
  4292. default:
  4293. ShowError("battle_calc_attack: unknown attack type! %d\n",attack_type);
  4294. memset(&d,0,sizeof(d));
  4295. break;
  4296. }
  4297. if( d.damage + d.damage2 < 1 )
  4298. { //Miss/Absorbed
  4299. //Weapon attacks should go through to cause additional effects.
  4300. if (d.dmg_lv == ATK_DEF /*&& attack_type&(BF_MAGIC|BF_MISC)*/) // Isn't it that additional effects don't apply if miss?
  4301. d.dmg_lv = ATK_MISS;
  4302. d.dmotion = 0;
  4303. }
  4304. else // Some skills like Weaponry Research will cause damage even if attack is dodged
  4305. d.dmg_lv = ATK_DEF;
  4306. return d;
  4307. }
  4308.  
  4309. //Calculates BF_WEAPON returned damage.
  4310. int battle_calc_return_damage(struct block_list *src, struct block_list *bl, int *damage, int flag)
  4311. {
  4312. struct map_session_data* sd = NULL;
  4313. int rdamage = 0, max_damage = status_get_max_hp(bl);
  4314. struct status_change *sc = status_get_sc(bl);
  4315. struct status_change *ssc = status_get_sc(src);
  4316.  
  4317. sd = BL_CAST(BL_PC, bl);
  4318.  
  4319. //Bounces back part of the damage.
  4320. if( (flag&(BF_SHORT|BF_MAGIC)) == BF_SHORT )
  4321. {
  4322. if( sd && sd->short_weapon_damage_return )
  4323. {
  4324. rdamage += (*damage) * sd->short_weapon_damage_return / 100;
  4325. if(rdamage < 1) rdamage = 1;
  4326. }
  4327. if( sc && sc->data[SC_DEATHBOUND] && !is_boss(src) )
  4328. {
  4329. int dir = map_calc_dir(bl,src->x,src->y),
  4330. t_dir = unit_getdir(bl), rd1 = 0;
  4331.  
  4332. if( distance_bl(src,bl) <= 0 || !map_check_dir(dir,t_dir) )
  4333. {
  4334. rd1 = min((*damage),max_damage) * sc->data[SC_DEATHBOUND]->val2 / 100; // Amplify damage.
  4335. (*damage) = rd1 * 30 / 100; // Player receives 30% of the amplified damage.
  4336. clif_skill_damage(src,bl,gettick(), status_get_amotion(src), 0, -30000, 1, RK_DEATHBOUND, sc->data[SC_DEATHBOUND]->val1,6);
  4337. status_change_end(bl,SC_DEATHBOUND,-1);
  4338. rdamage += rd1 * 70 / 100; // Target receives 70% of the amplified damage. [Rytech]
  4339. }
  4340. }
  4341. if( sc && sc->data[SC_REFLECTSHIELD] )
  4342. {
  4343. rdamage += (*damage) * sc->data[SC_REFLECTSHIELD]->val2 / 100;
  4344. if (rdamage < 1) rdamage = 1;
  4345. }//Now only reflects short range damage only. Does not reflect magic anymore.
  4346. if( sc && sc->data[SC_REFLECTDAMAGE] && rand()%100 < 30 + 10 * sc->data[SC_REFLECTDAMAGE]->val1)
  4347. {
  4348. if( battle_config.renewal_baselvl_skill_effect == 1 && status_get_lv(src) >= 100 )
  4349. max_damage = max_damage * status_get_lv(bl) / 100;
  4350. else
  4351. max_damage = max_damage * 150 / 100;
  4352. rdamage = (*damage) * sc->data[SC_REFLECTDAMAGE]->val2 / 100;
  4353. if( rdamage > max_damage ) rdamage = max_damage;
  4354. if ((--sc->data[SC_REFLECTDAMAGE]->val3) <= 0)
  4355. status_change_end(bl,SC_REFLECTDAMAGE,-1);
  4356. }
  4357. if( sc && sc->data[SC_SHIELDSPELL_DEF] && sc->data[SC_SHIELDSPELL_DEF]->val1 == 2 )
  4358. {
  4359. rdamage += (*damage) * sc->data[SC_SHIELDSPELL_DEF]->val2 / 100;
  4360. rdamage = cap_value(rdamage,1,max_damage);
  4361. }
  4362. if( ssc && ssc->data[SC_INSPIRATION] )
  4363. {
  4364. rdamage += (*damage) / 100;
  4365. rdamage = cap_value(rdamage,1,max_damage);
  4366. }
  4367. // if( sc && sc->data[SC_CRESCENTELBOW] && !(flag&BF_SKILL) && !is_boss(src) && rand()%100 < sc->data[SC_CRESCENTELBOW]->val2 )
  4368. if( sc && sc->data[SC_CRESCENTELBOW] && !is_boss(bl) && rand()%100 < sc->data[SC_CRESCENTELBOW]->val2 )
  4369. { // Stimated formula from test
  4370. // Edited MyRO to halve reflect damage, Jan 2013
  4371. // rdamage += (int)((*damage) + (*damage) * status_get_hp(src) * 2.15 / 100000); // edit damage here
  4372. rdamage += (int)((*damage) + (*damage) * status_get_hp(src) * 2.15 / 100000)/2; // edit damage here (damage cut in half)
  4373. if( rdamage < 1 ) rdamage = 1;
  4374. }
  4375. }
  4376. else
  4377. {
  4378. if( sd && sd->long_weapon_damage_return )
  4379. {
  4380. rdamage += (*damage) * sd->long_weapon_damage_return / 100;
  4381. if( rdamage < 1 ) rdamage = 1;
  4382. }
  4383. }
  4384. return rdamage;
  4385. }
  4386.  
  4387. void battle_drain(TBL_PC *sd, struct block_list *tbl, int rdamage, int ldamage, int race, int boss)
  4388. {
  4389. struct weapon_data *wd;
  4390. int type, thp = 0, tsp = 0, rhp = 0, rsp = 0, hp, sp, i, *damage;
  4391. for (i = 0; i < 4; i++) {
  4392. //First two iterations: Right hand
  4393. if (i < 2) { wd = &sd->right_weapon; damage = &rdamage; }
  4394. else { wd = &sd->left_weapon; damage = &ldamage; }
  4395. if (*damage <= 0) continue;
  4396. //First and Third iterations: race, other two boss/nonboss state
  4397. if (i == 0 || i == 2)
  4398. type = race;
  4399. else
  4400. type = boss?RC_BOSS:RC_NONBOSS;
  4401.  
  4402. hp = wd->hp_drain[type].value;
  4403. if (wd->hp_drain[type].rate)
  4404. hp += battle_calc_drain(*damage, wd->hp_drain[type].rate, wd->hp_drain[type].per);
  4405.  
  4406. sp = wd->sp_drain[type].value;
  4407. if (wd->sp_drain[type].rate)
  4408. sp += battle_calc_drain(*damage, wd->sp_drain[type].rate, wd->sp_drain[type].per);
  4409.  
  4410. if (hp) {
  4411. if (wd->hp_drain[type].type)
  4412. rhp += hp;
  4413. thp += hp;
  4414. }
  4415. if (sp) {
  4416. if (wd->sp_drain[type].type)
  4417. rsp += sp;
  4418. tsp += sp;
  4419. }
  4420. }
  4421.  
  4422. if (sd->sp_vanish_rate && rand()%1000 < sd->sp_vanish_rate)
  4423. status_percent_damage(&sd->bl, tbl, 0, (unsigned char)sd->sp_vanish_per, false);
  4424. if (!thp && !tsp) return;
  4425.  
  4426. status_heal(&sd->bl, thp, tsp, battle_config.show_hp_sp_drain?3:1);
  4427.  
  4428. if (rhp || rsp)
  4429. status_zap(tbl, rhp, rsp);
  4430. }
  4431.  
  4432. // Deals the same damage to targets in area. [pakpil]
  4433. int battle_damage_area( struct block_list *bl, va_list ap)
  4434. {
  4435. unsigned int tick;
  4436. int amotion, dmotion, damage;
  4437. struct block_list *src;
  4438.  
  4439. nullpo_ret(bl);
  4440.  
  4441. tick=va_arg(ap, unsigned int);
  4442. src=va_arg(ap,struct block_list *);
  4443. amotion=va_arg(ap,int);
  4444. dmotion=va_arg(ap,int);
  4445. damage=va_arg(ap,int);
  4446.  
  4447. if( bl != src && battle_check_target(src,bl,BCT_ENEMY) > 0 && !(bl->type == BL_MOB && ((TBL_MOB*)bl)->class_ == MOBID_EMPERIUM) )
  4448. {
  4449. map_freeblock_lock();
  4450. if( amotion )
  4451. battle_delay_damage(tick, amotion,src,bl,0,0,0,damage,ATK_DEF,0);
  4452. else
  4453. status_fix_damage(src,bl,damage,0);
  4454. clif_damage(bl,bl,tick,amotion,dmotion,damage,1,ATK_BLOCK,0);
  4455. skill_additional_effect(src, bl, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick);
  4456. map_freeblock_unlock();
  4457. }
  4458.  
  4459. return 0;
  4460. }
  4461.  
  4462. /*==========================================
  4463. * ’ê??U????—??ü????
  4464. *------------------------------------------*/
  4465. enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* target, unsigned int tick, int flag)
  4466. {
  4467. struct map_session_data *sd = NULL, *tsd = NULL;
  4468. struct status_data *sstatus, *tstatus;
  4469. struct status_change *sc, *tsc;
  4470. int damage,rdamage=0,rdelay=0;
  4471. int skillv;
  4472. struct Damage wd;
  4473.  
  4474. nullpo_retr(ATK_NONE, src);
  4475. nullpo_retr(ATK_NONE, target);
  4476.  
  4477. if (src->prev == NULL || target->prev == NULL)
  4478. return ATK_NONE;
  4479.  
  4480. sd = BL_CAST(BL_PC, src);
  4481. tsd = BL_CAST(BL_PC, target);
  4482.  
  4483. sstatus = status_get_status_data(src);
  4484. tstatus = status_get_status_data(target);
  4485.  
  4486. sc = status_get_sc(src);
  4487. tsc = status_get_sc(target);
  4488.  
  4489. if (sc && !sc->count) //Avoid sc checks when there's none to check for. [Skotlex]
  4490. sc = NULL;
  4491. if (tsc && !tsc->count)
  4492. tsc = NULL;
  4493.  
  4494. if (sd)
  4495. {
  4496. sd->state.arrow_atk = (sd->status.weapon == W_BOW || (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE));
  4497. if (sd->state.arrow_atk)
  4498. {
  4499. int index = sd->equip_index[EQI_AMMO];
  4500. if (index<0) {
  4501. clif_arrow_fail(sd,0);
  4502. return ATK_NONE;
  4503. }
  4504. //Ammo check by Ishizu-chan
  4505. if (sd->inventory_data[index])
  4506. switch (sd->status.weapon) {
  4507. case W_BOW:
  4508. if (sd->inventory_data[index]->look != A_ARROW) {
  4509. clif_arrow_fail(sd,0);
  4510. return ATK_NONE;
  4511. }
  4512. break;
  4513. case W_REVOLVER:
  4514. case W_RIFLE:
  4515. case W_GATLING:
  4516. case W_SHOTGUN:
  4517. if (sd->inventory_data[index]->look != A_BULLET) {
  4518. clif_arrow_fail(sd,0);
  4519. return ATK_NONE;
  4520. }
  4521. break;
  4522. case W_GRENADE:
  4523. if (sd->inventory_data[index]->look != A_GRENADE) {
  4524. clif_arrow_fail(sd,0);
  4525. return ATK_NONE;
  4526. }
  4527. break;
  4528. }
  4529. }
  4530. }
  4531.  
  4532. if (sc && sc->data[SC_CLOAKING] && !(sc->data[SC_CLOAKING]->val4&2))
  4533. status_change_end(src, SC_CLOAKING, INVALID_TIMER);
  4534.  
  4535. if (sc && sc->data[SC_CLOAKINGEXCEED] && !(sc->data[SC_CLOAKINGEXCEED]->val4&2))
  4536. status_change_end(src,SC_CLOAKINGEXCEED,-1);
  4537.  
  4538. if (sc && sc->data[SC_CAMOUFLAGE] && !(sc->data[SC_CAMOUFLAGE]->val3&2))
  4539. status_change_end(src,SC_CAMOUFLAGE,-1);
  4540.  
  4541. if( tsc && tsc->data[SC_AUTOCOUNTER] && status_check_skilluse(target, src, KN_AUTOCOUNTER, tsc->data[SC_AUTOCOUNTER]->val1, 1) )
  4542. {
  4543. int dir = map_calc_dir(target,src->x,src->y);
  4544. int t_dir = unit_getdir(target);
  4545. int dist = distance_bl(src, target);
  4546. if(dist <= 0 || (!map_check_dir(dir,t_dir) && dist <= tstatus->rhw.range+1))
  4547. {
  4548. int skilllv = tsc->data[SC_AUTOCOUNTER]->val1;
  4549. clif_skillcastcancel(target); //Remove the casting bar. [Skotlex]
  4550. clif_damage(src, target, tick, sstatus->amotion, 1, 0, 1, 0, 0); //Display MISS.
  4551. status_change_end(target, SC_AUTOCOUNTER, INVALID_TIMER);
  4552. skill_attack(BF_WEAPON,target,target,src,KN_AUTOCOUNTER,skilllv,tick,0);
  4553. return ATK_NONE;
  4554. }
  4555. }
  4556.  
  4557. if( tsc && tsc->data[SC_BLADESTOP_WAIT] && !is_boss(src) && (src->type == BL_PC || tsd == NULL || distance_bl(src, target) <= (tsd->status.weapon == W_FIST ? 1 : 2)) )
  4558. {
  4559. int skilllv = tsc->data[SC_BLADESTOP_WAIT]->val1;
  4560. int duration = skill_get_time2(MO_BLADESTOP,skilllv);
  4561. status_change_end(target, SC_BLADESTOP_WAIT, INVALID_TIMER);
  4562. if(sc_start4(src, SC_BLADESTOP, 100, sd?pc_checkskill(sd, MO_BLADESTOP):5, 0, 0, target->id, duration))
  4563. { //Target locked.
  4564. clif_damage(src, target, tick, sstatus->amotion, 1, 0, 1, 0, 0); //Display MISS.
  4565. clif_bladestop(target, src->id, 1);
  4566. sc_start4(target, SC_BLADESTOP, 100, skilllv, 0, 0, src->id, duration);
  4567. return ATK_NONE;
  4568. }
  4569. }
  4570.  
  4571. if(sd && (skillv = pc_checkskill(sd,MO_TRIPLEATTACK)) > 0)
  4572. {
  4573. int triple_rate= 30 - skillv; //Base Rate
  4574. if (sc && sc->data[SC_SKILLRATE_UP] && sc->data[SC_SKILLRATE_UP]->val1 == MO_TRIPLEATTACK)
  4575. {
  4576. triple_rate+= triple_rate*(sc->data[SC_SKILLRATE_UP]->val2)/100;
  4577. status_change_end(src, SC_SKILLRATE_UP, INVALID_TIMER);
  4578. }
  4579. if (rand()%100 < triple_rate)
  4580. //FIXME: invalid return type!
  4581. return (damage_lv)skill_attack(BF_WEAPON,src,src,target,MO_TRIPLEATTACK,skillv,tick,0);
  4582. }
  4583.  
  4584. if (sc)
  4585. {
  4586. if (sc->data[SC_SACRIFICE])
  4587. {
  4588. int skilllv = sc->data[SC_SACRIFICE]->val1;
  4589.  
  4590. if( --sc->data[SC_SACRIFICE]->val2 <= 0 )
  4591. status_change_end(src, SC_SACRIFICE, INVALID_TIMER);
  4592.  
  4593. status_zap(src, sstatus->max_hp*9/100, 0);//Damage to self is always 9%
  4594.  
  4595. //FIXME: invalid return type!
  4596. return (damage_lv)skill_attack(BF_WEAPON,src,src,target,PA_SACRIFICE,skilllv,tick,0);
  4597. }
  4598. if (sc->data[SC_MAGICALATTACK])
  4599. //FIXME: invalid return type!
  4600. return (damage_lv)skill_attack(BF_MAGIC,src,src,target,NPC_MAGICALATTACK,sc->data[SC_MAGICALATTACK]->val1,tick,0);
  4601. if( sc->data[SC_GT_ENERGYGAIN] )
  4602. {
  4603. int duration = skill_get_time(MO_CALLSPIRITS, sc->data[SC_GT_ENERGYGAIN]->val1);
  4604. if( sd && rand()%100 < 10 + 5 * sc->data[SC_GT_ENERGYGAIN]->val1)
  4605. pc_addspiritball(sd, duration, sc->data[SC_GT_ENERGYGAIN]->val1);
  4606. }
  4607. }
  4608.  
  4609. if(tsc && tsc->data[SC_KAAHI] && tsc->data[SC_KAAHI]->val4 == INVALID_TIMER && tstatus->hp < tstatus->max_hp)
  4610. tsc->data[SC_KAAHI]->val4 = add_timer(tick + skill_get_time2(SL_KAAHI,tsc->data[SC_KAAHI]->val1), kaahi_heal_timer, target->id, SC_KAAHI); //Activate heal.
  4611.  
  4612. wd = battle_calc_attack(BF_WEAPON, src, target, 0, 0, flag);
  4613.  
  4614. if(sc)
  4615. {
  4616. if( sc->data[SC_EXEEDBREAK] )
  4617. {
  4618. wd.damage = wd.damage * sc->data[SC_EXEEDBREAK]->val1 / 100;
  4619. status_change_end(src,SC_EXEEDBREAK,-1);
  4620. }
  4621. if( sc->data[SC_SPELLFIST] )
  4622. {
  4623. if( --(sc->data[SC_SPELLFIST]->val1) >= 0 )
  4624. wd = battle_calc_attack(BF_MAGIC,src,target,sc->data[SC_SPELLFIST]->val3,sc->data[SC_SPELLFIST]->val4,flag);
  4625. else
  4626. status_change_end(src,SC_SPELLFIST,-1);
  4627. }
  4628. }
  4629.  
  4630. if( sd && sc && sc->data[SC_GIANTGROWTH] && (wd.flag&BF_SHORT) && rand()%100 < sc->data[SC_GIANTGROWTH]->val2 )
  4631. wd.damage *= 3; // Triple Damage
  4632.  
  4633. if (sd && sd->state.arrow_atk) //Consume arrow.
  4634. battle_consume_ammo(sd, 0, 0);
  4635.  
  4636. damage = wd.damage + wd.damage2;
  4637. if( damage > 0 && src != target )
  4638. {
  4639.  
  4640. if( sc && sc->data[SC_DUPLELIGHT] && (wd.flag&BF_SHORT) && rand()%100 <= 10+2*sc->data[SC_DUPLELIGHT]->val1 )
  4641. { // Activates it only from melee damage
  4642. int skillid;
  4643. if( rand()%2 == 1 )
  4644. skillid = AB_DUPLELIGHT_MELEE;
  4645. else
  4646. skillid = AB_DUPLELIGHT_MAGIC;
  4647. skill_attack(skill_get_type(skillid), src, src, target, skillid, sc->data[SC_DUPLELIGHT]->val1, tick, SD_LEVEL);
  4648. }
  4649.  
  4650. rdamage = battle_calc_return_damage(src, target, &damage, wd.flag);
  4651.  
  4652. if( rdamage > 0 )
  4653. {
  4654. if( tsc && tsc->data[SC_REFLECTDAMAGE] )
  4655. {
  4656. if( src != target )// Don't reflect your own damage (Grand Cross)
  4657. map_foreachinshootrange(battle_damage_area,target,skill_get_splash(LG_REFLECTDAMAGE,1),BL_CHAR,tick,target,wd.amotion,wd.dmotion,rdamage,tstatus->race,0);
  4658. }
  4659. else
  4660. {
  4661. if( tsc && tsc->data[SC_CRESCENTELBOW] )
  4662. { // Deal rdamage to src and 10% damage back to target.
  4663. clif_skill_nodamage(target,target,SR_CRESCENTELBOW_AUTOSPELL,tsc->data[SC_CRESCENTELBOW]->val1,1);
  4664. skill_blown(target,src,skill_get_blewcount(SR_CRESCENTELBOW_AUTOSPELL,tsc->data[SC_CRESCENTELBOW]->val1),unit_getdir(src),0);
  4665. status_damage(NULL,target,rdamage/10,0,0,1); //Reflect edit here
  4666. clif_damage(target, target, tick, wd.amotion, wd.dmotion, rdamage/10, wd.div_ , wd.type, wd.damage2);
  4667. status_change_end(target, SC_CRESCENTELBOW, INVALID_TIMER);
  4668. }
  4669. rdelay = clif_damage(src, src, tick, wd.amotion, sstatus->dmotion, rdamage, 1, 4, 0);
  4670. //Use Reflect Shield to signal this kind of skill trigger. [Skotlex]
  4671. skill_additional_effect(target,src,CR_REFLECTSHIELD,1,BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick);
  4672. }
  4673. }
  4674. }
  4675.  
  4676. if( tsc )
  4677. {
  4678. if( tsc->data[SC_DEVOTION] )
  4679. {
  4680. struct status_change_entry *sce = tsc->data[SC_DEVOTION];
  4681. struct block_list *d_bl = map_id2bl(sce->val1);
  4682.  
  4683. if( d_bl && (
  4684. (d_bl->type == BL_MER && ((TBL_MER*)d_bl)->master && ((TBL_MER*)d_bl)->master->bl.id == target->id) ||
  4685. (d_bl->type == BL_PC && ((TBL_PC*)d_bl)->devotion[sce->val2] == target->id)
  4686. ) && check_distance_bl(target, d_bl, sce->val3) )
  4687. {
  4688. clif_damage(d_bl, d_bl, gettick(), 0, 0, damage, 0, 0, 0);
  4689. status_fix_damage(NULL, d_bl, damage, 0);
  4690. }
  4691. else
  4692. status_change_end(target, SC_DEVOTION, INVALID_TIMER);
  4693. }
  4694.  
  4695. if( tsc->data[SC_CIRCLE_OF_FIRE_OPTION] && (wd.flag&BF_SHORT) && target->type == BL_PC )
  4696. {
  4697. struct elemental_data *ed = ((TBL_PC*)target)->ed;
  4698. if( ed )
  4699. {
  4700. clif_skill_damage(&ed->bl, target, tick, status_get_amotion(src), 0, -30000, 1, EL_CIRCLE_OF_FIRE, tsc->data[SC_CIRCLE_OF_FIRE_OPTION]->val1, 6);
  4701. skill_attack(BF_MAGIC,&ed->bl,&ed->bl,src,EL_CIRCLE_OF_FIRE,tsc->data[SC_CIRCLE_OF_FIRE_OPTION]->val1,tick,wd.flag);
  4702. }
  4703. }
  4704.  
  4705. if( tsc->data[SC_WATER_SCREEN_OPTION] && tsc->data[SC_WATER_SCREEN_OPTION]->val1 )
  4706. {
  4707. struct block_list *e_bl = map_id2bl(tsc->data[SC_WATER_SCREEN_OPTION]->val1);
  4708. if( e_bl && !status_isdead(e_bl) )
  4709. {
  4710. clif_damage(e_bl,e_bl,tick,wd.amotion,wd.dmotion,damage,wd.div_,wd.type,wd.damage2);
  4711. status_damage(target,e_bl,damage,0,0,0);
  4712. // Just show damage in target.
  4713. clif_damage(src, target, tick, wd.amotion, wd.dmotion, damage, wd.div_, wd.type, wd.damage2 );
  4714. return ATK_NONE;
  4715. }
  4716. }
  4717. }
  4718.  
  4719. wd.dmotion = clif_damage(src, target, tick, wd.amotion, wd.dmotion, wd.damage, wd.div_ , wd.type, wd.damage2);
  4720.  
  4721. if (sd && sd->splash_range > 0 && damage > 0)
  4722. skill_castend_damage_id(src, target, 0, 1, tick, 0);
  4723.  
  4724. map_freeblock_lock();
  4725.  
  4726. battle_delay_damage(tick, wd.amotion, src, target, wd.flag, 0, 0, damage, wd.dmg_lv, wd.dmotion);
  4727.  
  4728. if (sc && sc->data[SC_AUTOSPELL] && rand()%100 < sc->data[SC_AUTOSPELL]->val4) {
  4729. int sp = 0;
  4730. int skillid = sc->data[SC_AUTOSPELL]->val2;
  4731. int skilllv = sc->data[SC_AUTOSPELL]->val3;
  4732. int i = rand()%100;
  4733. if (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_SAGE)
  4734. i = 0; //Max chance, no skilllv reduction. [Skotlex]
  4735. if (i >= 50) skilllv -= 2;
  4736. else if (i >= 15) skilllv--;
  4737. if (skilllv < 1) skilllv = 1;
  4738. sp = skill_get_sp(skillid,skilllv) * 2 / 3;
  4739.  
  4740. if (sd) sd->state.autocast = 1;
  4741. if (status_charge(src, 0, sp)) {
  4742. switch (skill_get_casttype(skillid)) {
  4743. case CAST_GROUND:
  4744. skill_castend_pos2(src, target->x, target->y, skillid, skilllv, tick, flag);
  4745. break;
  4746. case CAST_NODAMAGE:
  4747. skill_castend_nodamage_id(src, target, skillid, skilllv, tick, flag);
  4748. break;
  4749. case CAST_DAMAGE:
  4750. skill_castend_damage_id(src, target, skillid, skilllv, tick, flag);
  4751. break;
  4752. }
  4753. }
  4754. if (sd) sd->state.autocast = 0;
  4755. }
  4756. if( sd && wd.flag&BF_SHORT && sc && sc->data[SC__AUTOSHADOWSPELL] && rand()%100 < sc->data[SC__AUTOSHADOWSPELL]->val3 &&
  4757. sd->status.skill[sc->data[SC__AUTOSHADOWSPELL]->val1].id != 0 && sd->status.skill[sc->data[SC__AUTOSHADOWSPELL]->val1].flag == 13 )
  4758. {
  4759. int r_skill = sd->status.skill[sc->data[SC__AUTOSHADOWSPELL]->val1].id,
  4760. r_lv = sc->data[SC__AUTOSHADOWSPELL]->val2;
  4761.  
  4762. if (r_skill != AL_HOLYLIGHT && r_skill != PR_MAGNUS)
  4763. {
  4764. skill_consume_requirement(sd,r_skill,r_lv,3);
  4765. switch( skill_get_casttype(r_skill) )
  4766. {
  4767. case CAST_GROUND:
  4768. skill_castend_pos2(src, target->x, target->y, r_skill, r_lv, tick, flag);
  4769. break;
  4770. case CAST_NODAMAGE:
  4771. skill_castend_nodamage_id(src, target, r_skill, r_lv, tick, flag);
  4772. break;
  4773. case CAST_DAMAGE:
  4774. skill_castend_damage_id(src, target, r_skill, r_lv, tick, flag);
  4775. break;
  4776. }
  4777.  
  4778. sd->ud.canact_tick = tick + skill_delayfix(src, r_skill, r_lv);
  4779. clif_status_change(src, SI_ACTIONDELAY, 1, skill_delayfix(src, r_skill, r_lv), 0, 0, 1);
  4780. }
  4781. }
  4782. if( sd && sc && (sc->data[SC_TROPIC_OPTION] || sc->data[SC_CHILLY_AIR_OPTION] || sc->data[SC_WILD_STORM_OPTION] || sc->data[SC_UPHEAVAL_OPTION]) )
  4783. { // Autocast one Bolt depending on status change.
  4784. int skillid = 0;
  4785. if( sc->data[SC_TROPIC_OPTION] ) skillid = sc->data[SC_TROPIC_OPTION]->val3;
  4786. else if( sc->data[SC_CHILLY_AIR_OPTION] ) skillid = sc->data[SC_CHILLY_AIR_OPTION]->val3;
  4787. else if( sc->data[SC_WILD_STORM_OPTION] ) skillid = sc->data[SC_WILD_STORM_OPTION]->val2;
  4788. else if( sc->data[SC_UPHEAVAL_OPTION] ) skillid = sc->data[SC_UPHEAVAL_OPTION]->val2;
  4789.  
  4790. sd->state.autocast = 1;
  4791. if( skillid && rand()%100 < 5 )
  4792. skill_castend_damage_id(src, target, skillid, pc_checkskill(sd,skillid), tick, flag);
  4793. sd->state.autocast = 0;
  4794. }
  4795.  
  4796. if (sd) {
  4797. if (wd.flag & BF_WEAPON && src != target && damage > 0) {
  4798. if (battle_config.left_cardfix_to_right)
  4799. battle_drain(sd, target, wd.damage, wd.damage, tstatus->race, is_boss(target));
  4800. else
  4801. battle_drain(sd, target, wd.damage, wd.damage2, tstatus->race, is_boss(target));
  4802. }
  4803. }
  4804. if( rdamage > 0 && !(tsc && tsc->data[SC_REFLECTDAMAGE]) ) { //By sending attack type "none" skill_additional_effect won't be invoked. [Skotlex]
  4805. if(tsd && src != target)
  4806. battle_drain(tsd, src, rdamage, rdamage, sstatus->race, is_boss(src));
  4807. battle_delay_damage(tick, wd.amotion, target, src, 0, 0, 0, rdamage, ATK_DEF, rdelay);
  4808. }
  4809.  
  4810. if (tsc) {
  4811. if (tsc->data[SC_POISONREACT] &&
  4812. (rand()%100 < tsc->data[SC_POISONREACT]->val3
  4813. || sstatus->def_ele == ELE_POISON) &&
  4814. // check_distance_bl(src, target, tstatus->rhw.range+1) && Doesn't checks range! o.O;
  4815. status_check_skilluse(target, src, TF_POISON, tsc->data[SC_POISONREACT]->val1, 0)
  4816. ) { //Poison React
  4817. struct status_change_entry *sce = tsc->data[SC_POISONREACT];
  4818. if (sstatus->def_ele == ELE_POISON) {
  4819. sce->val2 = 0;
  4820. skill_attack(BF_WEAPON,target,target,src,AS_POISONREACT,sce->val1,tick,0);
  4821. } else {
  4822. skill_attack(BF_WEAPON,target,target,src,TF_POISON, 5, tick, 0);
  4823. --sce->val2;
  4824. }
  4825. if (sce->val2 <= 0)
  4826. status_change_end(target, SC_POISONREACT, INVALID_TIMER);
  4827. }
  4828. }
  4829. map_freeblock_unlock();
  4830. return wd.dmg_lv;
  4831. }
  4832.  
  4833. int battle_check_undead(int race,int element)
  4834. {
  4835. if(battle_config.undead_detect_type == 0) {
  4836. if(element == ELE_UNDEAD)
  4837. return 1;
  4838. }
  4839. else if(battle_config.undead_detect_type == 1) {
  4840. if(race == RC_UNDEAD)
  4841. return 1;
  4842. }
  4843. else {
  4844. if(element == ELE_UNDEAD || race == RC_UNDEAD)
  4845. return 1;
  4846. }
  4847. return 0;
  4848. }
  4849.  
  4850. //Returns the upmost level master starting with the given object
  4851. struct block_list* battle_get_master(struct block_list *src)
  4852. {
  4853. struct block_list *prev; //Used for infinite loop check (master of yourself?)
  4854. do {
  4855. prev = src;
  4856. switch (src->type) {
  4857. case BL_PET:
  4858. if (((TBL_PET*)src)->msd)
  4859. src = (struct block_list*)((TBL_PET*)src)->msd;
  4860. break;
  4861. case BL_MOB:
  4862. if (((TBL_MOB*)src)->master_id)
  4863. src = map_id2bl(((TBL_MOB*)src)->master_id);
  4864. break;
  4865. case BL_HOM:
  4866. if (((TBL_HOM*)src)->master)
  4867. src = (struct block_list*)((TBL_HOM*)src)->master;
  4868. break;
  4869. case BL_MER:
  4870. if (((TBL_MER*)src)->master)
  4871. src = (struct block_list*)((TBL_MER*)src)->master;
  4872. break;
  4873. case BL_ELEM:
  4874. if (((TBL_ELEM*)src)->master)
  4875. src = (struct block_list*)((TBL_ELEM*)src)->master;
  4876. break;
  4877. case BL_SKILL:
  4878. if (((TBL_SKILL*)src)->group && ((TBL_SKILL*)src)->group->src_id)
  4879. src = map_id2bl(((TBL_SKILL*)src)->group->src_id);
  4880. break;
  4881. }
  4882. } while (src && src != prev);
  4883. return prev;
  4884. }
  4885.  
  4886. /*==========================================
  4887. * Checks the state between two targets (rewritten by Skotlex)
  4888. * (enemy, friend, party, guild, etc)
  4889. * See battle.h for possible values/combinations
  4890. * to be used here (BCT_* constants)
  4891. * Return value is:
  4892. * 1: flag holds true (is enemy, party, etc)
  4893. * -1: flag fails
  4894. * 0: Invalid target (non-targetable ever)
  4895. *------------------------------------------*/
  4896. int battle_check_target( struct block_list *src, struct block_list *target,int flag)
  4897. {
  4898. int m,state = 0; //Initial state none
  4899. int strip_enemy = 1; //Flag which marks whether to remove the BCT_ENEMY status if it's also friend/ally.
  4900. struct block_list *s_bl = src, *t_bl = target;
  4901.  
  4902. nullpo_ret(src);
  4903. nullpo_ret(target);
  4904.  
  4905. m = target->m;
  4906.  
  4907. //t_bl/s_bl hold the 'master' of the attack, while src/target are the actual
  4908. //objects involved.
  4909. if( (t_bl = battle_get_master(target)) == NULL )
  4910. t_bl = target;
  4911.  
  4912. if( (s_bl = battle_get_master(src)) == NULL )
  4913. s_bl = src;
  4914.  
  4915. switch( target->type )
  4916. { // Checks on actual target
  4917. case BL_PC:
  4918. if (((TBL_PC*)target)->invincible_timer != INVALID_TIMER || pc_isinvisible((TBL_PC*)target))
  4919. return -1; //Cannot be targeted yet.
  4920. break;
  4921. case BL_MOB:
  4922. if((((TBL_MOB*)target)->special_state.ai == 2 || //Marine Spheres
  4923. (((TBL_MOB*)target)->special_state.ai == 3 && battle_config.summon_flora&1)) && //Floras
  4924. s_bl->type == BL_PC && src->type != BL_MOB)
  4925. { //Targettable by players
  4926. state |= BCT_ENEMY;
  4927. strip_enemy = 0;
  4928. }
  4929. break;
  4930. case BL_SKILL:
  4931. {
  4932. TBL_SKILL *su = (TBL_SKILL*)target;
  4933. if( !su->group )
  4934. return 0;
  4935. if( skill_get_inf2(su->group->skill_id)&INF2_TRAP )
  4936. { //Only a few skills can target traps...
  4937. switch( battle_getcurrentskill(src) )
  4938. {
  4939. case MA_REMOVETRAP:
  4940. case HT_REMOVETRAP:
  4941. case AC_SHOWER:
  4942. case MA_SHOWER:
  4943. case WZ_SIGHTRASHER:
  4944. case WZ_SIGHTBLASTER:
  4945. case SM_MAGNUM:
  4946. case MS_MAGNUM:
  4947. case RA_DETONATOR:
  4948. case RA_SENSITIVEKEEN:
  4949. case GN_CRAZYWEED:
  4950. state |= BCT_ENEMY;
  4951. strip_enemy = 0;
  4952. break;
  4953. default:
  4954. return 0;
  4955. }
  4956. } else if (su->group->skill_id==WZ_ICEWALL || su->group->skill_id == GN_WALLOFTHORN || su->group->skill_id == WM_REVERBERATION)
  4957. {
  4958. state |= BCT_ENEMY;
  4959. strip_enemy = 0;
  4960. } else //Excepting traps and icewall, you should not be able to target skills.
  4961. return 0;
  4962. }
  4963. break;
  4964. //Valid targets with no special checks here.
  4965. case BL_MER:
  4966. case BL_HOM:
  4967. case BL_ELEM:
  4968. break;
  4969. //All else not specified is an invalid target.
  4970. default:
  4971. return 0;
  4972. }
  4973.  
  4974. switch( t_bl->type )
  4975. { //Checks on target master
  4976. case BL_PC:
  4977. {
  4978. struct map_session_data *sd;
  4979. if( t_bl == s_bl ) break;
  4980. sd = BL_CAST(BL_PC, t_bl);
  4981.  
  4982. if( sd->state.monster_ignore && flag&BCT_ENEMY )
  4983. return 0; // Global inminuty only to Attacks
  4984. if( sd->status.karma && s_bl->type == BL_PC && ((TBL_PC*)s_bl)->status.karma )
  4985. state |= BCT_ENEMY; // Characters with bad karma may fight amongst them
  4986. if( sd->state.killable ) {
  4987. state |= BCT_ENEMY; // Everything can kill it
  4988. strip_enemy = 0;
  4989. }
  4990. break;
  4991. }
  4992. case BL_MOB:
  4993. {
  4994. struct mob_data *md = BL_CAST(BL_MOB, t_bl);
  4995.  
  4996. if( !((agit_flag || agit2_flag) && map[m].flag.gvg_castle) && md->guardian_data && md->guardian_data->guild_id )
  4997. return 0; // Disable guardians/emperiums owned by Guilds on non-woe times.
  4998. break;
  4999. }
  5000. }
  5001.  
  5002. switch( src->type )
  5003. { //Checks on actual src type
  5004. case BL_PET:
  5005. if (t_bl->type != BL_MOB && flag&BCT_ENEMY)
  5006. return 0; //Pet may not attack non-mobs.
  5007. if (t_bl->type == BL_MOB && ((TBL_MOB*)t_bl)->guardian_data && flag&BCT_ENEMY)
  5008. return 0; //pet may not attack Guardians/Emperium
  5009. break;
  5010. case BL_SKILL:
  5011. {
  5012. struct skill_unit *su = (struct skill_unit *)src;
  5013. if (!su->group)
  5014. return 0;
  5015.  
  5016. if (su->group->src_id == target->id)
  5017. {
  5018. int inf2;
  5019. inf2 = skill_get_inf2(su->group->skill_id);
  5020. if (inf2&INF2_NO_TARGET_SELF)
  5021. return -1;
  5022. if (inf2&INF2_TARGET_SELF)
  5023. return 1;
  5024. }
  5025. break;
  5026. }
  5027. }
  5028.  
  5029. switch( s_bl->type )
  5030. { //Checks on source master
  5031. case BL_PC:
  5032. {
  5033. struct map_session_data *sd = BL_CAST(BL_PC, s_bl);
  5034. if( s_bl != t_bl )
  5035. {
  5036. if( sd->state.killer )
  5037. {
  5038. state |= BCT_ENEMY; // Can kill anything
  5039. strip_enemy = 0;
  5040. }
  5041. else if( sd->duel_group && !((!battle_config.duel_allow_pvp && map[m].flag.pvp) || (!battle_config.duel_allow_gvg && map_flag_gvg(m))) )
  5042. {
  5043. if( t_bl->type == BL_PC && (sd->duel_group == ((TBL_PC*)t_bl)->duel_group) )
  5044. return (BCT_ENEMY&flag)?1:-1; // Duel targets can ONLY be your enemy, nothing else.
  5045. else
  5046. return 0; // You can't target anything out of your duel
  5047. }
  5048. }
  5049. if( map_flag_gvg(m) && !sd->status.guild_id && t_bl->type == BL_MOB && ((TBL_MOB*)t_bl)->guardian_data )
  5050. return 0; //If you don't belong to a guild, can't target guardians/emperium.
  5051. if( t_bl->type != BL_PC )
  5052. state |= BCT_ENEMY; //Natural enemy.
  5053. break;
  5054. }
  5055. case BL_MOB:
  5056. {
  5057. struct mob_data *md = BL_CAST(BL_MOB, s_bl);
  5058. if( !((agit_flag || agit2_flag) && map[m].flag.gvg_castle) && md->guardian_data && md->guardian_data->guild_id )
  5059. return 0; // Disable guardians/emperium owned by Guilds on non-woe times.
  5060.  
  5061. if( !md->special_state.ai )
  5062. { //Normal mobs.
  5063. if( t_bl->type == BL_MOB && !((TBL_MOB*)t_bl)->special_state.ai )
  5064. state |= BCT_PARTY; //Normal mobs with no ai are friends.
  5065. else
  5066. state |= BCT_ENEMY; //However, all else are enemies.
  5067. }
  5068. else
  5069. {
  5070. if( t_bl->type == BL_MOB && !((TBL_MOB*)t_bl)->special_state.ai )
  5071. state |= BCT_ENEMY; //Natural enemy for AI mobs are normal mobs.
  5072. }
  5073. break;
  5074. }
  5075. default:
  5076. //Need some sort of default behaviour for unhandled types.
  5077. if (t_bl->type != s_bl->type)
  5078. state |= BCT_ENEMY;
  5079. break;
  5080. }
  5081.  
  5082. if( (flag&BCT_ALL) == BCT_ALL )
  5083. { //All actually stands for all attackable chars
  5084. if( target->type&BL_CHAR )
  5085. return 1;
  5086. else
  5087. return -1;
  5088. }
  5089. if( flag == BCT_NOONE ) //Why would someone use this? no clue.
  5090. return -1;
  5091.  
  5092. if( t_bl == s_bl )
  5093. { //No need for further testing.
  5094. state |= BCT_SELF|BCT_PARTY|BCT_GUILD;
  5095. if( state&BCT_ENEMY && strip_enemy )
  5096. state&=~BCT_ENEMY;
  5097. return (flag&state)?1:-1;
  5098. }
  5099.  
  5100. if( map_flag_vs(m) )
  5101. { //Check rivalry settings.
  5102. int sbg_id = 0, tbg_id = 0;
  5103. if( map[m].flag.battleground )
  5104. {
  5105. sbg_id = bg_team_get_id(s_bl);
  5106. tbg_id = bg_team_get_id(t_bl);
  5107. }
  5108. if( flag&(BCT_PARTY|BCT_ENEMY) )
  5109. {
  5110. int s_party = status_get_party_id(s_bl);
  5111. if( s_party && s_party == status_get_party_id(t_bl) && !(map[m].flag.pvp && map[m].flag.pvp_noparty) && !(map_flag_gvg(m) && map[m].flag.gvg_noparty) && (!map[m].flag.battleground || sbg_id == tbg_id) )
  5112. state |= BCT_PARTY;
  5113. else
  5114. state |= BCT_ENEMY;
  5115. }
  5116. if( flag&(BCT_GUILD|BCT_ENEMY) )
  5117. {
  5118. int s_guild = status_get_guild_id(s_bl);
  5119. int t_guild = status_get_guild_id(t_bl);
  5120. if( !(map[m].flag.pvp && map[m].flag.pvp_noguild) && s_guild && t_guild && (s_guild == t_guild || guild_isallied(s_guild, t_guild)) && (!map[m].flag.battleground || sbg_id == tbg_id) )
  5121. state |= BCT_GUILD;
  5122. else
  5123. state |= BCT_ENEMY;
  5124. }
  5125. if( state&BCT_ENEMY && map[m].flag.battleground && sbg_id && sbg_id == tbg_id )
  5126. state &= ~BCT_ENEMY;
  5127.  
  5128. if( state&BCT_ENEMY && battle_config.pk_mode && !map_flag_gvg(m) && s_bl->type == BL_PC && t_bl->type == BL_PC )
  5129. { // Prevent novice engagement on pk_mode (feature by Valaris)
  5130. TBL_PC *sd = (TBL_PC*)s_bl, *sd2 = (TBL_PC*)t_bl;
  5131. if (
  5132. (sd->class_&MAPID_UPPERMASK) == MAPID_NOVICE ||
  5133. (sd2->class_&MAPID_UPPERMASK) == MAPID_NOVICE ||
  5134. (int)sd->status.base_level < battle_config.pk_min_level ||
  5135. (int)sd2->status.base_level < battle_config.pk_min_level ||
  5136. (battle_config.pk_level_range && abs((int)sd->status.base_level - (int)sd2->status.base_level) > battle_config.pk_level_range)
  5137. )
  5138. state &= ~BCT_ENEMY;
  5139. }
  5140. }
  5141. else
  5142. { //Non pvp/gvg, check party/guild settings.
  5143. if( flag&BCT_PARTY || state&BCT_ENEMY )
  5144. {
  5145. int s_party = status_get_party_id(s_bl);
  5146. if(s_party && s_party == status_get_party_id(t_bl))
  5147. state |= BCT_PARTY;
  5148. }
  5149. if( flag&BCT_GUILD || state&BCT_ENEMY )
  5150. {
  5151. int s_guild = status_get_guild_id(s_bl);
  5152. int t_guild = status_get_guild_id(t_bl);
  5153. if(s_guild && t_guild && (s_guild == t_guild || guild_isallied(s_guild, t_guild)))
  5154. state |= BCT_GUILD;
  5155. }
  5156. }
  5157.  
  5158. if( !state ) //If not an enemy, nor a guild, nor party, nor yourself, it's neutral.
  5159. state = BCT_NEUTRAL;
  5160. //Alliance state takes precedence over enemy one.
  5161. else if( state&BCT_ENEMY && strip_enemy && state&(BCT_SELF|BCT_PARTY|BCT_GUILD) )
  5162. state&=~BCT_ENEMY;
  5163.  
  5164. return (flag&state)?1:-1;
  5165. }
  5166. /*==========================================
  5167. * ??’?”?’è
  5168. *------------------------------------------*/
  5169. bool battle_check_range(struct block_list *src, struct block_list *bl, int range)
  5170. {
  5171. int d;
  5172. nullpo_retr(false, src);
  5173. nullpo_retr(false, bl);
  5174.  
  5175. if( src->m != bl->m )
  5176. return false;
  5177.  
  5178. #ifndef CIRCULAR_AREA
  5179. if( src->type == BL_PC )
  5180. { // Range for players' attacks and skills should always have a circular check. [Inkfish]
  5181. int dx = src->x - bl->x, dy = src->y - bl->y;
  5182. if( !check_distance(dx*dx + dy*dy, 0, range*range+(dx&&dy?1:0)) )
  5183. return false;
  5184. }
  5185. else
  5186. #endif
  5187. if( !check_distance_bl(src, bl, range) )
  5188. return false;
  5189.  
  5190. if( (d = distance_bl(src, bl)) < 2 )
  5191. return true; // No need for path checking.
  5192.  
  5193. if( d > AREA_SIZE )
  5194. return false; // Avoid targetting objects beyond your range of sight.
  5195.  
  5196. return path_search_long(NULL,src->m,src->x,src->y,bl->x,bl->y,CELL_CHKWALL);
  5197. }
  5198.  
  5199. static const struct _battle_data {
  5200. const char* str;
  5201. int* val;
  5202. int defval;
  5203. int min;
  5204. int max;
  5205. } battle_data[] = {
  5206. { "warp_point_debug", &battle_config.warp_point_debug, 0, 0, 1, },
  5207. { "enable_critical", &battle_config.enable_critical, BL_PC, BL_NUL, BL_ALL, },
  5208. { "mob_critical_rate", &battle_config.mob_critical_rate, 100, 0, INT_MAX, },
  5209. { "critical_rate", &battle_config.critical_rate, 100, 0, INT_MAX, },
  5210. { "enable_baseatk", &battle_config.enable_baseatk, BL_PC|BL_HOM, BL_NUL, BL_ALL, },
  5211. { "enable_perfect_flee", &battle_config.enable_perfect_flee, BL_PC|BL_PET, BL_NUL, BL_ALL, },
  5212. { "casting_rate", &battle_config.cast_rate, 100, 0, INT_MAX, },
  5213. { "delay_rate", &battle_config.delay_rate, 100, 0, INT_MAX, },
  5214. { "delay_dependon_dex", &battle_config.delay_dependon_dex, 0, 0, 1, },
  5215. { "delay_dependon_agi", &battle_config.delay_dependon_agi, 0, 0, 1, },
  5216. { "skill_delay_attack_enable", &battle_config.sdelay_attack_enable, 0, 0, 1, },
  5217. { "left_cardfix_to_right", &battle_config.left_cardfix_to_right, 0, 0, 1, },
  5218. { "skill_add_range", &battle_config.skill_add_range, 0, 0, INT_MAX, },
  5219. { "skill_out_range_consume", &battle_config.skill_out_range_consume, 1, 0, 1, },
  5220. { "skillrange_by_distance", &battle_config.skillrange_by_distance, ~BL_PC, BL_NUL, BL_ALL, },
  5221. { "skillrange_from_weapon", &battle_config.use_weapon_skill_range, ~BL_PC, BL_NUL, BL_ALL, },
  5222. { "player_damage_delay_rate", &battle_config.pc_damage_delay_rate, 100, 0, INT_MAX, },
  5223. { "defunit_not_enemy", &battle_config.defnotenemy, 0, 0, 1, },
  5224. { "gvg_traps_target_all", &battle_config.vs_traps_bctall, BL_PC, BL_NUL, BL_ALL, },
  5225. { "traps_setting", &battle_config.traps_setting, 0, 0, 1, },
  5226. { "summon_flora_setting", &battle_config.summon_flora, 1|2, 0, 1|2, },
  5227. { "clear_skills_on_death", &battle_config.clear_unit_ondeath, BL_NUL, BL_NUL, BL_ALL, },
  5228. { "clear_skills_on_warp", &battle_config.clear_unit_onwarp, BL_ALL, BL_NUL, BL_ALL, },
  5229. { "random_monster_checklv", &battle_config.random_monster_checklv, 0, 0, 1, },
  5230. { "attribute_recover", &battle_config.attr_recover, 1, 0, 1, },
  5231. { "flooritem_lifetime", &battle_config.flooritem_lifetime, 60000, 1000, INT_MAX, },
  5232. { "item_auto_get", &battle_config.item_auto_get, 0, 0, 1, },
  5233. { "item_first_get_time", &battle_config.item_first_get_time, 3000, 0, INT_MAX, },
  5234. { "item_second_get_time", &battle_config.item_second_get_time, 1000, 0, INT_MAX, },
  5235. { "item_third_get_time", &battle_config.item_third_get_time, 1000, 0, INT_MAX, },
  5236. { "mvp_item_first_get_time", &battle_config.mvp_item_first_get_time, 10000, 0, INT_MAX, },
  5237. { "mvp_item_second_get_time", &battle_config.mvp_item_second_get_time, 10000, 0, INT_MAX, },
  5238. { "mvp_item_third_get_time", &battle_config.mvp_item_third_get_time, 2000, 0, INT_MAX, },
  5239. { "drop_rate0item", &battle_config.drop_rate0item, 0, 0, 1, },
  5240. { "base_exp_rate", &battle_config.base_exp_rate, 100, 0, INT_MAX, },
  5241. { "job_exp_rate", &battle_config.job_exp_rate, 100, 0, INT_MAX, },
  5242. { "pvp_exp", &battle_config.pvp_exp, 1, 0, 1, },
  5243. { "death_penalty_type", &battle_config.death_penalty_type, 0, 0, 2, },
  5244. { "death_penalty_base", &battle_config.death_penalty_base, 0, 0, INT_MAX, },
  5245. { "death_penalty_job", &battle_config.death_penalty_job, 0, 0, INT_MAX, },
  5246. { "zeny_penalty", &battle_config.zeny_penalty, 0, 0, INT_MAX, },
  5247. { "hp_rate", &battle_config.hp_rate, 100, 1, INT_MAX, },
  5248. { "sp_rate", &battle_config.sp_rate, 100, 1, INT_MAX, },
  5249. { "restart_hp_rate", &battle_config.restart_hp_rate, 0, 0, 100, },
  5250. { "restart_sp_rate", &battle_config.restart_sp_rate, 0, 0, 100, },
  5251. { "guild_aura", &battle_config.guild_aura, 31, 0, 31, },
  5252. { "mvp_hp_rate", &battle_config.mvp_hp_rate, 100, 1, INT_MAX, },
  5253. { "mvp_exp_rate", &battle_config.mvp_exp_rate, 100, 0, INT_MAX, },
  5254. { "monster_hp_rate", &battle_config.monster_hp_rate, 100, 1, INT_MAX, },
  5255. { "monster_max_aspd", &battle_config.monster_max_aspd, 199, 100, 199, },
  5256. { "view_range_rate", &battle_config.view_range_rate, 100, 0, INT_MAX, },
  5257. { "chase_range_rate", &battle_config.chase_range_rate, 100, 0, INT_MAX, },
  5258. { "gtb_sc_immunity", &battle_config.gtb_sc_immunity, 50, 0, INT_MAX, },
  5259. { "guild_max_castles", &battle_config.guild_max_castles, 0, 0, INT_MAX, },
  5260. { "guild_skill_relog_delay", &battle_config.guild_skill_relog_delay, 0, 0, 1, },
  5261. { "emergency_call", &battle_config.emergency_call, 11, 0, 31, },
  5262. { "lowest_gm_level", &battle_config.lowest_gm_level, 1, 0, 99, },
  5263. { "atcommand_gm_only", &battle_config.atc_gmonly, 0, 0, 1, },
  5264. { "atcommand_spawn_quantity_limit", &battle_config.atc_spawn_quantity_limit, 100, 0, INT_MAX, },
  5265. { "atcommand_slave_clone_limit", &battle_config.atc_slave_clone_limit, 25, 0, INT_MAX, },
  5266. { "partial_name_scan", &battle_config.partial_name_scan, 0, 0, 1, },
  5267. { "gm_all_skill", &battle_config.gm_allskill, 0, 0, 100, },
  5268. { "gm_all_equipment", &battle_config.gm_allequip, 0, 0, 100, },
  5269. { "gm_bypass", &battle_config.gm_bypass, 100, 0, 100, },
  5270. { "gm_skill_unconditional", &battle_config.gm_skilluncond, 0, 0, 100, },
  5271. { "gm_join_chat", &battle_config.gm_join_chat, 0, 0, 100, },
  5272. { "gm_kick_chat", &battle_config.gm_kick_chat, 0, 0, 100, },
  5273. { "gm_can_party", &battle_config.gm_can_party, 0, 0, 1, },
  5274. { "gm_cant_party_min_lv", &battle_config.gm_cant_party_min_lv, 20, 0, 100, },
  5275. { "player_skillfree", &battle_config.skillfree, 0, 0, 1, },
  5276. { "player_skillup_limit", &battle_config.skillup_limit, 1, 0, 1, },
  5277. { "weapon_produce_rate", &battle_config.wp_rate, 100, 0, INT_MAX, },
  5278. { "potion_produce_rate", &battle_config.pp_rate, 100, 0, INT_MAX, },
  5279. { "rune_produce_rate", &battle_config.rune_produce_rate, 100, 0, INT_MAX, },
  5280. { "monster_active_enable", &battle_config.monster_active_enable, 1, 0, 1, },
  5281. { "monster_damage_delay_rate", &battle_config.monster_damage_delay_rate, 100, 0, INT_MAX, },
  5282. { "monster_loot_type", &battle_config.monster_loot_type, 0, 0, 1, },
  5283. // { "mob_skill_use", &battle_config.mob_skill_use, 1, 0, 1, }, //Deprecated
  5284. { "mob_skill_rate", &battle_config.mob_skill_rate, 100, 0, INT_MAX, },
  5285. { "mob_skill_delay", &battle_config.mob_skill_delay, 100, 0, INT_MAX, },
  5286. { "mob_count_rate", &battle_config.mob_count_rate, 100, 0, INT_MAX, },
  5287. { "mob_spawn_delay", &battle_config.mob_spawn_delay, 100, 0, INT_MAX, },
  5288. { "plant_spawn_delay", &battle_config.plant_spawn_delay, 100, 0, INT_MAX, },
  5289. { "boss_spawn_delay", &battle_config.boss_spawn_delay, 100, 0, INT_MAX, },
  5290. { "no_spawn_on_player", &battle_config.no_spawn_on_player, 0, 0, 100, },
  5291. { "force_random_spawn", &battle_config.force_random_spawn, 0, 0, 1, },
  5292. { "slaves_inherit_mode", &battle_config.slaves_inherit_mode, 2, 0, 3, },
  5293. { "slaves_inherit_speed", &battle_config.slaves_inherit_speed, 3, 0, 3, },
  5294. { "summons_trigger_autospells", &battle_config.summons_trigger_autospells, 1, 0, 1, },
  5295. { "pc_damage_walk_delay_rate", &battle_config.pc_walk_delay_rate, 20, 0, INT_MAX, },
  5296. { "damage_walk_delay_rate", &battle_config.walk_delay_rate, 100, 0, INT_MAX, },
  5297. { "multihit_delay", &battle_config.multihit_delay, 80, 0, INT_MAX, },
  5298. { "quest_skill_learn", &battle_config.quest_skill_learn, 0, 0, 1, },
  5299. { "quest_skill_reset", &battle_config.quest_skill_reset, 0, 0, 1, },
  5300. { "basic_skill_check", &battle_config.basic_skill_check, 1, 0, 1, },
  5301. { "guild_emperium_check", &battle_config.guild_emperium_check, 1, 0, 1, },
  5302. { "guild_exp_limit", &battle_config.guild_exp_limit, 50, 0, 99, },
  5303. { "player_invincible_time", &battle_config.pc_invincible_time, 5000, 0, INT_MAX, },
  5304. { "pet_catch_rate", &battle_config.pet_catch_rate, 100, 0, INT_MAX, },
  5305. { "pet_rename", &battle_config.pet_rename, 0, 0, 1, },
  5306. { "pet_friendly_rate", &battle_config.pet_friendly_rate, 100, 0, INT_MAX, },
  5307. { "pet_hungry_delay_rate", &battle_config.pet_hungry_delay_rate, 100, 10, INT_MAX, },
  5308. { "pet_hungry_friendly_decrease", &battle_config.pet_hungry_friendly_decrease, 5, 0, INT_MAX, },
  5309. { "pet_status_support", &battle_config.pet_status_support, 0, 0, 1, },
  5310. { "pet_attack_support", &battle_config.pet_attack_support, 0, 0, 1, },
  5311. { "pet_damage_support", &battle_config.pet_damage_support, 0, 0, 1, },
  5312. { "pet_support_min_friendly", &battle_config.pet_support_min_friendly, 900, 0, 950, },
  5313. { "pet_equip_min_friendly", &battle_config.pet_equip_min_friendly, 900, 0, 950, },
  5314. { "pet_support_rate", &battle_config.pet_support_rate, 100, 0, INT_MAX, },
  5315. { "pet_attack_exp_to_master", &battle_config.pet_attack_exp_to_master, 0, 0, 1, },
  5316. { "pet_attack_exp_rate", &battle_config.pet_attack_exp_rate, 100, 0, INT_MAX, },
  5317. { "pet_lv_rate", &battle_config.pet_lv_rate, 0, 0, INT_MAX, },
  5318. { "pet_max_stats", &battle_config.pet_max_stats, 99, 0, INT_MAX, },
  5319. { "pet_max_atk1", &battle_config.pet_max_atk1, 750, 0, INT_MAX, },
  5320. { "pet_max_atk2", &battle_config.pet_max_atk2, 1000, 0, INT_MAX, },
  5321. { "pet_disable_in_gvg", &battle_config.pet_no_gvg, 0, 0, 1, },
  5322. { "skill_min_damage", &battle_config.skill_min_damage, 2|4, 0, 1|2|4, },
  5323. { "finger_offensive_type", &battle_config.finger_offensive_type, 0, 0, 1, },
  5324. { "heal_exp", &battle_config.heal_exp, 0, 0, INT_MAX, },
  5325. { "resurrection_exp", &battle_config.resurrection_exp, 0, 0, INT_MAX, },
  5326. { "shop_exp", &battle_config.shop_exp, 0, 0, INT_MAX, },
  5327. { "max_heal_lv", &battle_config.max_heal_lv, 11, 1, INT_MAX, },
  5328. { "max_heal", &battle_config.max_heal, 9999, 0, INT_MAX, },
  5329. { "combo_delay_rate", &battle_config.combo_delay_rate, 100, 0, INT_MAX, },
  5330. { "item_check", &battle_config.item_check, 0, 0, 1, },
  5331. { "item_use_interval", &battle_config.item_use_interval, 100, 0, INT_MAX, },
  5332. { "cashfood_use_interval", &battle_config.cashfood_use_interval, 60000, 0, INT_MAX, },
  5333. { "wedding_modifydisplay", &battle_config.wedding_modifydisplay, 0, 0, 1, },
  5334. { "wedding_ignorepalette", &battle_config.wedding_ignorepalette, 0, 0, 1, },
  5335. { "xmas_ignorepalette", &battle_config.xmas_ignorepalette, 0, 0, 1, },
  5336. { "summer_ignorepalette", &battle_config.summer_ignorepalette, 0, 0, 1, },
  5337. { "natural_healhp_interval", &battle_config.natural_healhp_interval, 6000, NATURAL_HEAL_INTERVAL, INT_MAX, },
  5338. { "natural_healsp_interval", &battle_config.natural_healsp_interval, 8000, NATURAL_HEAL_INTERVAL, INT_MAX, },
  5339. { "natural_heal_skill_interval", &battle_config.natural_heal_skill_interval, 10000, NATURAL_HEAL_INTERVAL, INT_MAX, },
  5340. { "natural_heal_weight_rate", &battle_config.natural_heal_weight_rate, 50, 50, 101 },
  5341. { "arrow_decrement", &battle_config.arrow_decrement, 1, 0, 2, },
  5342. { "max_aspd", &battle_config.max_aspd, 199, 100, 199, },
  5343. { "max_walk_speed", &battle_config.max_walk_speed, 300, 100, 100*DEFAULT_WALK_SPEED, },
  5344. { "max_lv", &battle_config.max_lv, 99, 0, 150, },
  5345. { "aura_lv", &battle_config.aura_lv, 99, 0, INT_MAX, },
  5346. { "max_hp", &battle_config.max_hp, 32500, 100, 1000000000, },
  5347. { "max_sp", &battle_config.max_sp, 32500, 100, 1000000000, },
  5348. { "max_cart_weight", &battle_config.max_cart_weight, 8000, 100, 1000000, },
  5349. { "max_parameter", &battle_config.max_parameter, 99, 10, 10000, },
  5350. { "max_baby_parameter", &battle_config.max_baby_parameter, 80, 10, 10000, },
  5351. { "max_third_parameter", &battle_config.max_third_parameter, 120, 10, 10000, },
  5352. { "max_baby_third_paramater", &battle_config.max_baby_third_paramater, 108, 10, 10000, },
  5353. { "max_def", &battle_config.max_def, 99, 0, INT_MAX, },
  5354. { "over_def_bonus", &battle_config.over_def_bonus, 0, 0, 1000, },
  5355. { "skill_log", &battle_config.skill_log, BL_NUL, BL_NUL, BL_ALL, },
  5356. { "battle_log", &battle_config.battle_log, 0, 0, 1, },
  5357. { "save_log", &battle_config.save_log, 0, 0, 1, },
  5358. { "etc_log", &battle_config.etc_log, 1, 0, 1, },
  5359. { "save_clothcolor", &battle_config.save_clothcolor, 1, 0, 1, },
  5360. { "undead_detect_type", &battle_config.undead_detect_type, 0, 0, 2, },
  5361. { "auto_counter_type", &battle_config.auto_counter_type, BL_ALL, BL_NUL, BL_ALL, },
  5362. { "min_hitrate", &battle_config.min_hitrate, 5, 0, 100, },
  5363. { "max_hitrate", &battle_config.max_hitrate, 100, 0, 100, },
  5364. { "agi_penalty_target", &battle_config.agi_penalty_target, BL_PC, BL_NUL, BL_ALL, },
  5365. { "agi_penalty_type", &battle_config.agi_penalty_type, 1, 0, 2, },
  5366. { "agi_penalty_count", &battle_config.agi_penalty_count, 3, 2, INT_MAX, },
  5367. { "agi_penalty_num", &battle_config.agi_penalty_num, 10, 0, INT_MAX, },
  5368. { "agi_penalty_count_lv", &battle_config.agi_penalty_count_lv, ATK_FLEE, 0, INT_MAX, },
  5369. { "vit_penalty_target", &battle_config.vit_penalty_target, BL_PC, BL_NUL, BL_ALL, },
  5370. { "vit_penalty_type", &battle_config.vit_penalty_type, 1, 0, 2, },
  5371. { "vit_penalty_count", &battle_config.vit_penalty_count, 3, 2, INT_MAX, },
  5372. { "vit_penalty_num", &battle_config.vit_penalty_num, 5, 0, INT_MAX, },
  5373. { "vit_penalty_count_lv", &battle_config.vit_penalty_count_lv, ATK_MISS, 0, INT_MAX, },
  5374. { "weapon_defense_type", &battle_config.weapon_defense_type, 0, 0, INT_MAX, },
  5375. { "magic_defense_type", &battle_config.magic_defense_type, 0, 0, INT_MAX, },
  5376. { "skill_reiteration", &battle_config.skill_reiteration, BL_NUL, BL_NUL, BL_ALL, },
  5377. { "skill_nofootset", &battle_config.skill_nofootset, BL_PC, BL_NUL, BL_ALL, },
  5378. { "player_cloak_check_type", &battle_config.pc_cloak_check_type, 1, 0, 1|2|4, },
  5379. { "monster_cloak_check_type", &battle_config.monster_cloak_check_type, 4, 0, 1|2|4, },
  5380. { "player_camouflage_check_type", &battle_config.pc_camouflage_check_type, 1, 0, 1|2|4, },
  5381. { "sense_type", &battle_config.estimation_type, 1|2, 0, 1|2, },
  5382. { "gvg_eliminate_time", &battle_config.gvg_eliminate_time, 7000, 0, INT_MAX, },
  5383. { "gvg_short_attack_damage_rate", &battle_config.gvg_short_damage_rate, 80, 0, INT_MAX, },
  5384. { "gvg_long_attack_damage_rate", &battle_config.gvg_long_damage_rate, 80, 0, INT_MAX, },
  5385. { "gvg_weapon_attack_damage_rate", &battle_config.gvg_weapon_damage_rate, 60, 0, INT_MAX, },
  5386. { "gvg_magic_attack_damage_rate", &battle_config.gvg_magic_damage_rate, 60, 0, INT_MAX, },
  5387. { "gvg_misc_attack_damage_rate", &battle_config.gvg_misc_damage_rate, 60, 0, INT_MAX, },
  5388. { "gvg_flee_penalty", &battle_config.gvg_flee_penalty, 20, 0, INT_MAX, },
  5389. { "pk_short_attack_damage_rate", &battle_config.pk_short_damage_rate, 80, 0, INT_MAX, },
  5390. { "pk_long_attack_damage_rate", &battle_config.pk_long_damage_rate, 70, 0, INT_MAX, },
  5391. { "pk_weapon_attack_damage_rate", &battle_config.pk_weapon_damage_rate, 60, 0, INT_MAX, },
  5392. { "pk_magic_attack_damage_rate", &battle_config.pk_magic_damage_rate, 60, 0, INT_MAX, },
  5393. { "pk_misc_attack_damage_rate", &battle_config.pk_misc_damage_rate, 60, 0, INT_MAX, },
  5394. { "mob_changetarget_byskill", &battle_config.mob_changetarget_byskill, 0, 0, 1, },
  5395. { "attack_direction_change", &battle_config.attack_direction_change, BL_ALL, BL_NUL, BL_ALL, },
  5396. { "land_skill_limit", &battle_config.land_skill_limit, BL_ALL, BL_NUL, BL_ALL, },
  5397. { "monster_class_change_full_recover", &battle_config.monster_class_change_recover, 1, 0, 1, },
  5398. { "produce_item_name_input", &battle_config.produce_item_name_input, 0x1|0x2, 0, 0x9F, },
  5399. { "display_skill_fail", &battle_config.display_skill_fail, 2, 0, 1|2|4|8, },
  5400. { "chat_warpportal", &battle_config.chat_warpportal, 0, 0, 1, },
  5401. { "mob_warp", &battle_config.mob_warp, 0, 0, 1|2|4|8, },
  5402. { "dead_branch_active", &battle_config.dead_branch_active, 1, 0, 1, },
  5403. { "vending_max_value", &battle_config.vending_max_value, 10000000, 1, MAX_ZENY, },
  5404. { "vending_over_max", &battle_config.vending_over_max, 1, 0, 1, },
  5405. { "show_steal_in_same_party", &battle_config.show_steal_in_same_party, 0, 0, 1, },
  5406. { "party_hp_mode", &battle_config.party_hp_mode, 0, 0, 1, },
  5407. { "show_party_share_picker", &battle_config.party_show_share_picker, 1, 0, 1, },
  5408. { "show_picker.item_type", &battle_config.show_picker_item_type, 112, 0, INT_MAX, },
  5409. { "party_update_interval", &battle_config.party_update_interval, 1000, 100, INT_MAX, },
  5410. { "party_item_share_type", &battle_config.party_share_type, 0, 0, 1|2|3|4, },
  5411. { "attack_attr_none", &battle_config.attack_attr_none, ~BL_PC, BL_NUL, BL_ALL, },
  5412. { "gx_allhit", &battle_config.gx_allhit, 0, 0, 1, },
  5413. { "gx_disptype", &battle_config.gx_disptype, 1, 0, 1, },
  5414. { "devotion_level_difference", &battle_config.devotion_level_difference, 10, 0, INT_MAX, },
  5415. { "player_skill_partner_check", &battle_config.player_skill_partner_check, 1, 0, 1, },
  5416. { "hide_GM_session", &battle_config.hide_GM_session, 0, 0, 1, },
  5417. { "invite_request_check", &battle_config.invite_request_check, 1, 0, 1, },
  5418. { "skill_removetrap_type", &battle_config.skill_removetrap_type, 0, 0, 1, },
  5419. { "disp_experience", &battle_config.disp_experience, 0, 0, 1, },
  5420. { "disp_zeny", &battle_config.disp_zeny, 0, 0, 1, },
  5421. { "castle_defense_rate", &battle_config.castle_defense_rate, 100, 0, 100, },
  5422. { "gm_cant_drop_min_lv", &battle_config.gm_cant_drop_min_lv, 1, 0, 100, },
  5423. { "gm_cant_drop_max_lv", &battle_config.gm_cant_drop_max_lv, 0, 0, 100, },
  5424. { "disp_hpmeter", &battle_config.disp_hpmeter, 0, 0, 100, },
  5425. { "bone_drop", &battle_config.bone_drop, 0, 0, 2, },
  5426. { "buyer_name", &battle_config.buyer_name, 1, 0, 1, },
  5427. { "skill_wall_check", &battle_config.skill_wall_check, 1, 0, 1, },
  5428. { "cell_stack_limit", &battle_config.cell_stack_limit, 1, 1, 255, },
  5429. // eAthena additions
  5430. { "item_logarithmic_drops", &battle_config.logarithmic_drops, 0, 0, 1, },
  5431. { "item_drop_common_min", &battle_config.item_drop_common_min, 1, 1, 10000, },
  5432. { "item_drop_common_max", &battle_config.item_drop_common_max, 10000, 1, 10000, },
  5433. { "item_drop_equip_min", &battle_config.item_drop_equip_min, 1, 1, 10000, },
  5434. { "item_drop_equip_max", &battle_config.item_drop_equip_max, 10000, 1, 10000, },
  5435. { "item_drop_card_min", &battle_config.item_drop_card_min, 1, 1, 10000, },
  5436. { "item_drop_card_max", &battle_config.item_drop_card_max, 10000, 1, 10000, },
  5437. { "item_drop_mvp_min", &battle_config.item_drop_mvp_min, 1, 1, 10000, },
  5438. { "item_drop_mvp_max", &battle_config.item_drop_mvp_max, 10000, 1, 10000, },
  5439. { "item_drop_heal_min", &battle_config.item_drop_heal_min, 1, 1, 10000, },
  5440. { "item_drop_heal_max", &battle_config.item_drop_heal_max, 10000, 1, 10000, },
  5441. { "item_drop_use_min", &battle_config.item_drop_use_min, 1, 1, 10000, },
  5442. { "item_drop_use_max", &battle_config.item_drop_use_max, 10000, 1, 10000, },
  5443. { "item_drop_add_min", &battle_config.item_drop_adddrop_min, 1, 1, 10000, },
  5444. { "item_drop_add_max", &battle_config.item_drop_adddrop_max, 10000, 1, 10000, },
  5445. { "item_drop_treasure_min", &battle_config.item_drop_treasure_min, 1, 1, 10000, },
  5446. { "item_drop_treasure_max", &battle_config.item_drop_treasure_max, 10000, 1, 10000, },
  5447. { "item_rate_mvp", &battle_config.item_rate_mvp, 100, 0, 1000000, },
  5448. { "item_rate_common", &battle_config.item_rate_common, 100, 0, 1000000, },
  5449. { "item_rate_common_boss", &battle_config.item_rate_common_boss, 100, 0, 1000000, },
  5450. { "item_rate_equip", &battle_config.item_rate_equip, 100, 0, 1000000, },
  5451. { "item_rate_equip_boss", &battle_config.item_rate_equip_boss, 100, 0, 1000000, },
  5452. { "item_rate_card", &battle_config.item_rate_card, 100, 0, 1000000, },
  5453. { "item_rate_card_boss", &battle_config.item_rate_card_boss, 100, 0, 1000000, },
  5454. { "item_rate_heal", &battle_config.item_rate_heal, 100, 0, 1000000, },
  5455. { "item_rate_heal_boss", &battle_config.item_rate_heal_boss, 100, 0, 1000000, },
  5456. { "item_rate_use", &battle_config.item_rate_use, 100, 0, 1000000, },
  5457. { "item_rate_use_boss", &battle_config.item_rate_use_boss, 100, 0, 1000000, },
  5458. { "item_rate_adddrop", &battle_config.item_rate_adddrop, 100, 0, 1000000, },
  5459. { "item_rate_treasure", &battle_config.item_rate_treasure, 100, 0, 1000000, },
  5460. { "prevent_logout", &battle_config.prevent_logout, 10000, 0, 60000, },
  5461. { "alchemist_summon_reward", &battle_config.alchemist_summon_reward, 1, 0, 2, },
  5462. { "drops_by_luk", &battle_config.drops_by_luk, 0, 0, INT_MAX, },
  5463. { "drops_by_luk2", &battle_config.drops_by_luk2, 0, 0, INT_MAX, },
  5464. { "equip_natural_break_rate", &battle_config.equip_natural_break_rate, 0, 0, INT_MAX, },
  5465. { "equip_self_break_rate", &battle_config.equip_self_break_rate, 100, 0, INT_MAX, },
  5466. { "equip_skill_break_rate", &battle_config.equip_skill_break_rate, 100, 0, INT_MAX, },
  5467. { "pk_mode", &battle_config.pk_mode, 0, 0, 1, },
  5468. { "pk_level_range", &battle_config.pk_level_range, 0, 0, INT_MAX, },
  5469. { "manner_system", &battle_config.manner_system, 0xFFF, 0, 0xFFF, },
  5470. { "manner_system_new", &battle_config.manner_system_new, 0xFFF, 0, 0xFFF, },
  5471. { "pet_equip_required", &battle_config.pet_equip_required, 0, 0, 1, },
  5472. { "multi_level_up", &battle_config.multi_level_up, 0, 0, 1, },
  5473. { "max_exp_gain_rate", &battle_config.max_exp_gain_rate, 0, 0, INT_MAX, },
  5474. { "backstab_bow_penalty", &battle_config.backstab_bow_penalty, 0, 0, 1, },
  5475. { "night_at_start", &battle_config.night_at_start, 0, 0, 1, },
  5476. { "show_mob_info", &battle_config.show_mob_info, 0, 0, 1|2|4, },
  5477. { "ban_hack_trade", &battle_config.ban_hack_trade, 0, 0, INT_MAX, },
  5478. { "hack_info_GM_level", &battle_config.hack_info_GM_level, 60, 0, 100, },
  5479. { "any_warp_GM_min_level", &battle_config.any_warp_GM_min_level, 20, 0, 100, },
  5480. { "who_display_aid", &battle_config.who_display_aid, 40, 0, 100, },
  5481. { "packet_ver_flag", &battle_config.packet_ver_flag, 0xFFFFFF,0x0000,INT_MAX, },
  5482. { "min_hair_style", &battle_config.min_hair_style, 0, 0, INT_MAX, },
  5483. { "max_hair_style", &battle_config.max_hair_style, 23, 0, INT_MAX, },
  5484. { "min_hair_color", &battle_config.min_hair_color, 0, 0, INT_MAX, },
  5485. { "max_hair_color", &battle_config.max_hair_color, 9, 0, INT_MAX, },
  5486. { "min_cloth_color", &battle_config.min_cloth_color, 0, 0, INT_MAX, },
  5487. { "max_cloth_color", &battle_config.max_cloth_color, 4, 0, INT_MAX, },
  5488. { "pet_hair_style", &battle_config.pet_hair_style, 100, 0, INT_MAX, },
  5489. { "castrate_dex_scale", &battle_config.castrate_dex_scale, 150, 1, INT_MAX, },
  5490. { "area_size", &battle_config.area_size, 14, 0, INT_MAX, },
  5491. { "zeny_from_mobs", &battle_config.zeny_from_mobs, 0, 0, 1, },
  5492. { "mobs_level_up", &battle_config.mobs_level_up, 0, 0, 1, },
  5493. { "mobs_level_up_exp_rate", &battle_config.mobs_level_up_exp_rate, 1, 1, INT_MAX, },
  5494. { "pk_min_level", &battle_config.pk_min_level, 55, 1, INT_MAX, },
  5495. { "skill_steal_max_tries", &battle_config.skill_steal_max_tries, 0, 0, UCHAR_MAX, },
  5496. { "motd_type", &battle_config.motd_type, 0, 0, 1, },
  5497. { "finding_ore_rate", &battle_config.finding_ore_rate, 100, 0, INT_MAX, },
  5498. { "exp_calc_type", &battle_config.exp_calc_type, 0, 0, 1, },
  5499. { "exp_bonus_attacker", &battle_config.exp_bonus_attacker, 25, 0, INT_MAX, },
  5500. { "exp_bonus_max_attacker", &battle_config.exp_bonus_max_attacker, 12, 2, INT_MAX, },
  5501. { "min_skill_delay_limit", &battle_config.min_skill_delay_limit, 100, 10, INT_MAX, },
  5502. { "default_walk_delay", &battle_config.default_walk_delay, 300, 0, INT_MAX, },
  5503. { "no_skill_delay", &battle_config.no_skill_delay, BL_MOB, BL_NUL, BL_ALL, },
  5504. { "attack_walk_delay", &battle_config.attack_walk_delay, BL_ALL, BL_NUL, BL_ALL, },
  5505. { "require_glory_guild", &battle_config.require_glory_guild, 0, 0, 1, },
  5506. { "idle_no_share", &battle_config.idle_no_share, 0, 0, INT_MAX, },
  5507. { "party_even_share_bonus", &battle_config.party_even_share_bonus, 0, 0, INT_MAX, },
  5508. { "delay_battle_damage", &battle_config.delay_battle_damage, 1, 0, 1, },
  5509. { "hide_woe_damage", &battle_config.hide_woe_damage, 0, 0, 1, },
  5510. { "display_version", &battle_config.display_version, 1, 0, 1, },
  5511. { "display_hallucination", &battle_config.display_hallucination, 1, 0, 1, },
  5512. { "use_statpoint_table", &battle_config.use_statpoint_table, 1, 0, 1, },
  5513. { "ignore_items_gender", &battle_config.ignore_items_gender, 1, 0, 1, },
  5514. { "copyskill_restrict", &battle_config.copyskill_restrict, 2, 0, 2, },
  5515. { "berserk_cancels_buffs", &battle_config.berserk_cancels_buffs, 0, 0, 1, },
  5516. { "debuff_on_logout", &battle_config.debuff_on_logout, 1|2, 0, 1|2, },
  5517. { "monster_ai", &battle_config.mob_ai, 0x000, 0x000, 0x77F, },
  5518. { "hom_setting", &battle_config.hom_setting, 0xFFFF, 0x0000, 0xFFFF, },
  5519. { "dynamic_mobs", &battle_config.dynamic_mobs, 1, 0, 1, },
  5520. { "mob_remove_damaged", &battle_config.mob_remove_damaged, 1, 0, 1, },
  5521. { "show_hp_sp_drain", &battle_config.show_hp_sp_drain, 0, 0, 1, },
  5522. { "show_hp_sp_gain", &battle_config.show_hp_sp_gain, 1, 0, 1, },
  5523. { "mob_npc_event_type", &battle_config.mob_npc_event_type, 1, 0, 1, },
  5524. { "mob_clear_delay", &battle_config.mob_clear_delay, 0, 0, INT_MAX, },
  5525. { "character_size", &battle_config.character_size, 1|2, 0, 1|2, },
  5526. { "mob_max_skilllvl", &battle_config.mob_max_skilllvl, MAX_SKILL_LEVEL, 1, MAX_SKILL_LEVEL, },
  5527. { "retaliate_to_master", &battle_config.retaliate_to_master, 1, 0, 1, },
  5528. { "rare_drop_announce", &battle_config.rare_drop_announce, 0, 0, 10000, },
  5529. { "title_lvl1", &battle_config.title_lvl1, 1, 0, 100, },
  5530. { "title_lvl2", &battle_config.title_lvl2, 10, 0, 100, },
  5531. { "title_lvl3", &battle_config.title_lvl3, 20, 0, 100, },
  5532. { "title_lvl4", &battle_config.title_lvl4, 40, 0, 100, },
  5533. { "title_lvl5", &battle_config.title_lvl5, 50, 0, 100, },
  5534. { "title_lvl6", &battle_config.title_lvl6, 60, 0, 100, },
  5535. { "title_lvl7", &battle_config.title_lvl7, 80, 0, 100, },
  5536. { "title_lvl8", &battle_config.title_lvl8, 99, 0, 100, },
  5537. { "duel_allow_pvp", &battle_config.duel_allow_pvp, 0, 0, 1, },
  5538. { "duel_allow_gvg", &battle_config.duel_allow_gvg, 0, 0, 1, },
  5539. { "duel_allow_teleport", &battle_config.duel_allow_teleport, 0, 0, 1, },
  5540. { "duel_autoleave_when_die", &battle_config.duel_autoleave_when_die, 1, 0, 1, },
  5541. { "duel_time_interval", &battle_config.duel_time_interval, 60, 0, INT_MAX, },
  5542. { "duel_only_on_same_map", &battle_config.duel_only_on_same_map, 0, 0, 1, },
  5543. { "skip_teleport_lv1_menu", &battle_config.skip_teleport_lv1_menu, 0, 0, 1, },
  5544. { "allow_skill_without_day", &battle_config.allow_skill_without_day, 0, 0, 1, },
  5545. { "allow_es_magic_player", &battle_config.allow_es_magic_pc, 0, 0, 1, },
  5546. { "skill_caster_check", &battle_config.skill_caster_check, 1, 0, 1, },
  5547. { "status_cast_cancel", &battle_config.sc_castcancel, BL_NUL, BL_NUL, BL_ALL, },
  5548. { "pc_status_def_rate", &battle_config.pc_sc_def_rate, 100, 0, INT_MAX, },
  5549. { "mob_status_def_rate", &battle_config.mob_sc_def_rate, 100, 0, INT_MAX, },
  5550. { "pc_luk_status_def", &battle_config.pc_luk_sc_def, 300, 1, INT_MAX, },
  5551. { "mob_luk_status_def", &battle_config.mob_luk_sc_def, 300, 1, INT_MAX, },
  5552. { "pc_max_status_def", &battle_config.pc_max_sc_def, 100, 0, INT_MAX, },
  5553. { "mob_max_status_def", &battle_config.mob_max_sc_def, 100, 0, INT_MAX, },
  5554. { "sg_miracle_skill_ratio", &battle_config.sg_miracle_skill_ratio, 1, 0, 10000, },
  5555. { "sg_angel_skill_ratio", &battle_config.sg_angel_skill_ratio, 10, 0, 10000, },
  5556. { "autospell_stacking", &battle_config.autospell_stacking, 0, 0, 1, },
  5557. { "override_mob_names", &battle_config.override_mob_names, 0, 0, 2, },
  5558. { "min_chat_delay", &battle_config.min_chat_delay, 0, 0, INT_MAX, },
  5559. { "friend_auto_add", &battle_config.friend_auto_add, 1, 0, 1, },
  5560. { "hom_rename", &battle_config.hom_rename, 0, 0, 1, },
  5561. { "homunculus_show_growth", &battle_config.homunculus_show_growth, 0, 0, 1, },
  5562. { "homunculus_friendly_rate", &battle_config.homunculus_friendly_rate, 100, 0, INT_MAX, },
  5563. { "vending_tax", &battle_config.vending_tax, 0, 0, 10000, },
  5564. { "homunculus_max_level", &battle_config.hom_max_level, 99, 0, MAX_LEVEL, }, // [Nibi]
  5565. { "homunculus_S_max_level", &battle_config.hom_S_max_level, 150, 0, MAX_LEVEL, }, // [Nibi]
  5566. { "day_duration", &battle_config.day_duration, 0, 0, INT_MAX, },
  5567. { "night_duration", &battle_config.night_duration, 0, 0, INT_MAX, },
  5568. { "mob_remove_delay", &battle_config.mob_remove_delay, 60000, 1000, INT_MAX, },
  5569. { "mob_active_time", &battle_config.mob_active_time, 0, 0, INT_MAX, },
  5570. { "boss_active_time", &battle_config.boss_active_time, 0, 0, INT_MAX, },
  5571. { "sg_miracle_skill_duration", &battle_config.sg_miracle_skill_duration, 3600000, 0, INT_MAX, },
  5572. { "hvan_explosion_intimate", &battle_config.hvan_explosion_intimate, 45000, 0, 100000, },
  5573. { "quest_exp_rate", &battle_config.quest_exp_rate, 100, 0, INT_MAX, },
  5574. { "at_mapflag", &battle_config.autotrade_mapflag, 0, 0, 1, },
  5575. { "at_timeout", &battle_config.at_timeout, 0, 0, INT_MAX, },
  5576. { "homunculus_autoloot", &battle_config.homunculus_autoloot, 0, 0, 1, },
  5577. { "idle_no_autoloot", &battle_config.idle_no_autoloot, 0, 0, INT_MAX, },
  5578. { "max_guild_alliance", &battle_config.max_guild_alliance, 3, 0, 3, },
  5579. { "ksprotection", &battle_config.ksprotection, 5000, 0, INT_MAX, },
  5580. { "auction_feeperhour", &battle_config.auction_feeperhour, 12000, 0, INT_MAX, },
  5581. { "auction_maximumprice", &battle_config.auction_maximumprice, 500000000, 0, MAX_ZENY, },
  5582. { "gm_viewequip_min_lv", &battle_config.gm_viewequip_min_lv, 0, 0, 99, },
  5583. { "homunculus_auto_vapor", &battle_config.homunculus_auto_vapor, 1, 0, 1, },
  5584. { "display_status_timers", &battle_config.display_status_timers, 1, 0, 1, },
  5585. { "skill_add_heal_rate", &battle_config.skill_add_heal_rate, 7, 0, INT_MAX, },
  5586. { "eq_single_target_reflectable", &battle_config.eq_single_target_reflectable, 1, 0, 1, },
  5587. { "invincible.nodamage", &battle_config.invincible_nodamage, 0, 0, 1, },
  5588. { "mob_slave_keep_target", &battle_config.mob_slave_keep_target, 0, 0, 1, },
  5589. { "autospell_check_range", &battle_config.autospell_check_range, 0, 0, 1, },
  5590. { "client_reshuffle_dice", &battle_config.client_reshuffle_dice, 0, 0, 1, },
  5591. { "client_sort_storage", &battle_config.client_sort_storage, 0, 0, 1, },
  5592. { "gm_check_minlevel", &battle_config.gm_check_minlevel, 60, 0, 100, },
  5593. { "feature.buying_store", &battle_config.feature_buying_store, 1, 0, 1, },
  5594. { "feature.search_stores", &battle_config.feature_search_stores, 1, 0, 1, },
  5595. { "searchstore_querydelay", &battle_config.searchstore_querydelay, 10, 0, INT_MAX, },
  5596. { "searchstore_maxresults", &battle_config.searchstore_maxresults, 30, 1, INT_MAX, },
  5597. { "display_party_name", &battle_config.display_party_name, 0, 0, 1, },
  5598. // BattleGround Settings
  5599. { "bg_update_interval", &battle_config.bg_update_interval, 1000, 100, INT_MAX, },
  5600. { "bg_short_attack_damage_rate", &battle_config.bg_short_damage_rate, 80, 0, INT_MAX, },
  5601. { "bg_long_attack_damage_rate", &battle_config.bg_long_damage_rate, 80, 0, INT_MAX, },
  5602. { "bg_weapon_attack_damage_rate", &battle_config.bg_weapon_damage_rate, 60, 0, INT_MAX, },
  5603. { "bg_magic_attack_damage_rate", &battle_config.bg_magic_damage_rate, 60, 0, INT_MAX, },
  5604. { "bg_misc_attack_damage_rate", &battle_config.bg_misc_damage_rate, 60, 0, INT_MAX, },
  5605. { "bg_flee_penalty", &battle_config.bg_flee_penalty, 20, 0, INT_MAX, },
  5606. // Casting Time Renewal Settings
  5607. { "renewal_cast_3rd_skills", &battle_config.renewal_cast_3rd_skills, 1, 0, 1, },
  5608. { "castrate_dex_scale_3rd", &battle_config.castrate_dex_scale_3rd, 150, 1, INT_MAX, },
  5609. { "warg_can_falcon", &battle_config.warg_can_falcon, 0, 0, 1, },
  5610. { "renewal_edp", &battle_config.renewal_edp, 0, 0, 3, },
  5611. { "use_renewal_statpoints", &battle_config.use_renewal_statpoints, 0, 0, 1, },
  5612. { "max_highlvl_nerf", &battle_config.max_highlvl_nerf, 100, 0, INT_MAX, },
  5613. { "max_joblvl_nerf", &battle_config.max_joblvl_nerf, 100, 0, INT_MAX, },
  5614. { "max_joblvl_nerf_misc", &battle_config.max_joblvl_nerf_misc, 100, 0, INT_MAX, },
  5615. { "skillsbonus_maxhp_RK", &battle_config.skillsbonus_maxhp_RK, 0, 0, INT_MAX, },
  5616. { "skillsbonus_maxhp_SR", &battle_config.skillsbonus_maxhp_SR, 0, 0, INT_MAX, },
  5617. { "metallicsound_spburn_rate", &battle_config.metallicsound_spburn_rate, 100, 0, INT_MAX, },
  5618. { "renewal_baselvl_skill_ratio", &battle_config.renewal_baselvl_skill_ratio, 1, 0, 1, },
  5619. { "renewal_baselvl_skill_effect", &battle_config.renewal_baselvl_skill_effect, 1, 0, 1, },
  5620. { "mado_skill_limit", &battle_config.mado_skill_limit, 1, 0, 1, },
  5621. { "mado_loss_on_death", &battle_config.mado_loss_on_death, 1, 0, 1, },
  5622. };
  5623.  
  5624.  
  5625. int battle_set_value(const char* w1, const char* w2)
  5626. {
  5627. int val = config_switch(w2);
  5628.  
  5629. int i;
  5630. ARR_FIND(0, ARRAYLENGTH(battle_data), i, strcmpi(w1, battle_data[i].str) == 0);
  5631. if (i == ARRAYLENGTH(battle_data))
  5632. return 0; // not found
  5633.  
  5634. if (val < battle_data[i].min || val > battle_data[i].max)
  5635. {
  5636. ShowWarning("Value for setting '%s': %s is invalid (min:%i max:%i)! Defaulting to %i...\n", w1, w2, battle_data[i].min, battle_data[i].max, battle_data[i].defval);
  5637. val = battle_data[i].defval;
  5638. }
  5639.  
  5640. *battle_data[i].val = val;
  5641. return 1;
  5642. }
  5643.  
  5644. int battle_get_value(const char* w1)
  5645. {
  5646. int i;
  5647. ARR_FIND(0, ARRAYLENGTH(battle_data), i, strcmpi(w1, battle_data[i].str) == 0);
  5648. if (i == ARRAYLENGTH(battle_data))
  5649. return 0; // not found
  5650. else
  5651. return *battle_data[i].val;
  5652. }
  5653.  
  5654. void battle_set_defaults()
  5655. {
  5656. int i;
  5657. for (i = 0; i < ARRAYLENGTH(battle_data); i++)
  5658. *battle_data[i].val = battle_data[i].defval;
  5659. }
  5660.  
  5661. void battle_adjust_conf()
  5662. {
  5663. battle_config.monster_max_aspd = 2000 - battle_config.monster_max_aspd*10;
  5664. battle_config.max_aspd = 2000 - battle_config.max_aspd*10;
  5665. battle_config.max_walk_speed = 100*DEFAULT_WALK_SPEED/battle_config.max_walk_speed;
  5666. battle_config.max_cart_weight *= 10;
  5667.  
  5668. if(battle_config.max_def > 100 && !battle_config.weapon_defense_type) // added by [Skotlex]
  5669. battle_config.max_def = 100;
  5670.  
  5671. if(battle_config.min_hitrate > battle_config.max_hitrate)
  5672. battle_config.min_hitrate = battle_config.max_hitrate;
  5673.  
  5674. if(battle_config.pet_max_atk1 > battle_config.pet_max_atk2) //Skotlex
  5675. battle_config.pet_max_atk1 = battle_config.pet_max_atk2;
  5676.  
  5677. if (battle_config.day_duration && battle_config.day_duration < 60000) // added by [Yor]
  5678. battle_config.day_duration = 60000;
  5679. if (battle_config.night_duration && battle_config.night_duration < 60000) // added by [Yor]
  5680. battle_config.night_duration = 60000;
  5681.  
  5682. #ifndef CELL_NOSTACK
  5683. if (battle_config.cell_stack_limit != 1)
  5684. ShowWarning("Battle setting 'cell_stack_limit' takes no effect as this server was compiled without Cell Stack Limit support.\n");
  5685. #endif
  5686. }
  5687.  
  5688. int battle_config_read(const char* cfgName)
  5689. {
  5690. char line[1024], w1[1024], w2[1024];
  5691. FILE* fp;
  5692. static int count = 0;
  5693.  
  5694. if (count == 0)
  5695. battle_set_defaults();
  5696.  
  5697. count++;
  5698.  
  5699. fp = fopen(cfgName,"r");
  5700. if (fp == NULL)
  5701. ShowError("File not found: %s\n", cfgName);
  5702. else
  5703. {
  5704. while(fgets(line, sizeof(line), fp))
  5705. {
  5706. if (line[0] == '/' && line[1] == '/')
  5707. continue;
  5708. if (sscanf(line, "%1023[^:]:%1023s", w1, w2) != 2)
  5709. continue;
  5710. if (strcmpi(w1, "import") == 0)
  5711. battle_config_read(w2);
  5712. else
  5713. if (battle_set_value(w1, w2) == 0)
  5714. ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName);
  5715. }
  5716.  
  5717. fclose(fp);
  5718. }
  5719.  
  5720. count--;
  5721.  
  5722. if (count == 0)
  5723. battle_adjust_conf();
  5724.  
  5725. return 0;
  5726. }
  5727.  
  5728. void do_init_battle(void)
  5729. {
  5730. delay_damage_ers = ers_new(sizeof(struct delay_damage));
  5731. add_timer_func_list(battle_delay_damage_sub, "battle_delay_damage_sub");
  5732. }
  5733.  
  5734. void do_final_battle(void)
  5735. {
  5736. ers_destroy(delay_damage_ers);
  5737. }
Advertisement
Add Comment
Please, Sign In to add comment