root/src/map/battle.c @ 1

Revision 1, 149.6 kB (checked in by jinshiro, 17 years ago)
RevLine 
[1]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 "mercenary.h"
19#include "mob.h"
20#include "itemdb.h"
21#include "clif.h"
22#include "pet.h"
23#include "guild.h"
24#include "party.h"
25#include "battle.h"
26
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <math.h>
31
32int attr_fix_table[4][ELE_MAX][ELE_MAX];
33
34struct Battle_Config battle_config;
35static struct eri *delay_damage_ers; //For battle delay damage structures.
36
37int battle_getcurrentskill(struct block_list *bl)
38{       //Returns the current/last skill in use by this bl.
39        struct unit_data *ud;
40
41        if (bl->type == BL_SKILL) {
42                struct skill_unit * su = (struct skill_unit*)bl;
43                return su->group?su->group->skill_id:0;
44        }
45        ud = unit_bl2ud(bl);
46        return ud?ud->skillid:0;
47}
48
49/*==========================================
50 * Get random targetting enemy
51 *------------------------------------------*/
52static int battle_gettargeted_sub(struct block_list *bl, va_list ap)
53{
54        struct block_list **bl_list;
55        struct unit_data *ud;
56        int target_id;
57        int *c;
58
59        bl_list = va_arg(ap, struct block_list **);
60        c = va_arg(ap, int *);
61        target_id = va_arg(ap, int);
62
63        if (bl->id == target_id)
64                return 0;
65        if (*c >= 24)
66                return 0;
67
68        ud = unit_bl2ud(bl);
69        if (!ud) return 0;
70
71        if (ud->target == target_id || ud->skilltarget == target_id) {
72                bl_list[(*c)++] = bl;
73                return 1;
74        }
75        return 0;       
76}
77
78struct block_list* battle_gettargeted(struct block_list *target)
79{
80        struct block_list *bl_list[24];
81        int c = 0;
82        nullpo_retr(NULL, target);
83
84        memset(bl_list, 0, sizeof(bl_list));
85        map_foreachinrange(battle_gettargeted_sub, target, AREA_SIZE, BL_CHAR, bl_list, &c, target->id);
86        if (c == 0 || c > 24)
87                return NULL;
88        return bl_list[rand()%c];
89}
90
91
92//Returns the id of the current targetted character of the passed bl. [Skotlex]
93int battle_gettarget(struct block_list* bl)
94{
95        switch (bl->type)
96        {
97                case BL_PC:  return ((struct map_session_data*)bl)->ud.target;
98                case BL_MOB: return ((struct mob_data*)bl)->target_id;
99                case BL_PET: return ((struct pet_data*)bl)->target_id;
100                case BL_HOM: return ((struct homun_data*)bl)->ud.target;
101        }
102        return 0;
103}
104
105static int battle_getenemy_sub(struct block_list *bl, va_list ap)
106{
107        struct block_list **bl_list;
108        struct block_list *target;
109        int *c;
110
111        bl_list = va_arg(ap, struct block_list **);
112        c = va_arg(ap, int *);
113        target = va_arg(ap, struct block_list *);
114
115        if (bl->id == target->id)
116                return 0;
117        if (*c >= 24)
118                return 0;
119        if (status_isdead(bl))
120                return 0;
121        if (battle_check_target(target, bl, BCT_ENEMY) > 0) {
122                bl_list[(*c)++] = bl;
123                return 1;
124        }
125        return 0;       
126}
127
128// Picks a random enemy of the given type (BL_PC, BL_CHAR, etc) within the range given. [Skotlex]
129struct block_list* battle_getenemy(struct block_list *target, int type, int range)
130{
131        struct block_list *bl_list[24];
132        int c = 0;
133        memset(bl_list, 0, sizeof(bl_list));
134        map_foreachinrange(battle_getenemy_sub, target, range, type, bl_list, &c, target);
135        if (c == 0 || c > 24)
136                return NULL;
137        return bl_list[rand()%c];
138}
139
140// ƒ_E?[ƒW‚Ì’x‰„
141struct delay_damage {
142        struct block_list *src;
143        int target;
144        int damage;
145        int delay;
146        unsigned short distance;
147        unsigned short skill_lv;
148        unsigned short skill_id;
149        enum damage_lv dmg_lv;
150        unsigned short attack_type;
151};
152
153int battle_delay_damage_sub(int tid, unsigned int tick, int id, intptr data)
154{
155        struct delay_damage *dat = (struct delay_damage *)data;
156        struct block_list *target = map_id2bl(dat->target);
157        if (target && dat && map_id2bl(id) == dat->src && target->prev != NULL && !status_isdead(target) &&
158                target->m == dat->src->m &&
159                (target->type != BL_PC || ((TBL_PC*)target)->invincible_timer == -1) &&
160                check_distance_bl(dat->src, target, dat->distance)) //Check to see if you haven't teleported. [Skotlex]
161        {
162                map_freeblock_lock();
163                status_fix_damage(dat->src, target, dat->damage, dat->delay);
164                if (dat->damage > 0 && dat->attack_type)
165                {
166                        if (!status_isdead(target))
167                                skill_additional_effect(dat->src,target,dat->skill_id,dat->skill_lv,dat->attack_type,tick);
168                        skill_counter_additional_effect(dat->src,target,dat->skill_id,dat->skill_lv,dat->attack_type,tick);
169                }
170                map_freeblock_unlock();
171        }
172        ers_free(delay_damage_ers, dat);
173        return 0;
174}
175
176int 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)
177{
178        struct delay_damage *dat;
179        nullpo_retr(0, src);
180        nullpo_retr(0, target);
181
182        if (!battle_config.delay_battle_damage) {
183                map_freeblock_lock();
184                status_fix_damage(src, target, damage, ddelay);
185                if (damage > 0 && attack_type)
186                {
187                        if (!status_isdead(target))
188                                skill_additional_effect(src, target, skill_id, skill_lv, attack_type, gettick());
189                        skill_counter_additional_effect(src, target, skill_id, skill_lv, attack_type, gettick());
190                }
191                map_freeblock_unlock();
192                return 0;
193        }
194        dat = ers_alloc(delay_damage_ers, struct delay_damage);
195        dat->src = src;
196        dat->target = target->id;
197        dat->skill_id = skill_id;
198        dat->skill_lv = skill_lv;
199        dat->attack_type = attack_type;
200        dat->damage = damage;
201        dat->dmg_lv = dmg_lv;
202        dat->delay = ddelay;
203        dat->distance = distance_bl(src, target)+10; //Attack should connect regardless unless you teleported.
204        if (src->type != BL_PC && amotion > 1000)
205                amotion = 1000; //Aegis places a damage-delay cap of 1 sec to non player attacks. [Skotlex]
206        add_timer(tick+amotion, battle_delay_damage_sub, src->id, (int)dat);
207       
208        return 0;
209}
210
211int battle_attr_ratio(int atk_elem,int def_type, int def_lv)
212{
213       
214        if (atk_elem < 0 || atk_elem >= ELE_MAX)
215                return 100;
216
217        if (def_type < 0 || def_type > ELE_MAX || def_lv < 1 || def_lv > 4)
218                return 100;
219
220        return attr_fix_table[def_lv-1][atk_elem][def_type];
221}
222
223/*==========================================
224 * Does attribute fix modifiers.
225 * Added passing of the chars so that the status changes can affect it. [Skotlex]
226 * Note: Passing src/target == NULL is perfectly valid, it skips SC_ checks.
227 *------------------------------------------*/
228int battle_attr_fix(struct block_list *src, struct block_list *target, int damage,int atk_elem,int def_type, int def_lv)
229{
230        struct status_change *sc=NULL, *tsc=NULL;
231        int ratio;
232       
233        if (src) sc = status_get_sc(src);
234        if (target) tsc = status_get_sc(target);
235       
236        if (atk_elem < 0 || atk_elem >= ELE_MAX)
237                atk_elem = rand()%ELE_MAX;
238
239        if (def_type < 0 || def_type > ELE_MAX ||
240                def_lv < 1 || def_lv > 4) {
241                ShowError("battle_attr_fix: unknown attr type: atk=%d def_type=%d def_lv=%d\n",atk_elem,def_type,def_lv);
242                return damage;
243        }
244
245        ratio = attr_fix_table[def_lv-1][atk_elem][def_type];
246        if (sc && sc->count)
247        {
248                if(sc->data[SC_VOLCANO] && atk_elem == ELE_FIRE)
249                        ratio += enchant_eff[sc->data[SC_VOLCANO]->val1-1];
250                if(sc->data[SC_VIOLENTGALE] && atk_elem == ELE_WIND)
251                        ratio += enchant_eff[sc->data[SC_VIOLENTGALE]->val1-1];
252                if(sc->data[SC_DELUGE] && atk_elem == ELE_WATER)
253                        ratio += enchant_eff[sc->data[SC_DELUGE]->val1-1];
254        }
255        if (tsc && tsc->count)
256        {
257                if(tsc->data[SC_SPIDERWEB] && atk_elem == ELE_FIRE)
258                {       // [Celest]
259                        damage <<= 1;
260                        status_change_end(target, SC_SPIDERWEB, -1);
261                }
262        }
263        return damage*ratio/100;
264}
265
266/*==========================================
267 * ƒ_E?[ƒW?Å?IŒvŽZ
268 *------------------------------------------*/
269int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,int div_,int skill_num,int skill_lv,int flag)
270{
271        struct map_session_data *sd = NULL;
272        struct status_change *sc;
273        struct status_change_entry *sce;
274
275        nullpo_retr(0, bl);
276
277        if (!damage)
278                return 0;
279       
280        if( mob_ksprotected(src, bl) )
281                return 0;
282
283        if (bl->type == BL_PC) {
284                sd=(struct map_session_data *)bl;
285                //Special no damage states
286                if(flag&BF_WEAPON && sd->special_state.no_weapon_damage)
287                        damage -= damage*sd->special_state.no_weapon_damage/100;
288
289                if(flag&BF_MAGIC && sd->special_state.no_magic_damage)
290                        damage -= damage*sd->special_state.no_magic_damage/100;
291
292                if(flag&BF_MISC && sd->special_state.no_misc_damage)
293                        damage -= damage*sd->special_state.no_misc_damage/100;
294
295                if(!damage) return 0;
296        }
297       
298        if (skill_num == PA_PRESSURE)
299                return damage; //This skill bypass everything else.
300
301        sc = status_get_sc(bl);
302
303        if (sc && sc->count) {
304                //First, sc_*'s that reduce damage to 0.
305                if( sc->data[SC_SAFETYWALL] && (flag&(BF_SHORT|BF_MAGIC))==BF_SHORT )
306                {
307                        struct skill_unit_group *group = (struct skill_unit_group *)sc->data[SC_SAFETYWALL]->val3;
308                        if (group) {
309                                if (--group->val2<=0)
310                                        skill_delunitgroup(NULL,group);
311                                return 0;
312                        }
313                        status_change_end(bl,SC_SAFETYWALL,-1);
314                }
315
316                if( sc->data[SC_PNEUMA] && (flag&(BF_MAGIC|BF_LONG)) == BF_LONG )
317                        return 0;
318
319                if((sce=sc->data[SC_AUTOGUARD]) && flag&BF_WEAPON &&
320                        !(skill_get_nk(skill_num)&NK_NO_CARDFIX_ATK) &&
321                        rand()%100 < sce->val2)
322                {
323                        int delay;
324                        clif_skill_nodamage(bl,bl,CR_AUTOGUARD,sce->val1,1);
325                        // different delay depending on skill level [celest]
326                        if (sce->val1 <= 5)
327                                delay = 300;
328                        else if (sce->val1 > 5 && sce->val1 <= 9)
329                                delay = 200;
330                        else
331                                delay = 100;
332                        unit_set_walkdelay(bl, gettick(), delay, 1);
333
334                        if(sc->data[SC_SHRINK] && rand()%100<5*sce->val1)
335                                skill_blown(bl,src,skill_get_blewcount(CR_SHRINK,1),-1,0);
336                        return 0;
337                }
338
339                if((sce=sc->data[SC_PARRYING]) && flag&BF_WEAPON
340                        && skill_num != WS_CARTTERMINATION
341                        && rand()%100 < sce->val2)
342                {// attack blocked by Parrying
343                        clif_skill_nodamage(bl,bl,LK_PARRYING,sce->val1,1);
344                        return 0;
345                }
346               
347                if(sc->data[SC_DODGE] && !sc->opt1 &&
348                        (flag&BF_LONG || sc->data[SC_SPURT])
349                        && rand()%100 < 20) {
350                        if (sd && pc_issit(sd)) pc_setstand(sd); //Stand it to dodge.
351                        clif_skill_nodamage(bl,bl,TK_DODGE,1,1);
352                        if (!sc->data[SC_COMBO])
353                                sc_start4(bl, SC_COMBO, 100, TK_JUMPKICK, src->id, 1, 0, 2000);
354                        return 0;
355                }
356
357                if(sc->data[SC_HERMODE] && flag&BF_MAGIC)
358                        return 0;
359
360                if(sc->data[SC_TATAMIGAESHI] && (flag&(BF_MAGIC|BF_LONG)) == BF_LONG)
361                        return 0;
362
363                if((sce=sc->data[SC_KAUPE]) &&
364                        rand()%100 < sce->val2 &&
365                        (src->type == BL_PC || !skill_num))
366                {       //Kaupe only blocks all skills of players.
367                        clif_specialeffect(bl, 462, AREA);
368                        //Shouldn't end until Breaker's non-weapon part connects.
369                        if (skill_num != ASC_BREAKER || !(flag&BF_WEAPON))
370                                if (--(sce->val3) <= 0) //We make it work like Safety Wall, even though it only blocks 1 time.
371                                        status_change_end(bl, SC_KAUPE, -1);
372                        return 0;
373                }
374
375                if (((sce=sc->data[SC_UTSUSEMI]) || sc->data[SC_BUNSINJYUTSU])
376                && 
377                        flag&BF_WEAPON && !(skill_get_nk(skill_num)&NK_NO_CARDFIX_ATK))
378                {
379                        if (sce) {
380                                clif_specialeffect(bl, 462, AREA);
381                                skill_blown(src,bl,sce->val3,-1,0);
382                        }
383                        //Both need to be consumed if they are active.
384                        if (sce && --(sce->val2) <= 0)
385                                status_change_end(bl, SC_UTSUSEMI, -1);
386                        if ((sce=sc->data[SC_BUNSINJYUTSU]) && --(sce->val2) <= 0)
387                                status_change_end(bl, SC_BUNSINJYUTSU, -1);
388                        return 0;
389                }
390
391                //Now damage increasing effects
392                if(sc->data[SC_AETERNA] && skill_num != PF_SOULBURN){
393                        damage<<=1;
394                        //Shouldn't end until Breaker's non-weapon part connects.
395                        if (skill_num != ASC_BREAKER || !(flag&BF_WEAPON))
396                                status_change_end( bl,SC_AETERNA,-1 );
397                }
398
399                //Finally damage reductions....
400                if(sc->data[SC_ASSUMPTIO]){
401                        if(map_flag_vs(bl->m))
402                                damage=damage*2/3; //Receive 66% damage
403                        else
404                                damage>>=1; //Receive 50% damage
405                }
406
407                if(sc->data[SC_DEFENDER] &&
408                        (flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON))
409                        damage=damage*(100-sc->data[SC_DEFENDER]->val2)/100;
410
411                if(sc->data[SC_ADJUSTMENT] &&
412                        (flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON))
413                        damage -= 20*damage/100;
414
415                if(sc->data[SC_FOGWALL]) {
416                        if(flag&BF_SKILL) //25% reduction
417                                damage -= 25*damage/100;
418                        else if ((flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON))
419                                damage >>= 2; //75% reduction
420                }
421
422                if((sce=sc->data[SC_ARMOR]) && //NPC_DEFENDER
423                        sce->val3&flag && sce->val4&flag)
424                        damage -= damage*sc->data[SC_ARMOR]->val2/100;
425
426                if(sc->data[SC_ENERGYCOAT] && flag&BF_WEAPON
427                        && skill_num != WS_CARTTERMINATION)
428                {
429                        struct status_data *status = status_get_status_data(bl);
430                        int per = 100*status->sp / status->max_sp -1; //100% should be counted as the 80~99% interval
431                        per /=20; //Uses 20% SP intervals.
432                        //SP Cost: 1% + 0.5% per every 20% SP
433                        if (!status_charge(bl, 0, (10+5*per)*status->max_sp/1000))
434                                status_change_end( bl,SC_ENERGYCOAT,-1 );
435                        //Reduction: 6% + 6% every 20%
436                        damage -= damage * 6 * (1+per) / 100;
437                }
438
439                if((sce=sc->data[SC_REJECTSWORD]) && flag&BF_WEAPON &&
440                        // Fixed the condition check [Aalye]
441                        (src->type!=BL_PC || (
442                                ((TBL_PC *)src)->status.weapon == W_DAGGER ||
443                                ((TBL_PC *)src)->status.weapon == W_1HSWORD ||
444                                ((TBL_PC *)src)->status.weapon == W_2HSWORD
445                        )) &&
446                        rand()%100 < sce->val2
447                ){
448                        damage = damage*50/100;
449                        status_fix_damage(bl,src,damage,clif_damage(bl,src,gettick(),0,0,damage,0,0,0));
450                        clif_skill_nodamage(bl,bl,ST_REJECTSWORD,sce->val1,1);
451                        if(--(sce->val3)<=0)
452                                status_change_end(bl, SC_REJECTSWORD, -1);
453                }
454
455                //Finally Kyrie because it may, or not, reduce damage to 0.
456                if((sce = sc->data[SC_KYRIE]) && damage > 0){
457                        sce->val2-=damage;
458                        if(flag&BF_WEAPON || skill_num == TF_THROWSTONE){
459                                if(sce->val2>=0)
460                                        damage=0;
461                                else
462                                        damage=-sce->val2;
463                        }
464                        if((--sce->val3)<=0 || (sce->val2<=0) || skill_num == AL_HOLYLIGHT)
465                                status_change_end(bl, SC_KYRIE, -1);
466                }
467
468                if (!damage) return 0;
469
470                //Probably not the most correct place, but it'll do here
471                //(since battle_drain is strictly for players currently)
472                if ((sce=sc->data[SC_BLOODLUST]) && flag&BF_WEAPON && damage > 0 &&
473                        rand()%100 < sce->val3)
474                        status_heal(src, damage*sce->val4/100, 0, 3);
475
476        }
477        //SC effects from caster side. Currently none.
478/*     
479        sc = status_get_sc(src);
480        if (sc && sc->count) {
481        }
482*/     
483        if (battle_config.pk_mode && sd && bl->type == BL_PC && damage)
484        {
485                if (flag & BF_SKILL) { //Skills get a different reduction than non-skills. [Skotlex]
486                        if (flag&BF_WEAPON)
487                                damage = damage * battle_config.pk_weapon_damage_rate/100;
488                        if (flag&BF_MAGIC)
489                                damage = damage * battle_config.pk_magic_damage_rate/100;
490                        if (flag&BF_MISC)
491                                damage = damage * battle_config.pk_misc_damage_rate/100;
492                } else { //Normal attacks get reductions based on range.
493                        if (flag & BF_SHORT)
494                                damage = damage * battle_config.pk_short_damage_rate/100;
495                        if (flag & BF_LONG)
496                                damage = damage * battle_config.pk_long_damage_rate/100;
497                }
498                if(!damage) damage  = 1;
499        }
500
501        if(battle_config.skill_min_damage && damage > 0 && damage < div_)
502        {
503                if ((flag&BF_WEAPON && battle_config.skill_min_damage&1)
504                        || (flag&BF_MAGIC && battle_config.skill_min_damage&2)
505                        || (flag&BF_MISC && battle_config.skill_min_damage&4)
506                )
507                        damage = div_;
508        }
509
510        if( bl->type == BL_MOB && !status_isdead(bl) && src != bl) {
511          if (damage > 0 )
512                        mobskill_event((TBL_MOB*)bl,src,gettick(),flag);
513          if (skill_num)
514                        mobskill_event((TBL_MOB*)bl,src,gettick(),MSC_SKILLUSED|(skill_num<<16));
515        }
516
517        return damage;
518}
519
520/*==========================================
521 * Calculates GVG related damage adjustments.
522 *------------------------------------------*/
523int battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int damage,int div_,int skill_num,int skill_lv,int flag)
524{
525        struct mob_data *md = NULL;
526        int class_;
527
528        if (!damage) //No reductions to make.
529                return 0;
530       
531        class_ = status_get_class(bl);
532
533        if (bl->type == BL_MOB)
534                md=(struct mob_data *)bl;
535       
536        if(md && md->guardian_data) {
537                if(class_ == MOBID_EMPERIUM && flag&BF_SKILL)
538                //Skill immunity.
539                        switch (skill_num) {
540                        case MO_TRIPLEATTACK:
541                        case HW_GRAVITATION:
542                                break;
543                        default:
544                                return 0;
545                }
546                if(src->type != BL_MOB) {
547                        struct guild *g=guild_search(status_get_guild_id(src));
548                        if (!g) return 0;
549                        if (class_ == MOBID_EMPERIUM && guild_checkskill(g,GD_APPROVAL) <= 0)
550                                return 0;
551                        if (battle_config.guild_max_castles &&
552                                guild_checkcastles(g)>=battle_config.guild_max_castles)
553                                return 0; // [MouseJstr]
554                }
555        }
556
557        switch (skill_num) {
558        //Skills with no damage reduction.
559        case PA_PRESSURE:
560        case HW_GRAVITATION:
561        case NJ_ZENYNAGE:
562                break;
563        default:
564                if (md && md->guardian_data) {
565                        damage -= damage * (md->guardian_data->castle->defense/100) * battle_config.castle_defense_rate/100;
566                }
567                if (flag & BF_SKILL) { //Skills get a different reduction than non-skills. [Skotlex]
568                        if (flag&BF_WEAPON)
569                                damage = damage * battle_config.gvg_weapon_damage_rate/100;
570                        if (flag&BF_MAGIC)
571                                damage = damage * battle_config.gvg_magic_damage_rate/100;
572                        if (flag&BF_MISC)
573                                damage = damage * battle_config.gvg_misc_damage_rate/100;
574                } else { //Normal attacks get reductions based on range.
575                        if (flag & BF_SHORT)
576                                damage = damage * battle_config.gvg_short_damage_rate/100;
577                        if (flag & BF_LONG)
578                                damage = damage * battle_config.gvg_long_damage_rate/100;
579                }
580                if(!damage) damage  = 1;
581        }
582        return damage;
583}
584
585/*==========================================
586 * HP/SP‹zŽû‚ÌŒvŽZ
587 *------------------------------------------*/
588static int battle_calc_drain(int damage, int rate, int per)
589{
590        int diff = 0;
591
592        if (per && rand()%1000 < rate) {
593                diff = (damage * per) / 100;
594                if (diff == 0) {
595                        if (per > 0)
596                                diff = 1;
597                        else
598                                diff = -1;
599                }
600        }
601        return diff;
602}
603
604/*==========================================
605 * ?C—ûƒ_E?[ƒW
606 *------------------------------------------*/
607int battle_addmastery(struct map_session_data *sd,struct block_list *target,int dmg,int type)
608{
609        int damage,skill;
610        struct status_data *status = status_get_status_data(target);
611        int weapon;
612        damage = dmg;
613
614        nullpo_retr(0, sd);
615
616        if((skill = pc_checkskill(sd,AL_DEMONBANE)) > 0 &&
617                (status->race==RC_UNDEAD || status->race==RC_DEMON) )
618                damage += (skill*(int)(3+(sd->status.base_level+1)*0.05));      // submitted by orn
619                //damage += (skill * 3);
620
621        if((skill = pc_checkskill(sd,HT_BEASTBANE)) > 0 && (status->race==RC_BRUTE || status->race==RC_INSECT) ) {
622                damage += (skill * 4);
623                if (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_HUNTER)
624                        damage += sd->status.str;
625        }
626
627        if(type == 0)
628                weapon = sd->weapontype1;
629        else
630                weapon = sd->weapontype2;
631        switch(weapon)
632        {
633                case W_DAGGER:
634                case W_1HSWORD:
635                        if((skill = pc_checkskill(sd,SM_SWORD)) > 0)
636                                damage += (skill * 4);
637                        break;
638                case W_2HSWORD:
639                        if((skill = pc_checkskill(sd,SM_TWOHAND)) > 0)
640                                damage += (skill * 4);
641                        break;
642                case W_1HSPEAR:
643                case W_2HSPEAR:
644                        if((skill = pc_checkskill(sd,KN_SPEARMASTERY)) > 0) {
645                                if(!pc_isriding(sd))
646                                        damage += (skill * 4);
647                                else
648                                        damage += (skill * 5);
649                        }
650                        break;
651                case W_1HAXE:
652                case W_2HAXE:
653                        if((skill = pc_checkskill(sd,AM_AXEMASTERY)) > 0)
654                                damage += (skill * 3);
655                        break;
656                case W_MACE:
657                case W_2HMACE:
658                        if((skill = pc_checkskill(sd,PR_MACEMASTERY)) > 0)
659                                damage += (skill * 3);
660                        break;
661                case W_FIST:
662                        if((skill = pc_checkskill(sd,TK_RUN)) > 0)
663                                damage += (skill * 10);
664                        // No break, fallthrough to Knuckles
665                case W_KNUCKLE:
666                        if((skill = pc_checkskill(sd,MO_IRONHAND)) > 0)
667                                damage += (skill * 3);
668                        break;
669                case W_MUSICAL:
670                        if((skill = pc_checkskill(sd,BA_MUSICALLESSON)) > 0)
671                                damage += (skill * 3);
672                        break;
673                case W_WHIP:
674                        if((skill = pc_checkskill(sd,DC_DANCINGLESSON)) > 0)
675                                damage += (skill * 3);
676                        break;
677                case W_BOOK:
678                        if((skill = pc_checkskill(sd,SA_ADVANCEDBOOK)) > 0)
679                                damage += (skill * 3);
680                        break;
681                case W_KATAR:
682                        if((skill = pc_checkskill(sd,AS_KATAR)) > 0)
683                                damage += (skill * 3);
684                        break;
685        }
686
687        return damage;
688}
689/*==========================================
690 * Calculates the standard damage of a normal attack assuming it hits,
691 * it calculates nothing extra fancy, is needed for magnum break's WATK_ELEMENT bonus. [Skotlex]
692 *------------------------------------------
693 * Pass damage2 as NULL to not calc it.
694 * Flag values:
695 * &1: Critical hit
696 * &2: Arrow attack
697 * &4: Skill is Magic Crasher
698 * &8: Skip target size adjustment (Extremity Fist?)
699 *&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)
700 */
701static 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)
702{
703        unsigned short atkmin=0, atkmax=0;
704        short type = 0;
705        int damage = 0;
706
707        if (!sd)
708        {       //Mobs/Pets
709                if(flag&4)
710                {                 
711                        atkmin = status->matk_min;
712                        atkmax = status->matk_max;
713                } else {
714                        atkmin = wa->atk;
715                        atkmax = wa->atk2;
716                }
717                if (atkmin > atkmax)
718                        atkmin = atkmax;
719        } else {        //PCs
720                atkmax = wa->atk;
721                type = (wa == &status->lhw)?EQI_HAND_L:EQI_HAND_R;
722
723                if (!(flag&1) || (flag&2))
724                {       //Normal attacks
725                        atkmin = status->dex;
726                       
727                        if (sd->equip_index[type] >= 0 && sd->inventory_data[sd->equip_index[type]])
728                                atkmin = atkmin*(80 + sd->inventory_data[sd->equip_index[type]]->wlv*20)/100;
729
730                        if (atkmin > atkmax)
731                                atkmin = atkmax;
732                       
733                        if(flag&2 && !(flag&16))
734                        {       //Bows
735                                atkmin = atkmin*atkmax/100;
736                                if (atkmin > atkmax)
737                                        atkmax = atkmin;
738                        }
739                }
740        }
741       
742        if (sc && sc->data[SC_MAXIMIZEPOWER])
743                atkmin = atkmax;
744       
745        //Weapon Damage calculation
746        if (!(flag&1))
747                damage = (atkmax>atkmin? rand()%(atkmax-atkmin):0)+atkmin;
748        else 
749                damage = atkmax;
750       
751        if (sd)
752        {
753                //rodatazone says the range is 0~arrow_atk-1 for non crit
754                if (flag&2 && sd->arrow_atk)
755                        damage += ((flag&1)?sd->arrow_atk:rand()%sd->arrow_atk);
756
757                //SizeFix only for players
758                if (!(sd->special_state.no_sizefix || (flag&8)))
759                        damage = damage*(type==EQI_HAND_L?
760                                sd->left_weapon.atkmods[t_size]:
761                                sd->right_weapon.atkmods[t_size])/100;
762        }
763       
764        //Finally, add baseatk
765        if(flag&4)
766                damage += status->matk_min;
767        else
768                damage += status->batk;
769       
770        //rodatazone says that Overrefine bonuses are part of baseatk
771        //Here we also apply the weapon_atk_rate bonus so it is correctly applied on left/right hands.
772        if(sd) {
773                if (type == EQI_HAND_L) {
774                        if(sd->left_weapon.overrefine)
775                                damage += rand()%sd->left_weapon.overrefine+1;
776                        if (sd->weapon_atk_rate[sd->weapontype2])
777                                damage += damage*sd->weapon_atk_rate[sd->weapontype2]/100;;
778                } else { //Right hand
779                        if(sd->right_weapon.overrefine)
780                                damage += rand()%sd->right_weapon.overrefine+1;
781                        if (sd->weapon_atk_rate[sd->weapontype1])
782                                damage += damage*sd->weapon_atk_rate[sd->weapontype1]/100;;
783                }
784        }
785        return damage;
786}
787
788/*==========================================
789 * Consumes ammo for the given skill.
790 *------------------------------------------*/
791void battle_consume_ammo(TBL_PC*sd, int skill, int lv)
792{
793        int qty=1;
794        if (!battle_config.arrow_decrement)
795                return;
796       
797        if (skill)
798        {
799                qty = skill_get_ammo_qty(skill, lv);
800                if (!qty) qty = 1;
801        }
802
803        if(sd->equip_index[EQI_AMMO]>=0) //Qty check should have been done in skill_check_condition
804                pc_delitem(sd,sd->equip_index[EQI_AMMO],qty,0);
805}
806
807static int battle_range_type(
808        struct block_list *src, struct block_list *target,
809        int skill_num, int skill_lv)
810{       //Skill Range Criteria
811        if (battle_config.skillrange_by_distance &&
812                (src->type&battle_config.skillrange_by_distance)
813        ) { //based on distance between src/target [Skotlex]
814                if (check_distance_bl(src, target, 5))
815                        return BF_SHORT;
816                return BF_LONG;
817        }
818        //based on used skill's range
819        if (skill_get_range2(src, skill_num, skill_lv) < 5)
820                return BF_SHORT;
821        return BF_LONG;
822}
823
824static int battle_blewcount_bonus(struct map_session_data *sd, int skill_num)
825{
826        int i;
827        if (!sd->skillblown[0].id)
828                return 0;
829        //Apply the bonus blewcount. [Skotlex]
830        for (i = 0; i < ARRAYLENGTH(sd->skillblown) && sd->skillblown[i].id; i++) {
831                if (sd->skillblown[i].id == skill_num)
832                        return sd->skillblown[i].val;
833        }
834        return 0;
835}
836
837struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list *target,int skill_num,int skill_lv,int mflag);
838struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *target,int skill_num,int skill_lv,int mflag);
839
840//For quick div adjustment.
841#define damage_div_fix(dmg, div) { if (div > 1) (dmg)*=div; else if (div < 0) (div)*=-1; }
842/*==========================================
843 * battle_calc_weapon_attack (by Skotlex)
844 *------------------------------------------*/
845static struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list *target,int skill_num,int skill_lv,int wflag)
846{
847        unsigned int skillratio = 100;  //Skill dmg modifiers.
848        short skill=0;
849        short s_ele, s_ele_, t_class;
850        int i, nk;
851
852        struct map_session_data *sd, *tsd;
853        struct Damage wd;
854        struct status_change *sc = status_get_sc(src);
855        struct status_change *tsc = status_get_sc(target);
856        struct status_data *sstatus = status_get_status_data(src);
857        struct status_data *tstatus = status_get_status_data(target);
858        struct {
859                unsigned hit : 1; //the attack Hit? (not a miss)
860                unsigned cri : 1;               //Critical hit
861                unsigned idef : 1;      //Ignore defense
862                unsigned idef2 : 1;     //Ignore defense (left weapon)
863                unsigned pdef : 2;      //Pierces defense (Investigate/Ice Pick)
864                unsigned pdef2 : 2;     //1: Use def+def2/100, 2: Use def+def2/50       
865                unsigned infdef : 1;    //Infinite defense (plants)
866                unsigned arrow : 1;     //Attack is arrow-based
867                unsigned rh : 1;                //Attack considers right hand (wd.damage)
868                unsigned lh : 1;                //Attack considers left hand (wd.damage2)
869                unsigned weapon : 1; //It's a weapon attack (consider VVS, and all that)
870        }       flag;   
871
872        memset(&wd,0,sizeof(wd));
873        memset(&flag,0,sizeof(flag));
874
875        if(src==NULL || target==NULL)
876        {
877                nullpo_info(NLP_MARK);
878                return wd;
879        }
880        //Initial flag
881        flag.rh=1;
882        flag.weapon=1;
883        flag.infdef=(tstatus->mode&MD_PLANT?1:0);
884
885        //Initial Values
886        wd.type=0; //Normal attack
887        wd.div_=skill_num?skill_get_num(skill_num,skill_lv):1;
888        wd.amotion=(skill_num && skill_get_inf(skill_num)&INF_GROUND_SKILL)?0:sstatus->amotion; //Amotion should be 0 for ground skills.
889        if(skill_num == KN_AUTOCOUNTER)
890                wd.amotion >>= 1;
891        wd.dmotion=tstatus->dmotion;
892        wd.blewcount=skill_get_blewcount(skill_num,skill_lv);
893        wd.flag = BF_WEAPON; //Initial Flag
894        wd.flag|= skill_num?BF_SKILL:BF_NORMAL;
895        wd.dmg_lv=ATK_DEF;      //This assumption simplifies the assignation later
896        nk = skill_get_nk(skill_num);
897        flag.hit        = nk&NK_IGNORE_FLEE?1:0;
898        flag.idef = flag.idef2 = nk&NK_IGNORE_DEF?1:0;
899
900        if (sc && !sc->count)
901                sc = NULL; //Skip checking as there are no status changes active.
902        if (tsc && !tsc->count)
903                tsc = NULL; //Skip checking as there are no status changes active.
904
905        sd = BL_CAST(BL_PC, src);
906        tsd = BL_CAST(BL_PC, target);
907
908        if(sd)
909                wd.blewcount += battle_blewcount_bonus(sd, skill_num);
910
911        //Set miscellaneous data that needs be filled regardless of hit/miss
912        if(
913                (sd && sd->state.arrow_atk) ||
914                (!sd && ((skill_num && skill_get_ammotype(skill_num)) || sstatus->rhw.range>3))
915        )
916                flag.arrow = 1;
917       
918        if(skill_num){
919                wd.flag |= battle_range_type(src, target, skill_num, skill_lv);
920                switch(skill_num)
921                {
922                        case MO_FINGEROFFENSIVE:
923                                if(sd) {
924                                        if (battle_config.finger_offensive_type)
925                                                wd.div_ = 1;
926                                        else
927                                                wd.div_ = sd->spiritball_old;
928                                }
929                                break;
930                        case HT_PHANTASMIC:
931                                //Since these do not consume ammo, they need to be explicitly set as arrow attacks.
932                                flag.arrow = 1;
933                                break;
934
935                        case CR_SHIELDBOOMERANG:
936                        case PA_SHIELDCHAIN:
937                                flag.weapon = 0;
938                                break;
939
940                        case KN_PIERCE:
941                                wd.div_= (wd.div_>0?tstatus->size+1:-(tstatus->size+1));
942                                break;
943
944                        case TF_DOUBLE: //For NPC used skill.
945                        case GS_CHAINACTION:
946                                wd.type = 0x08;
947                                break;
948                               
949                        case GS_GROUNDDRIFT:
950                        case KN_SPEARSTAB:
951                        case KN_BOWLINGBASH:
952                        case MO_BALKYOUNG:
953                        case TK_TURNKICK:
954                                wd.blewcount=0;
955                                break;
956
957                        case KN_AUTOCOUNTER:
958                                wd.flag=(wd.flag&~BF_SKILLMASK)|BF_NORMAL;
959                                break;
960
961                        case NPC_CRITICALSLASH:
962                                flag.cri = 1; //Always critical skill.
963                                break;
964                }
965        } else //Range for normal attacks.
966                wd.flag |= flag.arrow?BF_LONG:BF_SHORT;
967       
968        if (!skill_num && tstatus->flee2 && rand()%1000 < tstatus->flee2)
969        {       //Check for Lucky Dodge
970                wd.type=0x0b;
971                wd.dmg_lv=ATK_LUCKY;
972                if (wd.div_ < 0) wd.div_*=-1;
973                return wd;
974        }
975
976        t_class = status_get_class(target);
977        s_ele = s_ele_ = skill_get_ele(skill_num, skill_lv);
978        if (!skill_num || s_ele == -1) { //Take weapon's element
979                s_ele = sstatus->rhw.ele;
980                s_ele_ = sstatus->lhw.ele;
981                if (flag.arrow && sd && sd->arrow_ele)
982                        s_ele = sd->arrow_ele;
983        } else if (s_ele == -2) { //Use enchantment's element
984                s_ele = s_ele_ = status_get_attack_sc_element(src,sc);
985        }
986        if (skill_num == GS_GROUNDDRIFT)
987                s_ele = s_ele_ = wflag; //element comes in flag.
988
989        if(!skill_num)
990        {       //Skills ALWAYS use ONLY your right-hand weapon (tested on Aegis 10.2)
991                if (sd && sd->weapontype1 == 0 && sd->weapontype2 > 0)
992                {
993                        flag.rh=0;
994                        flag.lh=1;
995                }
996                if (sstatus->lhw.atk)
997                        flag.lh=1;
998        }
999
1000        //Check for critical
1001        if(!flag.cri && sstatus->cri &&
1002                (!skill_num ||
1003                skill_num == KN_AUTOCOUNTER ||
1004                skill_num == SN_SHARPSHOOTING ||
1005                skill_num == NJ_KIRIKAGE))
1006        {
1007                short cri = sstatus->cri;
1008                if (sd)
1009                {
1010                        cri+= sd->critaddrace[tstatus->race];
1011                        if(flag.arrow)
1012                                cri += sd->arrow_cri;
1013                        if(sd->status.weapon == W_KATAR)
1014                                cri <<=1;
1015                }
1016                //The official equation is *2, but that only applies when sd's do critical.
1017                //Therefore, we use the old value 3 on cases when an sd gets attacked by a mob
1018                cri -= tstatus->luk*(!sd&&tsd?3:2);
1019               
1020                if(tsc)
1021                {
1022                        if (tsc->data[SC_SLEEP])
1023                                cri <<=1;
1024                }
1025                switch (skill_num)
1026                {
1027                        case KN_AUTOCOUNTER:
1028                                if(battle_config.auto_counter_type &&
1029                                        (battle_config.auto_counter_type&src->type))
1030                                        flag.cri = 1;
1031                                else
1032                                        cri <<= 1;
1033                                break;
1034                        case SN_SHARPSHOOTING:
1035                                cri += 200;
1036                                break;
1037                        case NJ_KIRIKAGE:
1038                                cri += 250 + 50*skill_lv;
1039                                break;
1040                }
1041                if(tsd && tsd->critical_def)
1042                        cri = cri*(100-tsd->critical_def)/100;
1043                if (rand()%1000 < cri)
1044                        flag.cri= 1;
1045        }
1046        if (flag.cri)
1047        {
1048                wd.type = 0x0a;
1049                flag.idef = flag.idef2 = flag.hit = 1;
1050        } else {        //Check for Perfect Hit
1051                if(sd && sd->perfect_hit > 0 && rand()%100 < sd->perfect_hit)
1052                        flag.hit = 1;
1053                if (sc && sc->data[SC_FUSION]) {
1054                        flag.hit = 1; //SG_FUSION always hit [Komurka]
1055                        flag.idef = flag.idef2 = 1; //def ignore [Komurka]
1056                }
1057                if (skill_num && !flag.hit)
1058                        switch(skill_num)
1059                        {
1060                                case AS_SPLASHER:
1061                                        if (wflag) // Always hits the one exploding.
1062                                                break;
1063                                        flag.hit = 1;
1064                                        break;
1065                                case CR_SHIELDBOOMERANG:
1066                                        if (sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_CRUSADER)
1067                                                flag.hit = 1;
1068                                        break;
1069                                case 0:
1070                                        //If flag, this is splash damage from Baphomet Card and it always hits.
1071                                        if (wflag)
1072                                                flag.hit = 1;
1073                                        break;
1074                        }
1075                if (tsc && !flag.hit && tsc->opt1 && tsc->opt1 != OPT1_STONEWAIT)
1076                        flag.hit = 1;
1077        }
1078
1079        if (!flag.hit)
1080        {       //Hit/Flee calculation
1081                short
1082                        flee = tstatus->flee,
1083                        hitrate=80; //Default hitrate
1084
1085                if(battle_config.agi_penalty_type &&
1086                        battle_config.agi_penalty_target&target->type)
1087                {       
1088                        unsigned char attacker_count; //256 max targets should be a sane max
1089                        attacker_count = unit_counttargeted(target,battle_config.agi_penalty_count_lv);
1090                        if(attacker_count >= battle_config.agi_penalty_count)
1091                        {
1092                                if (battle_config.agi_penalty_type == 1)
1093                                        flee = (flee * (100 - (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num))/100;
1094                                else //asume type 2: absolute reduction
1095                                        flee -= (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num;
1096                                if(flee < 1) flee = 1;
1097                        }
1098                }
1099
1100                hitrate+= sstatus->hit - flee;
1101
1102                if(wd.flag&BF_LONG && !skill_num && //Fogwall's hit penalty is only for normal ranged attacks.
1103                        tsc && tsc->data[SC_FOGWALL])
1104                        hitrate -= 50;
1105
1106                if(sd && flag.arrow)
1107                        hitrate += sd->arrow_hit;
1108                if(skill_num)
1109                        switch(skill_num)
1110                {       //Hit skill modifiers
1111                        //It is proven that bonus is applied on final hitrate, not hit.
1112                        case SM_BASH:
1113                                hitrate += hitrate * 5 * skill_lv / 100;
1114                                break;
1115                        case SM_MAGNUM:
1116                                hitrate += hitrate * 10 * skill_lv / 100;
1117                                break;
1118                        case KN_AUTOCOUNTER:
1119                        case PA_SHIELDCHAIN:
1120                        case NPC_WATERATTACK:
1121                        case NPC_GROUNDATTACK:
1122                        case NPC_FIREATTACK:
1123                        case NPC_WINDATTACK:
1124                        case NPC_POISONATTACK:
1125                        case NPC_HOLYATTACK:
1126                        case NPC_DARKNESSATTACK:
1127                        case NPC_UNDEADATTACK:
1128                        case NPC_TELEKINESISATTACK:
1129                        case NPC_BLEEDING:
1130                                hitrate += hitrate * 20 / 100;
1131                                break;
1132                        case KN_PIERCE:
1133                                hitrate += hitrate * 5 * skill_lv / 100;
1134                                break;
1135                        case AS_SONICBLOW:
1136                                if(sd && pc_checkskill(sd,AS_SONICACCEL)>0)
1137                                        hitrate += hitrate * 50 / 100;
1138                                break;
1139                }
1140
1141                // Weaponry Research hidden bonus
1142                if (sd && (skill = pc_checkskill(sd,BS_WEAPONRESEARCH)) > 0)
1143                        hitrate += hitrate * ( 2 * skill ) / 100;
1144
1145                hitrate = cap_value(hitrate, battle_config.min_hitrate, battle_config.max_hitrate); 
1146
1147                if(rand()%100 >= hitrate)
1148                        wd.dmg_lv = ATK_FLEE;
1149                else
1150                        flag.hit = 1;
1151        }       //End hit/miss calculation
1152
1153        if (flag.hit && !flag.infdef) //No need to do the math for plants
1154        {       //Hitting attack
1155
1156//Assuming that 99% of the cases we will not need to check for the flag.rh... we don't.
1157//ATK_RATE scales the damage. 100 = no change. 50 is halved, 200 is doubled, etc
1158#define ATK_RATE( a ) { wd.damage= wd.damage*(a)/100 ; if(flag.lh) wd.damage2= wd.damage2*(a)/100; }
1159#define ATK_RATE2( a , b ) { wd.damage= wd.damage*(a)/100 ; if(flag.lh) wd.damage2= wd.damage2*(b)/100; }
1160//Adds dmg%. 100 = +100% (double) damage. 10 = +10% damage
1161#define ATK_ADDRATE( a ) { wd.damage+= wd.damage*(a)/100 ; if(flag.lh) wd.damage2+= wd.damage2*(a)/100; }
1162#define ATK_ADDRATE2( a , b ) { wd.damage+= wd.damage*(a)/100 ; if(flag.lh) wd.damage2+= wd.damage2*(b)/100; }
1163//Adds an absolute value to damage. 100 = +100 damage
1164#define ATK_ADD( a ) { wd.damage+= a; if (flag.lh) wd.damage2+= a; }
1165#define ATK_ADD2( a , b ) { wd.damage+= a; if (flag.lh) wd.damage2+= b; }
1166
1167                switch (skill_num)
1168                {       //Calc base damage according to skill
1169                        case NJ_ISSEN:
1170                                wd.damage = 40*sstatus->str +skill_lv*(sstatus->hp/10 + 35);
1171                                wd.damage2 = 0;
1172                                status_set_hp(src, 1, 0);
1173                                break;
1174                        case PA_SACRIFICE:
1175                                wd.damage = sstatus->max_hp* 9/100;
1176                                status_zap(src, wd.damage, 0);//Damage to self is always 9%
1177                                wd.damage2 = 0;
1178
1179                                if (sc && sc->data[SC_SACRIFICE])
1180                                {
1181                                        if (--sc->data[SC_SACRIFICE]->val2 <= 0)
1182                                                status_change_end(src, SC_SACRIFICE,-1);
1183                                }
1184                                break;
1185                        case LK_SPIRALPIERCE:
1186                                if (sd) {
1187                                        short index = sd->equip_index[EQI_HAND_R];
1188
1189                                        if (index >= 0 &&
1190                                                sd->inventory_data[index] &&
1191                                                sd->inventory_data[index]->type == IT_WEAPON)
1192                                                wd.damage = sd->inventory_data[index]->weight*8/100; //80% of weight
1193                                } else
1194                                        wd.damage = sstatus->rhw.atk2*8/10; //Else use Atk2
1195
1196                                ATK_ADDRATE(50*skill_lv); //Skill modifier applies to weight only.
1197                                i = sstatus->str/10;
1198                                i*=i;
1199                                ATK_ADD(i); //Add str bonus.
1200                                switch (tstatus->size) { //Size-fix. Is this modified by weapon perfection?
1201                                        case 0: //Small: 125%
1202                                                ATK_RATE(125);
1203                                                break;
1204                                        //case 1: //Medium: 100%
1205                                        case 2: //Large: 75%
1206                                                ATK_RATE(75);
1207                                                break;
1208                                }
1209                                break;
1210                        case CR_SHIELDBOOMERANG:
1211                        case PA_SHIELDCHAIN:
1212                                wd.damage = sstatus->batk;
1213                                if (sd) {
1214                                        short index = sd->equip_index[EQI_HAND_L];
1215
1216                                        if (index >= 0 &&
1217                                                sd->inventory_data[index] &&
1218                                                sd->inventory_data[index]->type == IT_ARMOR)
1219                                                ATK_ADD(sd->inventory_data[index]->weight/10);
1220                                        break;
1221                                } else
1222                                        ATK_ADD(sstatus->rhw.atk2); //Else use Atk2
1223                                break;
1224                        case HFLI_SBR44:        //[orn]
1225                                if(src->type == BL_HOM) {
1226                                        wd.damage = ((TBL_HOM*)src)->homunculus.intimacy ;
1227                                        break;
1228                                }
1229                        default:
1230                        {
1231                                i = (flag.cri?1:0)|
1232                                        (flag.arrow?2:0)|
1233                                        (skill_num == HW_MAGICCRASHER?4:0)|
1234                                        (!skill_num && sc && sc->data[SC_CHANGE]?4:0)|
1235                                        (skill_num == MO_EXTREMITYFIST?8:0)|
1236                                        (sc && sc->data[SC_WEAPONPERFECTION]?8:0);
1237                                if (flag.arrow && sd)
1238                                switch(sd->status.weapon) {
1239                                        case W_BOW:
1240                                        case W_REVOLVER:
1241                                        case W_GATLING:
1242                                        case W_SHOTGUN:
1243                                        case W_GRENADE:
1244                                                break;
1245                                        default:
1246                                                i |= 16; // for ex. shuriken must not be influenced by DEX
1247                                }
1248                                wd.damage = battle_calc_base_damage(sstatus, &sstatus->rhw, sc, tstatus->size, sd, i);
1249                                if (flag.lh)
1250                                        wd.damage2 = battle_calc_base_damage(sstatus, &sstatus->lhw, sc, tstatus->size, sd, i);
1251
1252                                if (nk&NK_SPLASHSPLIT){ // Divide ATK among targets
1253                                        if(wflag>0)
1254                                                wd.damage/= wflag;
1255                                        else
1256                                                ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_num, skill_get_name(skill_num));
1257                                }
1258
1259                                //Add any bonuses that modify the base baseatk+watk (pre-skills)
1260                                if(sd)
1261                                {
1262                                        if (sd->atk_rate != 100)
1263                                                ATK_RATE(sd->atk_rate);
1264
1265                                        if(flag.cri && sd->crit_atk_rate)
1266                                                ATK_ADDRATE(sd->crit_atk_rate);
1267
1268                                        if(sd->status.party_id && (skill=pc_checkskill(sd,TK_POWER)) > 0){
1269                                                i = party_foreachsamemap(party_sub_count, sd, 0);
1270                                                ATK_ADDRATE(2*skill*i);
1271                                        }
1272                                }
1273                                break;
1274                        }       //End default case
1275                } //End switch(skill_num)
1276
1277                //Skill damage modifiers that stack linearly
1278                if(sc && skill_num != PA_SACRIFICE)
1279                {
1280                        if(sc->data[SC_OVERTHRUST])
1281                                skillratio += sc->data[SC_OVERTHRUST]->val3;
1282                        if(sc->data[SC_MAXOVERTHRUST])
1283                                skillratio += sc->data[SC_MAXOVERTHRUST]->val2;
1284                        if(sc->data[SC_BERSERK])
1285                                skillratio += 100;
1286                }
1287                if (!skill_num)
1288                {
1289                        // Random chance to deal multiplied damage - Consider it as part of skill-based-damage
1290                        if(sd &&
1291                                sd->random_attack_increase_add > 0 &&
1292                                sd->random_attack_increase_per &&
1293                                rand()%100 < sd->random_attack_increase_per
1294                                )
1295                                skillratio += sd->random_attack_increase_add;
1296               
1297                        ATK_RATE(skillratio);
1298                } else {        //Skills
1299                        switch( skill_num )
1300                        {
1301                                case SM_BASH:
1302                                        skillratio += 30*skill_lv;
1303                                        break;
1304                                case SM_MAGNUM:
1305                                        skillratio += 20*skill_lv; 
1306                                        break;
1307                                case MC_MAMMONITE:
1308                                        skillratio += 50*skill_lv;
1309                                        break;
1310                                case HT_POWER: //FIXME: How exactly is the STR based damage supposed to be done? [Skotlex]
1311                                        skillratio += 5*sstatus->str;
1312                                        break;
1313                                case AC_DOUBLE:
1314                                        skillratio += 10*(skill_lv-1);
1315                                        break;
1316                                case AC_SHOWER:
1317                                        skillratio += 5*skill_lv-25;
1318                                        break;
1319                                case AC_CHARGEARROW:
1320                                        skillratio += 50;
1321                                        break;
1322                                case HT_FREEZINGTRAP:
1323                                        skillratio += -50+10*skill_lv;
1324                                        break;
1325                                case KN_PIERCE:
1326                                        skillratio += 10*skill_lv;
1327                                        break;
1328                                case KN_SPEARSTAB:
1329                                        skillratio += 15*skill_lv;
1330                                        break;
1331                                case KN_SPEARBOOMERANG:
1332                                        skillratio += 50*skill_lv;
1333                                        break;
1334                                case KN_BRANDISHSPEAR:
1335                                {
1336                                        int ratio = 100+20*skill_lv;
1337                                        skillratio += ratio-100;
1338                                        if(skill_lv>3 && wflag==1) skillratio += ratio/2;
1339                                        if(skill_lv>6 && wflag==1) skillratio += ratio/4;
1340                                        if(skill_lv>9 && wflag==1) skillratio += ratio/8;
1341                                        if(skill_lv>6 && wflag==2) skillratio += ratio/2;
1342                                        if(skill_lv>9 && wflag==2) skillratio += ratio/4;
1343                                        if(skill_lv>9 && wflag==3) skillratio += ratio/2;
1344                                        break;
1345                                }
1346                                case KN_BOWLINGBASH:
1347                                        skillratio+= 40*skill_lv;
1348                                        break;
1349                                case AS_GRIMTOOTH:
1350                                        skillratio += 20*skill_lv;
1351                                        break;
1352                                case AS_POISONREACT:
1353                                        skillratio += 30*skill_lv;
1354                                        break;
1355                                case AS_SONICBLOW:
1356                                        skillratio += -50+5*skill_lv;
1357                                        break;
1358                                case TF_SPRINKLESAND:
1359                                        skillratio += 30;
1360                                        break;
1361                                case MC_CARTREVOLUTION:
1362                                        skillratio += 50;
1363                                        if(sd && sd->cart_weight)
1364                                                skillratio += 100*sd->cart_weight/battle_config.max_cart_weight; // +1% every 1% weight
1365                                        else if (!sd)
1366                                                skillratio += 100; //Max damage for non players.
1367                                        break;
1368                                case NPC_RANDOMATTACK:
1369                                        skillratio += rand()%150-50;
1370                                        break;
1371                                case NPC_WATERATTACK:
1372                                case NPC_GROUNDATTACK:
1373                                case NPC_FIREATTACK:
1374                                case NPC_WINDATTACK:
1375                                case NPC_POISONATTACK:
1376                                case NPC_HOLYATTACK:
1377                                case NPC_DARKNESSATTACK:
1378                                case NPC_UNDEADATTACK:
1379                                case NPC_TELEKINESISATTACK:
1380                                case NPC_BLOODDRAIN:
1381                                case NPC_ACIDBREATH:
1382                                case NPC_DARKNESSBREATH:
1383                                case NPC_FIREBREATH:
1384                                case NPC_ICEBREATH:
1385                                case NPC_THUNDERBREATH:
1386                                case NPC_HELLJUDGEMENT:
1387                                case NPC_PULSESTRIKE:
1388                                        skillratio += 100*(skill_lv-1);
1389                                        break;
1390                                case RG_BACKSTAP:
1391                                        if(sd && sd->status.weapon == W_BOW && battle_config.backstab_bow_penalty)
1392                                                skillratio += (200+40*skill_lv)/2;
1393                                        else
1394                                                skillratio += 200+40*skill_lv;
1395                                        break;
1396                                case RG_RAID:
1397                                        skillratio += 40*skill_lv;
1398                                        break;
1399                                case RG_INTIMIDATE:
1400                                        skillratio += 30*skill_lv;
1401                                        break;
1402                                case CR_SHIELDCHARGE:
1403                                        skillratio += 20*skill_lv;
1404                                        break;
1405                                case CR_SHIELDBOOMERANG:
1406                                        skillratio += 30*skill_lv;
1407                                        break;
1408                                case NPC_DARKCROSS:
1409                                case CR_HOLYCROSS:
1410                                        skillratio += 35*skill_lv;
1411                                        break;
1412                                case AM_DEMONSTRATION:
1413                                        skillratio += 20*skill_lv;
1414                                        break;
1415                                case AM_ACIDTERROR:
1416                                        skillratio += 40*skill_lv;
1417                                        break;
1418                                case MO_FINGEROFFENSIVE:
1419                                        skillratio+= 50 * skill_lv;
1420                                        break;
1421                                case MO_INVESTIGATE:
1422                                        skillratio += 75*skill_lv;
1423                                        flag.pdef = flag.pdef2 = 2;
1424                                        break;
1425                                case MO_EXTREMITYFIST:
1426                                        {       //Overflow check. [Skotlex]
1427                                                unsigned int ratio = skillratio + 100*(8 + sstatus->sp/10);
1428                                                //You'd need something like 6K SP to reach this max, so should be fine for most purposes.
1429                                                if (ratio > 60000) ratio = 60000; //We leave some room here in case skillratio gets further increased.
1430                                                skillratio = (unsigned short)ratio;
1431                                                status_set_sp(src, 0, 0);
1432                                        }
1433                                        break;
1434                                case MO_TRIPLEATTACK:
1435                                        skillratio += 20*skill_lv;
1436                                        break;
1437                                case MO_CHAINCOMBO:
1438                                        skillratio += 50+50*skill_lv;
1439                                        break;
1440                                case MO_COMBOFINISH:
1441                                        skillratio += 140+60*skill_lv;
1442                                        break;
1443                                case BA_MUSICALSTRIKE:
1444                                case DC_THROWARROW:
1445                                        skillratio += 25+25*skill_lv;
1446                                        break;
1447                                case CH_TIGERFIST:
1448                                        skillratio += 100*skill_lv-60;
1449                                        break;
1450                                case CH_CHAINCRUSH:
1451                                        skillratio += 300+100*skill_lv;
1452                                        break;
1453                                case CH_PALMSTRIKE:
1454                                        skillratio += 100+100*skill_lv;
1455                                        break;
1456                                case LK_HEADCRUSH:
1457                                        skillratio += 40*skill_lv;
1458                                        break;
1459                                case LK_JOINTBEAT:
1460                                        i = 10*skill_lv-50;
1461                                        // Although not clear, it's being assumed that the 2x damage is only for the break neck ailment.
1462                                        if (wflag&BREAK_NECK) i*=2;
1463                                        skillratio += i;
1464                                        break;
1465                                case ASC_METEORASSAULT:
1466                                        skillratio += 40*skill_lv-60;
1467                                        break;
1468                                case SN_SHARPSHOOTING:
1469                                        skillratio += 100+50*skill_lv;
1470                                        break;
1471                                case CG_ARROWVULCAN:
1472                                        skillratio += 100+100*skill_lv;
1473                                        break;
1474                                case AS_SPLASHER:
1475                                        skillratio += 400+50*skill_lv;
1476                                        if(sd)
1477                                                skillratio += 30 * pc_checkskill(sd,AS_POISONREACT);
1478                                        break;
1479                                case ASC_BREAKER:
1480                                        skillratio += 100*skill_lv-100;
1481                                        break;
1482                                case PA_SACRIFICE:
1483                                        skillratio += 10*skill_lv-10;
1484                                        break;
1485                                case PA_SHIELDCHAIN:
1486                                        skillratio += 30*skill_lv;
1487                                        break;
1488                                case WS_CARTTERMINATION:
1489                                        i = 10 * (16 - skill_lv);
1490                                        if (i < 1) i = 1;
1491                                        //Preserve damage ratio when max cart weight is changed.
1492                                        if(sd && sd->cart_weight)
1493                                                skillratio += sd->cart_weight/i * 80000/battle_config.max_cart_weight - 100;
1494                                        else if (!sd)
1495                                                skillratio += 80000 / i - 100;
1496                                        break;
1497                                case TK_DOWNKICK:
1498                                        skillratio += 60 + 20*skill_lv;
1499                                        break;
1500                                case TK_STORMKICK:
1501                                        skillratio += 60 + 20*skill_lv;
1502                                        break;
1503                                case TK_TURNKICK:
1504                                        skillratio += 90 + 30*skill_lv;
1505                                        break;
1506                                case TK_COUNTER:
1507                                        skillratio += 90 + 30*skill_lv;
1508                                        break;
1509                                case TK_JUMPKICK:
1510                                        skillratio += -70 + 10*skill_lv;
1511                                        if (sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == skill_num)
1512                                                skillratio += 10*status_get_lv(src)/3; //Tumble bonus
1513                                        if (wflag)
1514                                                skillratio += 10*status_get_lv(src)/3; //Running bonus (TODO: What is the real bonus?)
1515                                        break;
1516                                case GS_TRIPLEACTION:
1517                                        skillratio += 50*skill_lv;
1518                                        break;
1519                                case GS_BULLSEYE:
1520                                        //Only works well against brute/demihumans non bosses.
1521                                        if((tstatus->race == RC_BRUTE || tstatus->race == RC_DEMIHUMAN)
1522                                                && !(tstatus->mode&MD_BOSS))
1523                                                skillratio += 400;
1524                                        break;
1525                                case GS_TRACKING:
1526                                        skillratio += 100 *(skill_lv+1);
1527                                        break;
1528                                case GS_PIERCINGSHOT:
1529                                        skillratio += 20*skill_lv;
1530                                        break;
1531                                case GS_RAPIDSHOWER:
1532                                        skillratio += 10*skill_lv;
1533                                        break;
1534                                case GS_DESPERADO:
1535                                        skillratio += 50*(skill_lv-1);
1536                                        break;
1537                                case GS_DUST:
1538                                        skillratio += 50*skill_lv;
1539                                        break;
1540                                case GS_FULLBUSTER:
1541                                        skillratio += 100*(skill_lv+2);
1542                                        break;
1543                                case GS_SPREADATTACK:
1544                                        skillratio += 20*(skill_lv-1);
1545                                        break;
1546                                case NJ_HUUMA:
1547                                        skillratio += 50 + 150*skill_lv;
1548                                        break;
1549                                case NJ_TATAMIGAESHI:
1550                                        skillratio += 10*skill_lv;
1551                                        break;
1552                                case NJ_KASUMIKIRI:
1553                                        skillratio += 10*skill_lv;
1554                                        break;
1555                                case NJ_KIRIKAGE:
1556                                        skillratio += 100*(skill_lv-1);
1557                                        break;
1558                                case KN_CHARGEATK:
1559                                        {
1560                                        int k = (wflag-1)/3; //+100% every 3 cells of distance
1561                                        if( k > 2 ) k = 2; // ...but hard-limited to 300%.
1562                                        skillratio += 100 * k; 
1563                                        }
1564                                        break;
1565                                case HT_PHANTASMIC:
1566                                        skillratio += 50;
1567                                        break;
1568                                case MO_BALKYOUNG:
1569                                        skillratio += 200;
1570                                        break;
1571                                case HFLI_MOON: //[orn]
1572                                        skillratio += 10+110*skill_lv;
1573                                        break;
1574                                case HFLI_SBR44:        //[orn]
1575                                        skillratio += 100 *(skill_lv-1);
1576                                        break;
1577                        }
1578
1579                        ATK_RATE(skillratio);
1580
1581                        //Constant/misc additions from skills
1582                        switch (skill_num) {
1583                                case MO_EXTREMITYFIST:
1584                                        ATK_ADD(250 + 150*skill_lv);
1585                                        break;
1586                                case TK_DOWNKICK:
1587                                case TK_STORMKICK:
1588                                case TK_TURNKICK:
1589                                case TK_COUNTER:
1590                                case TK_JUMPKICK:
1591                                        //TK_RUN kick damage bonus.
1592                                        if(sd && sd->weapontype1 == W_FIST && sd->weapontype2 == W_FIST)
1593                                                ATK_ADD(10*pc_checkskill(sd, TK_RUN));
1594                                        break;
1595                                case GS_MAGICALBULLET:
1596                                        if(sstatus->matk_max>sstatus->matk_min) {
1597                                                ATK_ADD(sstatus->matk_min+rand()%(sstatus->matk_max-sstatus->matk_min));
1598                                        } else {
1599                                                ATK_ADD(sstatus->matk_min);
1600                                        }
1601                                        break;
1602                                case NJ_SYURIKEN:
1603                                        ATK_ADD(4*skill_lv);
1604                                        break;
1605                        }
1606                }
1607                //Div fix.
1608                damage_div_fix(wd.damage, wd.div_);
1609
1610                //The following are applied on top of current damage and are stackable.
1611                if (sc) {
1612                        if(sc->data[SC_TRUESIGHT])
1613                                ATK_ADDRATE(2*sc->data[SC_TRUESIGHT]->val1);
1614
1615                        if(sc->data[SC_EDP] &&
1616                                skill_num != ASC_BREAKER &&
1617                                skill_num != ASC_METEORASSAULT &&
1618                                skill_num != AS_SPLASHER &&
1619                                skill_num != AS_VENOMKNIFE)
1620                                ATK_ADDRATE(sc->data[SC_EDP]->val3);
1621                }
1622
1623                switch (skill_num) {
1624                        case AS_SONICBLOW:
1625                                if (sc && sc->data[SC_SPIRIT] &&
1626                                        sc->data[SC_SPIRIT]->val2 == SL_ASSASIN)
1627                                        ATK_ADDRATE(map_flag_gvg(src->m)?25:100); //+25% dmg on woe/+100% dmg on nonwoe
1628
1629                                if(sd && pc_checkskill(sd,AS_SONICACCEL)>0)
1630                                        ATK_ADDRATE(10);
1631                        break;
1632                        case CR_SHIELDBOOMERANG:
1633                                if(sc && sc->data[SC_SPIRIT] &&
1634                                        sc->data[SC_SPIRIT]->val2 == SL_CRUSADER)
1635                                        ATK_ADDRATE(100);
1636                                break;
1637                }
1638               
1639                if(sd)
1640                {
1641                        if (skill_num && (i = pc_skillatk_bonus(sd, skill_num)))
1642                                ATK_ADDRATE(i);
1643
1644                        if(skill_num != PA_SACRIFICE && skill_num != MO_INVESTIGATE &&
1645                                skill_num != CR_GRANDCROSS && skill_num != NPC_GRANDDARKNESS &&
1646                                skill_num != PA_SHIELDCHAIN
1647                                && !flag.cri)
1648                        {       //Elemental/Racial adjustments
1649                                if(sd->right_weapon.def_ratio_atk_ele & (1<<tstatus->def_ele) ||
1650                                        sd->right_weapon.def_ratio_atk_race & (1<<tstatus->race) ||
1651                                        sd->right_weapon.def_ratio_atk_race & (1<<(is_boss(target)?RC_BOSS:RC_NONBOSS))
1652                                )
1653                                        flag.pdef = 1;
1654
1655                                if(sd->left_weapon.def_ratio_atk_ele & (1<<tstatus->def_ele) ||
1656                                        sd->left_weapon.def_ratio_atk_race & (1<<tstatus->race) ||
1657                                        sd->left_weapon.def_ratio_atk_race & (1<<(is_boss(target)?RC_BOSS:RC_NONBOSS))
1658                                ) {     //Pass effect onto right hand if configured so. [Skotlex]
1659                                        if (battle_config.left_cardfix_to_right && flag.rh)
1660                                                flag.pdef = 1;
1661                                        else
1662                                                flag.pdef2 = 1;
1663                                }
1664                        }
1665
1666                        if (skill_num != CR_GRANDCROSS && skill_num != NPC_GRANDDARKNESS)
1667                        {       //Ignore Defense?
1668                                if (!flag.idef && (
1669                                        sd->right_weapon.ignore_def_ele & (1<<tstatus->def_ele) ||
1670                                        sd->right_weapon.ignore_def_race & (1<<tstatus->race) ||
1671                                        sd->right_weapon.ignore_def_race & (is_boss(target)?1<<RC_BOSS:1<<RC_NONBOSS)
1672                                ))
1673                                        flag.idef = 1;
1674
1675                                if (!flag.idef2 && (
1676                                        sd->left_weapon.ignore_def_ele & (1<<tstatus->def_ele) ||
1677                                        sd->left_weapon.ignore_def_race & (1<<tstatus->race) ||
1678                                        sd->left_weapon.ignore_def_race & (is_boss(target)?1<<RC_BOSS:1<<RC_NONBOSS)
1679                                )) {
1680                                                if(battle_config.left_cardfix_to_right && flag.rh) //Move effect to right hand. [Skotlex]
1681                                                        flag.idef = 1;
1682                                                else
1683                                                        flag.idef2 = 1;
1684                                }
1685                        }
1686                }
1687
1688                if (!flag.idef || !flag.idef2)
1689                {       //Defense reduction
1690                        short vit_def;
1691                        signed char def1 = status_get_def(target); //Don't use tstatus->def1 due to skill timer reductions.
1692                        short def2 = (short)tstatus->def2;
1693                        if(battle_config.vit_penalty_type &&
1694                                battle_config.vit_penalty_target&target->type)
1695                        {
1696                                unsigned char target_count; //256 max targets should be a sane max
1697                                target_count = unit_counttargeted(target,battle_config.vit_penalty_count_lv);
1698                                if(target_count >= battle_config.vit_penalty_count) {
1699                                        if(battle_config.vit_penalty_type == 1) {
1700                                                def1 = (def1 * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100;
1701                                                def2 = (def2 * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100;
1702                                        } else { //Assume type 2
1703                                                def1 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num;
1704                                                def2 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num;
1705                                        }
1706                                }
1707                                if(skill_num == AM_ACIDTERROR) def1 = 0; //Acid Terror ignores only armor defense. [Skotlex]
1708                                if(def2 < 1) def2 = 1;
1709                        }
1710                        //Vitality reduction from rodatazone: http://rodatazone.simgaming.net/mechanics/substats.php#def       
1711                        if (tsd)        //Sd vit-eq
1712                        {       //[VIT*0.5] + rnd([VIT*0.3], max([VIT*0.3],[VIT^2/150]-1))
1713                                vit_def = def2*(def2-15)/150;
1714                                vit_def = def2/2 + (vit_def>0?rand()%vit_def:0);
1715                               
1716                                if((sstatus->race==RC_UNDEAD || sstatus->race==RC_DEMON) &&
1717                                        src->type == BL_MOB && (skill=pc_checkskill(tsd,AL_DP)) > 0)
1718                                        vit_def += skill*(int)(3 +(tsd->status.base_level+1)*0.04);   // submitted by orn
1719                        } else { //Mob-Pet vit-eq
1720                                //VIT + rnd(0,[VIT/20]^2-1)
1721                                vit_def = (def2/20)*(def2/20);
1722                                vit_def = def2 + (vit_def>0?rand()%vit_def:0);
1723                        }
1724                       
1725                        if (battle_config.weapon_defense_type) {
1726                                vit_def += def1*battle_config.weapon_defense_type;
1727                                def1 = 0;
1728                        }
1729                        if (def1 > 100) def1 = 100;
1730                        ATK_RATE2(
1731                                flag.idef ?100:
1732                                (flag.pdef ?flag.pdef *(def1 + vit_def):
1733                                100-def1),
1734                                flag.idef2?100:
1735                                (flag.pdef2?flag.pdef2*(def1 + vit_def):
1736                                100-def1)
1737                        );
1738                        ATK_ADD2(
1739                                flag.idef ||flag.pdef ?0:-vit_def,
1740                                flag.idef2||flag.pdef2?0:-vit_def
1741                        );
1742                }
1743
1744                //Post skill/vit reduction damage increases
1745                if (sc && skill_num != LK_SPIRALPIERCE)
1746                {       //SC skill damages
1747                        if(sc->data[SC_AURABLADE]) 
1748                                ATK_ADD(20*sc->data[SC_AURABLADE]->val1);
1749                }
1750
1751                //Refine bonus
1752                if (sd && flag.weapon && skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST) {
1753                        if (skill_num == MO_FINGEROFFENSIVE) //Counts refine bonus multiple times
1754                        {
1755                                ATK_ADD2(wd.div_*sstatus->rhw.atk2, wd.div_*sstatus->lhw.atk2);
1756                        } else {
1757                                ATK_ADD2(sstatus->rhw.atk2, sstatus->lhw.atk2);
1758                        }
1759                }
1760
1761                //Set to min of 1
1762                if (flag.rh && wd.damage < 1) wd.damage = 1;
1763                if (flag.lh && wd.damage2 < 1) wd.damage2 = 1;
1764
1765                if (sd && flag.weapon &&
1766                        skill_num != MO_INVESTIGATE &&
1767                        skill_num != MO_EXTREMITYFIST &&
1768                        skill_num != CR_GRANDCROSS)
1769                {       //Add mastery damage
1770                        if(skill_num != ASC_BREAKER && sd->status.weapon == W_KATAR &&
1771                                (skill=pc_checkskill(sd,ASC_KATAR)) > 0)
1772                        {       //Adv Katar Mastery is does not applies to ASC_BREAKER,
1773                                // but other masteries DO apply >_>
1774                                ATK_ADDRATE(10+ 2*skill);
1775                        }
1776
1777                        wd.damage = battle_addmastery(sd,target,wd.damage,0);
1778                        if (flag.lh)
1779                                wd.damage2 = battle_addmastery(sd,target,wd.damage2,1);
1780
1781                        if (sc && sc->data[SC_MIRACLE]) i = 2; //Star anger
1782                        else
1783                        ARR_FIND(0, 3, i, t_class == sd->hate_mob[i]);
1784                        if (i < 3 && (skill=pc_checkskill(sd,sg_info[i].anger_id))) 
1785                        {
1786                                skillratio = sd->status.base_level + sstatus->dex + sstatus->luk;
1787                                if (i == 2) skillratio += sstatus->str; //Star Anger
1788                                if (skill<4)
1789                                        skillratio /= 12-3*skill;
1790                                ATK_ADDRATE(skillratio);
1791                        }
1792                        if (skill_num == NJ_SYURIKEN && (skill = pc_checkskill(sd,NJ_TOBIDOUGU)) > 0)
1793                                ATK_ADD(3*skill);
1794                        if (skill_num == NJ_KUNAI)
1795                                ATK_ADD(60);
1796                }
1797        } //Here ends flag.hit section, the rest of the function applies to both hitting and missing attacks
1798        else if(wd.div_ < 0) //Since the attack missed...
1799                wd.div_ *= -1; 
1800
1801        if(skill_num == CR_GRANDCROSS || skill_num == NPC_GRANDDARKNESS)
1802                return wd; //Enough, rest is not needed.
1803
1804        if(sd && (skill=pc_checkskill(sd,BS_WEAPONRESEARCH)) > 0) 
1805                ATK_ADD(skill*2);
1806
1807        if(skill_num==TF_POISON)
1808                ATK_ADD(15*skill_lv);
1809
1810        if(!(nk&NK_NO_ELEFIX || (s_ele == ELE_NEUTRAL &&
1811                battle_config.attack_attr_none&src->type)))
1812        {       //Elemental attribute fix
1813                if (wd.damage > 0)
1814                {
1815                        wd.damage=battle_attr_fix(src,target,wd.damage,s_ele,tstatus->def_ele, tstatus->ele_lv);
1816                        if(skill_num==MC_CARTREVOLUTION) //Cart Revolution applies the element fix once more with neutral element
1817                                wd.damage = battle_attr_fix(src,target,wd.damage,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv);
1818                        if(skill_num== GS_GROUNDDRIFT) //Additional 50*lv Neutral damage.
1819                                wd.damage+= battle_attr_fix(src,target,50*skill_lv,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv);
1820                }
1821                if (flag.lh && wd.damage2 > 0)
1822                        wd.damage2 = battle_attr_fix(src,target,wd.damage2,s_ele_,tstatus->def_ele, tstatus->ele_lv);
1823                if(sc && sc->data[SC_WATK_ELEMENT])
1824                {       //Descriptions indicate this means adding a percent of a normal attack in another element. [Skotlex]
1825                        int damage= battle_calc_base_damage(sstatus, &sstatus->rhw, sc, tstatus->size, sd, (flag.arrow?2:0));
1826                        damage = damage*sc->data[SC_WATK_ELEMENT]->val2/100;
1827                        damage = battle_attr_fix(src,target,damage,sc->data[SC_WATK_ELEMENT]->val1,tstatus->def_ele, tstatus->ele_lv);
1828                        ATK_ADD(damage);
1829                }
1830        }
1831
1832        if (sd)
1833        {
1834                if (skill_num != CR_SHIELDBOOMERANG) //Only Shield boomerang doesn't takes the Star Crumbs bonus.
1835                        ATK_ADD2(wd.div_*sd->right_weapon.star, wd.div_*sd->left_weapon.star);
1836                if (skill_num==MO_FINGEROFFENSIVE) { //The finger offensive spheres on moment of attack do count. [Skotlex]
1837                        ATK_ADD(wd.div_*sd->spiritball_old*3);
1838                } else {
1839                        ATK_ADD(wd.div_*sd->spiritball*3);
1840                }
1841
1842                //Card Fix, sd side
1843                if ((wd.damage || wd.damage2) && !(nk&NK_NO_CARDFIX_ATK))
1844                {
1845                        int cardfix = 1000, cardfix_ = 1000;
1846                        int t_race2 = status_get_race2(target); 
1847                        if(sd->state.arrow_atk)
1848                        {
1849                                cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race]+sd->arrow_addrace[tstatus->race])/100;
1850                                if (!(nk&NK_NO_ELEFIX))
1851                                        cardfix=cardfix*(100+sd->right_weapon.addele[tstatus->def_ele]+sd->arrow_addele[tstatus->def_ele])/100;
1852                                cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size]+sd->arrow_addsize[tstatus->size])/100;
1853                                cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2])/100;
1854                                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;
1855                        } else {        //Melee attack
1856                                if(!battle_config.left_cardfix_to_right)
1857                                {
1858                                        cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race])/100;
1859                                        if (!(nk&NK_NO_ELEFIX))
1860                                                cardfix=cardfix*(100+sd->right_weapon.addele[tstatus->def_ele])/100;
1861                                        cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size])/100;
1862                                        cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2])/100;
1863                                        cardfix=cardfix*(100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100;
1864
1865                                        if (flag.lh)
1866                                        {
1867                                                cardfix_=cardfix_*(100+sd->left_weapon.addrace[tstatus->race])/100;
1868                                                if (!(nk&NK_NO_ELEFIX))
1869                                                        cardfix_=cardfix_*(100+sd->left_weapon.addele[tstatus->def_ele])/100;
1870                                                cardfix_=cardfix_*(100+sd->left_weapon.addsize[tstatus->size])/100;
1871                                                cardfix_=cardfix_*(100+sd->left_weapon.addrace2[t_race2])/100;
1872                                                cardfix_=cardfix_*(100+sd->left_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100;
1873                                        }
1874                                } else {
1875                                        cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race]+sd->left_weapon.addrace[tstatus->race])/100;
1876                                        cardfix=cardfix*(100+sd->right_weapon.addele[tstatus->def_ele]+sd->left_weapon.addele[tstatus->def_ele])/100;
1877                                        cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size]+sd->left_weapon.addsize[tstatus->size])/100;
1878                                        cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2]+sd->left_weapon.addrace2[t_race2])/100;
1879                                        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;
1880                                }
1881                        }
1882
1883                        for(i=0;i<ARRAYLENGTH(sd->right_weapon.add_dmg) && sd->right_weapon.add_dmg[i].rate;i++) {
1884                                if(sd->right_weapon.add_dmg[i].class_ == t_class) {
1885                                        cardfix=cardfix*(100+sd->right_weapon.add_dmg[i].rate)/100;
1886                                        break;
1887                                }
1888                        }
1889
1890                        if (flag.lh)
1891                        {
1892                                for(i=0;i<ARRAYLENGTH(sd->left_weapon.add_dmg) && sd->left_weapon.add_dmg[i].rate;i++) {
1893                                        if(sd->left_weapon.add_dmg[i].class_ == t_class) {
1894                                                cardfix_=cardfix_*(100+sd->left_weapon.add_dmg[i].rate)/100;
1895                                                break;
1896                                        }
1897                                }
1898                        }
1899
1900                        if(wd.flag&BF_LONG)
1901                                cardfix=cardfix*(100+sd->long_attack_atk_rate)/100;
1902
1903                        if (cardfix != 1000 || cardfix_ != 1000)
1904                                ATK_RATE2(cardfix/10, cardfix_/10);     //What happens if you use right-to-left and there's no right weapon, only left?
1905                }
1906               
1907                if (skill_num == CR_SHIELDBOOMERANG || skill_num == PA_SHIELDCHAIN) { //Refine bonus applies after cards and elements.
1908                        short index= sd->equip_index[EQI_HAND_L];
1909                        if (index >= 0 &&
1910                                sd->inventory_data[index] &&
1911                                sd->inventory_data[index]->type == IT_ARMOR)
1912                                ATK_ADD(10*sd->status.inventory[index].refine);
1913                }
1914        } //if (sd)
1915
1916        //Card Fix, tsd sid
1917        if (tsd && !(nk&NK_NO_CARDFIX_DEF))
1918        {
1919                short s_race2,s_class;
1920                short cardfix=1000;
1921
1922                s_race2 = status_get_race2(src);
1923                s_class = status_get_class(src);
1924
1925                if (!(nk&NK_NO_ELEFIX))
1926                {
1927                        cardfix=cardfix*(100-tsd->subele[s_ele])/100;
1928                        if (flag.lh && s_ele_ != s_ele)
1929                                cardfix=cardfix*(100-tsd->subele[s_ele_])/100;
1930                }
1931                cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100;
1932                cardfix=cardfix*(100-tsd->subrace2[s_race2])/100;
1933                cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100;
1934                cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100;
1935                for(i=0; i < ARRAYLENGTH(tsd->add_def) && tsd->add_def[i].rate;i++) {
1936                        if(tsd->add_def[i].class_ == s_class) {
1937                                cardfix=cardfix*(100-tsd->add_def[i].rate)/100;
1938                                break;
1939                        }
1940                }
1941
1942                if(wd.flag&BF_SHORT)
1943                        cardfix=cardfix*(100-tsd->near_attack_def_rate)/100;
1944                else    // BF_LONG (there's no other choice)
1945                        cardfix=cardfix*(100-tsd->long_attack_def_rate)/100;
1946
1947                if( tsd->sc.data[SC_DEF_RATE] )
1948                        cardfix=cardfix*(100-tsd->sc.data[SC_DEF_RATE]->val1)/100;
1949
1950                if (cardfix != 1000)
1951                        ATK_RATE(cardfix/10);
1952        }
1953
1954        if(flag.infdef)
1955        { //Plants receive 1 damage when hit
1956                if (flag.rh && (flag.hit || wd.damage>0))
1957                        wd.damage = 1;
1958                if (flag.lh && (flag.hit || wd.damage2>0))
1959                        wd.damage2 = 1;
1960                if (!(battle_config.skill_min_damage&1)) 
1961                        //Do not return if you are supposed to deal greater damage to plants than 1. [Skotlex]
1962                        return wd;
1963        }
1964
1965        if(sd && !skill_num && !flag.cri)
1966        {       //Check for double attack.
1967                if(((skill_lv = pc_checkskill(sd,TF_DOUBLE)) > 0 && sd->weapontype1 == W_DAGGER)
1968                        ||(sd->double_rate > 0 && sd->weapontype1 != W_FIST)) //Will fail bare-handed
1969                {       //Success chance is not added, the higher one is used [Skotlex]
1970                        if (rand()%100 < (5*skill_lv>sd->double_rate?5*skill_lv:sd->double_rate))
1971                        {
1972                                wd.div_=skill_get_num(TF_DOUBLE,skill_lv?skill_lv:1);
1973                                damage_div_fix(wd.damage, wd.div_);
1974                                wd.type = 0x08;
1975                        }
1976                } else
1977                if (sd->weapontype1 == W_REVOLVER &&
1978                        (skill_lv = pc_checkskill(sd,GS_CHAINACTION)) > 0 &&
1979                        (rand()%100 < 5*skill_lv)
1980                        )
1981                {
1982                        wd.div_=skill_get_num(GS_CHAINACTION,skill_lv);
1983                        damage_div_fix(wd.damage, wd.div_);
1984                        wd.type = 0x08;
1985                }
1986        }
1987
1988        if (sd)
1989        {
1990                if (!flag.rh && flag.lh) 
1991                {       //Move lh damage to the rh
1992                        wd.damage = wd.damage2;
1993                        wd.damage2 = 0;
1994                        flag.rh=1;
1995                        flag.lh=0;
1996                } else if(flag.rh && flag.lh)
1997                {       //Dual-wield
1998                        if (wd.damage)
1999                        {
2000                                skill = pc_checkskill(sd,AS_RIGHT);
2001                                wd.damage = wd.damage * (50 + (skill * 10))/100;
2002                                if(wd.damage < 1) wd.damage = 1;
2003                        }
2004                        if (wd.damage2)
2005                        {
2006                                skill = pc_checkskill(sd,AS_LEFT);
2007                                wd.damage2 = wd.damage2 * (30 + (skill * 10))/100;
2008                                if(wd.damage2 < 1) wd.damage2 = 1;
2009                        }
2010                } else if(sd->status.weapon == W_KATAR && !skill_num)
2011                { //Katars (offhand damage only applies to normal attacks, tested on Aegis 10.2)
2012                        skill = pc_checkskill(sd,TF_DOUBLE);
2013                        wd.damage2 = wd.damage * (1 + (skill * 2))/100;
2014
2015                        if(wd.damage && !wd.damage2) wd.damage2 = 1;
2016                        flag.lh = 1;
2017                }
2018        }
2019
2020        if(!flag.rh && wd.damage)
2021                wd.damage=0;
2022
2023        if(!flag.lh && wd.damage2)
2024                wd.damage2=0;
2025
2026        if(wd.damage + wd.damage2)
2027        {       //There is a total damage value
2028                if(!wd.damage2) {
2029                        wd.damage=battle_calc_damage(src,target,wd.damage,wd.div_,skill_num,skill_lv,wd.flag);
2030                        if (map_flag_gvg2(target->m))
2031                                wd.damage=battle_calc_gvg_damage(src,target,wd.damage,wd.div_,skill_num,skill_lv,wd.flag);
2032                } else
2033                if(!wd.damage) {
2034                        wd.damage2=battle_calc_damage(src,target,wd.damage2,wd.div_,skill_num,skill_lv,wd.flag);
2035                        if (map_flag_gvg2(target->m))
2036                                wd.damage2=battle_calc_gvg_damage(src,target,wd.damage2,wd.div_,skill_num,skill_lv,wd.flag);
2037                } else
2038                {
2039                        int d1=wd.damage+wd.damage2,d2=wd.damage2;
2040                        wd.damage=battle_calc_damage(src,target,d1,wd.div_,skill_num,skill_lv,wd.flag);
2041                        if (map_flag_gvg2(target->m))
2042                                wd.damage=battle_calc_gvg_damage(src,target,wd.damage,wd.div_,skill_num,skill_lv,wd.flag);
2043                        wd.damage2=(d2*100/d1)*wd.damage/100;
2044                        if(wd.damage > 1 && wd.damage2 < 1) wd.damage2=1;
2045                        wd.damage-=wd.damage2;
2046                }
2047        }
2048
2049        if(skill_num==ASC_BREAKER)
2050        {       //Breaker's int-based damage (a misc attack?)
2051                struct Damage md = battle_calc_misc_attack(src, target, skill_num, skill_lv, wflag);
2052                wd.damage += md.damage;
2053        }
2054
2055        if (wd.damage || wd.damage2) {
2056                if (sd && battle_config.equip_self_break_rate)
2057                {       // Self weapon breaking
2058                        int breakrate = battle_config.equip_natural_break_rate;
2059                        if (sc) {
2060                                if(sc->data[SC_OVERTHRUST])
2061                                        breakrate += 10;
2062                                if(sc->data[SC_MAXOVERTHRUST])
2063                                        breakrate += 10;
2064                        }
2065                        if (breakrate)
2066                                skill_break_equip(src, EQP_WEAPON, breakrate, BCT_SELF);
2067                }
2068                //Cart Termination/Tomahawk won't trigger breaking data. Why? No idea, go ask Gravity.
2069                if (battle_config.equip_skill_break_rate && skill_num != WS_CARTTERMINATION && skill_num != ITM_TOMAHAWK)
2070                {       // Target equipment breaking
2071                        int breakrate[2] = {0,0}; // weapon = 0, armor = 1
2072                        if (sd) {       // Break rate from equipment
2073                                breakrate[0] += sd->break_weapon_rate;
2074                                breakrate[1] += sd->break_armor_rate;
2075                        }
2076                        if (sc) {
2077                                if (sc->data[SC_MELTDOWN]) {
2078                                        breakrate[0] += sc->data[SC_MELTDOWN]->val2;
2079                                        breakrate[1] += sc->data[SC_MELTDOWN]->val3;
2080                                }
2081                        }       
2082                        if (breakrate[0])
2083                                skill_break_equip(target, EQP_WEAPON, breakrate[0], BCT_ENEMY);
2084                        if (breakrate[1])
2085                                skill_break_equip(target, EQP_ARMOR, breakrate[1], BCT_ENEMY);
2086                }
2087        }
2088
2089        //SG_FUSION hp penalty [Komurka]
2090        if (sc && sc->data[SC_FUSION])
2091        {
2092                int hp= sstatus->max_hp;
2093                if (sd && tsd) {
2094                        hp = 8*hp/100;
2095                        if (100*sstatus->hp <= 20*sstatus->max_hp)
2096                                hp = sstatus->hp;
2097                } else
2098                        hp = 5*hp/1000;
2099                status_zap(src, hp, 0);
2100        }
2101
2102        return wd;
2103}
2104
2105/*==========================================
2106 * battle_calc_magic_attack [DracoRPG]
2107 *------------------------------------------*/
2108struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list *target,int skill_num,int skill_lv,int mflag)
2109{
2110        int i, nk;
2111        short s_ele;
2112        unsigned int skillratio = 100;  //Skill dmg modifiers.
2113
2114        struct map_session_data *sd, *tsd;
2115        struct Damage ad;
2116        struct status_data *sstatus = status_get_status_data(src);
2117        struct status_data *tstatus = status_get_status_data(target);
2118        struct {
2119                unsigned imdef : 1;
2120                unsigned infdef : 1;
2121        }       flag;
2122
2123        memset(&ad,0,sizeof(ad));
2124        memset(&flag,0,sizeof(flag));
2125
2126        if(src==NULL || target==NULL)
2127        {
2128                nullpo_info(NLP_MARK);
2129                return ad;
2130        }
2131        //Initial Values
2132        ad.damage = 1;
2133        ad.div_=skill_get_num(skill_num,skill_lv);
2134        ad.amotion=skill_get_inf(skill_num)&INF_GROUND_SKILL?0:sstatus->amotion; //Amotion should be 0 for ground skills.
2135        ad.dmotion=tstatus->dmotion;
2136        ad.blewcount = skill_get_blewcount(skill_num,skill_lv);
2137        ad.flag=BF_MAGIC|BF_SKILL;
2138        ad.dmg_lv=ATK_DEF;
2139        nk = skill_get_nk(skill_num);
2140        flag.imdef = nk&NK_IGNORE_DEF?1:0;
2141
2142        sd = BL_CAST(BL_PC, src);
2143        tsd = BL_CAST(BL_PC, target);
2144
2145        //Initialize variables that will be used afterwards
2146        s_ele = skill_get_ele(skill_num, skill_lv);
2147
2148        if (s_ele == -1) // pl=-1 : the skill takes the weapon's element
2149                s_ele = sstatus->rhw.ele;
2150        else if (s_ele == -2) //Use status element
2151                s_ele = status_get_attack_sc_element(src,status_get_sc(src));
2152       
2153        //Set miscellaneous data that needs be filled
2154        if(sd) {
2155                sd->state.arrow_atk = 0;
2156                ad.blewcount += battle_blewcount_bonus(sd, skill_num);
2157        }
2158
2159        //Skill Range Criteria
2160        ad.flag |= battle_range_type(src, target, skill_num, skill_lv);
2161        flag.infdef=(tstatus->mode&MD_PLANT?1:0);
2162               
2163        switch(skill_num)
2164        {
2165                case MG_FIREWALL:
2166                case NJ_KAENSIN:
2167                        ad.dmotion = 0; //No flinch animation.
2168                        if ( tstatus->def_ele == ELE_FIRE || battle_check_undead(tstatus->race, tstatus->def_ele) )
2169                                ad.blewcount = 0; //No knockback
2170                        break;
2171                case PR_SANCTUARY:
2172                        ad.dmotion = 0; //No flinch animation.
2173                        break;
2174        }
2175
2176        if (!flag.infdef) //No need to do the math for plants
2177        {
2178
2179//MATK_RATE scales the damage. 100 = no change. 50 is halved, 200 is doubled, etc
2180#define MATK_RATE( a ) { ad.damage= ad.damage*(a)/100; }
2181//Adds dmg%. 100 = +100% (double) damage. 10 = +10% damage
2182#define MATK_ADDRATE( a ) { ad.damage+= ad.damage*(a)/100; }
2183//Adds an absolute value to damage. 100 = +100 damage
2184#define MATK_ADD( a ) { ad.damage+= a; }
2185
2186                switch (skill_num)
2187                {       //Calc base damage according to skill
2188                        case AL_HEAL:
2189                        case PR_BENEDICTIO:
2190                                ad.damage = skill_calc_heal(src, target, skill_lv)/2;
2191                                break;
2192                        case PR_ASPERSIO:
2193                                ad.damage = 40;
2194                                break;
2195                        case PR_SANCTUARY:
2196                                ad.damage = (skill_lv>6)?388:skill_lv*50;
2197                                break;
2198                        case ALL_RESURRECTION:
2199                        case PR_TURNUNDEAD:
2200                                //Undead check is on skill_castend_damageid code.
2201                                i = 20*skill_lv + sstatus->luk + sstatus->int_ + status_get_lv(src)
2202                                        + 200 - 200*tstatus->hp/tstatus->max_hp;
2203                                if(i > 700) i = 700;
2204                                if(rand()%1000 < i && !(tstatus->mode&MD_BOSS))
2205                                        ad.damage = tstatus->hp;
2206                                else
2207                                        ad.damage = status_get_lv(src) + sstatus->int_ + skill_lv * 10;
2208                                break;
2209                        case PF_SOULBURN:
2210                                ad.damage = tstatus->sp * 2;
2211                                break;
2212                        default:
2213                        {
2214                                if (sstatus->matk_max > sstatus->matk_min) {
2215                                        MATK_ADD(sstatus->matk_min+rand()%(1+sstatus->matk_max-sstatus->matk_min));
2216                                } else {
2217                                        MATK_ADD(sstatus->matk_min);
2218                                }
2219
2220                                if(nk&NK_SPLASHSPLIT){ // Divide MATK in case of multiple targets skill
2221                                        if(mflag>0)
2222                                                ad.damage/= mflag;
2223                                        else
2224                                                ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_num, skill_get_name(skill_num));
2225                                }
2226
2227                                switch(skill_num){
2228                                        case MG_NAPALMBEAT:
2229                                        case MG_FIREBALL:
2230                                                skillratio += skill_lv*10-30;
2231                                                break;
2232                                        case MG_SOULSTRIKE:
2233                                                if (battle_check_undead(tstatus->race,tstatus->def_ele))
2234                                                        skillratio += 5*skill_lv;
2235                                                break;
2236                                        case MG_FIREWALL:
2237                                                skillratio -= 50;
2238                                                break;
2239                                        case MG_THUNDERSTORM:
2240                                                skillratio -= 20;
2241                                                break;
2242                                        case MG_FROSTDIVER:
2243                                                skillratio += 10*skill_lv;
2244                                                break;
2245                                        case AL_HOLYLIGHT:
2246                                                skillratio += 25;
2247                                                if (sd && sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_PRIEST)
2248                                                        skillratio *= 5; //Does 5x damage include bonuses from other skills?
2249                                                break;
2250                                        case AL_RUWACH:
2251                                                skillratio += 45;
2252                                                break;
2253                                        case WZ_FROSTNOVA:
2254                                                skillratio += (100+skill_lv*10)*2/3-100;
2255                                                break;
2256                                        case WZ_FIREPILLAR:
2257                                                if (skill_lv > 10)
2258                                                        skillratio += 100;
2259                                                else
2260                                                        skillratio -= 80;
2261                                                break;
2262                                        case WZ_SIGHTRASHER:
2263                                                skillratio += 20*skill_lv;
2264                                                break;
2265                                        case WZ_VERMILION:
2266                                                skillratio += 20*skill_lv-20;
2267                                                break;
2268                                        case WZ_WATERBALL:
2269                                                skillratio += 30*skill_lv;
2270                                                break;
2271                                        case WZ_STORMGUST:
2272                                                skillratio += 40*skill_lv;
2273                                                break;
2274                                        case HW_NAPALMVULCAN:
2275                                                skillratio += 10*skill_lv-30;
2276                                                break;
2277                                        case SL_STIN:
2278                                                skillratio += (tstatus->size?-99:10*skill_lv); //target size must be small (0) for full damage.
2279                                                break;
2280                                        case SL_STUN:
2281                                                skillratio += (tstatus->size!=2?5*skill_lv:-99); //Full damage is dealt on small/medium targets
2282                                                break;
2283                                        case SL_SMA:
2284                                                skillratio += -60 + status_get_lv(src); //Base damage is 40% + lv%
2285                                                break;
2286                                        case NJ_KOUENKA:
2287                                                skillratio -= 10;
2288                                                break;
2289                                        case NJ_KAENSIN:
2290                                                skillratio -= 50;
2291                                                break;
2292                                        case NJ_BAKUENRYU:
2293                                                skillratio += 50*(skill_lv-1);
2294                                                break;
2295                                        case NJ_HYOUSYOURAKU:
2296                                                skillratio += 50*skill_lv;
2297                                                break;
2298                                        case NJ_RAIGEKISAI:
2299                                                skillratio += 60 + 40*skill_lv;
2300                                                break;
2301                                        case NJ_KAMAITACHI:
2302                                        case NPC_ENERGYDRAIN:
2303                                                skillratio += 100*skill_lv;
2304                                                break;
2305                                        case NPC_EARTHQUAKE:
2306                                                skillratio += 100 +100*skill_lv +100*(skill_lv/2);
2307                                                break;
2308                                }
2309
2310                                MATK_RATE(skillratio);
2311                       
2312                                //Constant/misc additions from skills
2313                                if (skill_num == WZ_FIREPILLAR)
2314                                        MATK_ADD(50);
2315                        }
2316                }
2317
2318                if(sd) {
2319                        //Damage bonuses
2320                        if ((i = pc_skillatk_bonus(sd, skill_num)))
2321                                ad.damage += ad.damage*i/100;
2322
2323                        //Ignore Defense?
2324                        if (!flag.imdef && (
2325                                sd->ignore_mdef_ele & (1<<tstatus->def_ele) ||
2326                                sd->ignore_mdef_race & (1<<tstatus->race) ||
2327                                sd->ignore_mdef_race & (is_boss(target)?1<<RC_BOSS:1<<RC_NONBOSS)
2328                        ))
2329                                flag.imdef = 1;
2330                }
2331
2332                if(!flag.imdef){
2333                        char mdef = tstatus->mdef;
2334                        int mdef2= tstatus->mdef2;
2335                        if(sd) {
2336                                i = sd->ignore_mdef[is_boss(target)?RC_BOSS:RC_NONBOSS];
2337                                i+= sd->ignore_mdef[tstatus->race];
2338                                if (i)
2339                                {
2340                                        if (i > 100) i = 100;
2341                                        mdef -= mdef * i/100;
2342                                        //mdef2-= mdef2* i/100;
2343                                }
2344                        }
2345                        if(battle_config.magic_defense_type)
2346                                ad.damage = ad.damage - mdef*battle_config.magic_defense_type - mdef2;
2347                        else
2348                                ad.damage = ad.damage * (100-mdef)/100 - mdef2;
2349                }
2350
2351                if(skill_num == CR_GRANDCROSS || skill_num == NPC_GRANDDARKNESS)
2352                {       //Apply the physical part of the skill's damage. [Skotlex]
2353                        struct Damage wd = battle_calc_weapon_attack(src,target,skill_num,skill_lv,mflag);
2354                        ad.damage = (wd.damage + ad.damage) * (100 + 40*skill_lv)/100;
2355                        if(src==target)
2356                        {
2357                                if (src->type == BL_PC)
2358                                        ad.damage = ad.damage/2;
2359                                else
2360                                        ad.damage = 0;
2361                        }
2362                }
2363               
2364                if (skill_num == NPC_EARTHQUAKE)
2365                {       //Adds atk2 to the damage, should be influenced by number of hits and skill-ratio, but not mdef reductions. [Skotlex]
2366                        //Also divide the extra bonuses from atk2 based on the number in range [Kevin]
2367                        if(mflag>0)
2368                                ad.damage+= (sstatus->rhw.atk2*skillratio/100)/mflag;
2369                        else
2370                                ShowError("Zero range by %d:%s, divide per 0 avoided!\n", skill_num, skill_get_name(skill_num));
2371                }
2372
2373                if(ad.damage<1)
2374                        ad.damage=1;
2375
2376                if (!(nk&NK_NO_ELEFIX))
2377                        ad.damage=battle_attr_fix(src, target, ad.damage, s_ele, tstatus->def_ele, tstatus->ele_lv);
2378
2379                if (sd && !(nk&NK_NO_CARDFIX_ATK)) {
2380                        short t_class = status_get_class(target);
2381                        short cardfix=1000;
2382
2383                        cardfix=cardfix*(100+sd->magic_addrace[tstatus->race])/100;
2384                        if (!(nk&NK_NO_ELEFIX))
2385                                cardfix=cardfix*(100+sd->magic_addele[tstatus->def_ele])/100;
2386                        cardfix=cardfix*(100+sd->magic_addsize[tstatus->size])/100;
2387                        cardfix=cardfix*(100+sd->magic_addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100;
2388                        for(i=0; i< ARRAYLENGTH(sd->add_mdmg) && sd->add_mdmg[i].rate;i++) {
2389                                if(sd->add_mdmg[i].class_ == t_class) {
2390                                        cardfix=cardfix*(100+sd->add_mdmg[i].rate)/100;
2391                                        continue;
2392                                }
2393                        }
2394                        if (cardfix != 1000)
2395                                MATK_RATE(cardfix/10);
2396                }
2397
2398                if (tsd && !(nk&NK_NO_CARDFIX_DEF))
2399                {       //Target cards.
2400                        short s_race2=status_get_race2(src);
2401                        short s_class= status_get_class(src);
2402                        int cardfix=1000;
2403
2404                        if (!(nk&NK_NO_ELEFIX))
2405                                cardfix=cardfix*(100-tsd->subele[s_ele])/100;
2406                        cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100;
2407                        cardfix=cardfix*(100-tsd->subrace2[s_race2])/100;
2408                        cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100;
2409                        cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100;
2410                        for(i=0; i < ARRAYLENGTH(tsd->add_mdef) && tsd->add_mdef[i].rate;i++) {
2411                                if(tsd->add_mdef[i].class_ == s_class) {
2412                                        cardfix=cardfix*(100-tsd->add_mdef[i].rate)/100;
2413                                        break;
2414                                }
2415                        }
2416                        //It was discovered that ranged defense also counts vs magic! [Skotlex]
2417                        if (ad.flag&BF_SHORT)
2418                                cardfix=cardfix*(100-tsd->near_attack_def_rate)/100;
2419                        else
2420                                cardfix=cardfix*(100-tsd->long_attack_def_rate)/100;
2421
2422                        cardfix=cardfix*(100-tsd->magic_def_rate)/100;
2423
2424                        if( tsd->sc.data[SC_MDEF_RATE] )
2425                                cardfix=cardfix*(100-tsd->sc.data[SC_MDEF_RATE]->val1)/100;
2426
2427                        if (cardfix != 1000)
2428                                MATK_RATE(cardfix/10);
2429                }
2430        }
2431
2432        damage_div_fix(ad.damage, ad.div_);
2433       
2434        if (flag.infdef && ad.damage)
2435                ad.damage = ad.damage>0?1:-1;
2436               
2437        ad.damage=battle_calc_damage(src,target,ad.damage,ad.div_,skill_num,skill_lv,ad.flag);
2438        if (map_flag_gvg2(target->m))
2439                ad.damage=battle_calc_gvg_damage(src,target,ad.damage,ad.div_,skill_num,skill_lv,ad.flag);
2440        return ad;
2441}
2442
2443/*==========================================
2444 * ‚»‚Ì‘Œƒ_E?[ƒWŒvŽZ
2445 *------------------------------------------*/
2446struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *target,int skill_num,int skill_lv,int mflag)
2447{
2448        int skill;
2449        short i, nk;
2450        short s_ele;
2451
2452        struct map_session_data *sd, *tsd;
2453        struct Damage md; //DO NOT CONFUSE with md of mob_data!
2454        struct status_data *sstatus = status_get_status_data(src);
2455        struct status_data *tstatus = status_get_status_data(target);
2456
2457        memset(&md,0,sizeof(md));
2458
2459        if( src == NULL || target == NULL ){
2460                nullpo_info(NLP_MARK);
2461                return md;
2462        }
2463
2464        //Some initial values
2465        md.amotion=skill_get_inf(skill_num)&INF_GROUND_SKILL?0:sstatus->amotion;
2466        md.dmotion=tstatus->dmotion;
2467        md.div_=skill_get_num( skill_num,skill_lv );
2468        md.blewcount=skill_get_blewcount(skill_num,skill_lv);
2469        md.dmg_lv=ATK_DEF;
2470        md.flag=BF_MISC|BF_SKILL;
2471
2472        nk = skill_get_nk(skill_num);
2473       
2474        sd = BL_CAST(BL_PC, src);
2475        tsd = BL_CAST(BL_PC, target);
2476       
2477        if(sd) {
2478                sd->state.arrow_atk = 0;
2479                md.blewcount += battle_blewcount_bonus(sd, skill_num);
2480        }
2481
2482        s_ele = skill_get_ele(skill_num, skill_lv);
2483        if (s_ele < 0) //Attack that takes weapon's element for misc attacks? Make it neutral [Skotlex]
2484                s_ele = ELE_NEUTRAL;
2485
2486        //Skill Range Criteria
2487        md.flag |= battle_range_type(src, target, skill_num, skill_lv);
2488
2489        switch(skill_num){
2490        case HT_LANDMINE:
2491                md.damage=skill_lv*(sstatus->dex+75)*(100+sstatus->int_)/100;
2492                break;
2493        case HT_BLASTMINE:
2494                md.damage=skill_lv*(sstatus->dex/2+50)*(100+sstatus->int_)/100;
2495                break;
2496        case HT_CLAYMORETRAP:
2497                md.damage=skill_lv*(sstatus->dex/2+75)*(100+sstatus->int_)/100;
2498                break;
2499        case HT_BLITZBEAT:
2500        case SN_FALCONASSAULT:
2501                //Blitz-beat Damage.
2502                if(!sd || (skill = pc_checkskill(sd,HT_STEELCROW)) <= 0)
2503                        skill=0;
2504                md.damage=(sstatus->dex/10+sstatus->int_/2+skill*3+40)*2;
2505                if(mflag > 1) //Autocasted Blitz.
2506                        nk|=NK_SPLASHSPLIT;
2507               
2508                if (skill_num == SN_FALCONASSAULT)
2509                {
2510                        //Div fix of Blitzbeat
2511                        skill = skill_get_num(HT_BLITZBEAT, 5);
2512                        damage_div_fix(md.damage, skill); 
2513
2514                        //Falcon Assault Modifier
2515                        md.damage=md.damage*(150+70*skill_lv)/100;
2516                }
2517                break;
2518        case TF_THROWSTONE:
2519                md.damage=50;
2520                break;
2521        case BA_DISSONANCE:
2522                md.damage=30+skill_lv*10;
2523                if (sd)
2524                        md.damage+= 3*pc_checkskill(sd,BA_MUSICALLESSON);
2525                break;
2526        case NPC_SELFDESTRUCTION:
2527                md.damage = sstatus->hp;
2528                break;
2529        case NPC_SMOKING:
2530                md.damage=3;
2531                break;
2532        case NPC_DARKBREATH:
2533                md.damage = 500 + (skill_lv-1)*1000 + rand()%1000;
2534                if(md.damage > 9999) md.damage = 9999;
2535                break;
2536        case PA_PRESSURE:
2537                md.damage=500+300*skill_lv;
2538                break;
2539        case PA_GOSPEL:
2540                md.damage = 1+rand()%9999;
2541                break;
2542        case CR_ACIDDEMONSTRATION: // updated the formula based on a Japanese formula found to be exact [Reddozen]
2543                if(tstatus->vit+sstatus->int_) //crash fix
2544                        md.damage = 7*tstatus->vit*sstatus->int_*sstatus->int_ / (10*(tstatus->vit+sstatus->int_));
2545                else
2546                        md.damage = 0;
2547                if (tsd) md.damage>>=1;
2548                if (md.damage < 0 || md.damage > INT_MAX>>1)
2549                //Overflow prevention, will anyone whine if I cap it to a few billion?
2550                //Not capped to INT_MAX to give some room for further damage increase.
2551                        md.damage = INT_MAX>>1;
2552                break;
2553        case NJ_ZENYNAGE:
2554                md.damage = skill_get_zeny(skill_num ,skill_lv);
2555                if (!md.damage) md.damage = 2;
2556                md.damage = md.damage + rand()%md.damage;
2557                if (is_boss(target))
2558                        md.damage=md.damage/3;
2559                else if (tsd)
2560                        md.damage=md.damage/2;
2561                break;
2562        case GS_FLING:
2563                md.damage = sd?sd->status.job_level:status_get_lv(src);
2564                break;
2565        case HVAN_EXPLOSION:    //[orn]
2566                md.damage = sstatus->max_hp * (50 + 50 * skill_lv) / 100 ;
2567                break ;
2568        case ASC_BREAKER:
2569                md.damage = 500+rand()%500 + 5*skill_lv * sstatus->int_;
2570                nk|=NK_IGNORE_FLEE|NK_NO_ELEFIX; //These two are not properties of the weapon based part.
2571                break;
2572        case HW_GRAVITATION:
2573                md.damage = 200+200*skill_lv;
2574                md.dmotion = 0; //No flinch animation.
2575                break;
2576        case NPC_EVILLAND:
2577                md.damage = (skill_lv>6)?666:skill_lv*100;
2578                break;
2579        }
2580
2581        if (nk&NK_SPLASHSPLIT){ // Divide ATK among targets
2582                if(mflag>0)
2583                        md.damage/= mflag;
2584                else
2585                        ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_num, skill_get_name(skill_num));
2586        }
2587
2588        damage_div_fix(md.damage, md.div_);
2589       
2590        if (!(nk&NK_IGNORE_FLEE))
2591        {
2592                struct status_change *sc = status_get_sc(target);
2593                i = 0; //Temp for "hit or no hit"
2594                if(sc && sc->opt1 && sc->opt1 != OPT1_STONEWAIT)
2595                        i = 1;
2596                else {
2597                        short
2598                                flee = tstatus->flee,
2599                                hitrate=80; //Default hitrate
2600
2601                        if(battle_config.agi_penalty_type && 
2602                                battle_config.agi_penalty_target&target->type)
2603                        {       
2604                                unsigned char attacker_count; //256 max targets should be a sane max
2605                                attacker_count = unit_counttargeted(target,battle_config.agi_penalty_count_lv);
2606                                if(attacker_count >= battle_config.agi_penalty_count)
2607                                {
2608                                        if (battle_config.agi_penalty_type == 1)
2609                                                flee = (flee * (100 - (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num))/100;
2610                                        else //asume type 2: absolute reduction
2611                                                flee -= (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num;
2612                                        if(flee < 1) flee = 1;
2613                                }
2614                        }
2615
2616                        hitrate+= sstatus->hit - flee;
2617                        hitrate = cap_value(hitrate, battle_config.min_hitrate, battle_config.max_hitrate);
2618
2619                        if(rand()%100 < hitrate)
2620                                i = 1;
2621                }
2622                if (!i) {
2623                        md.damage = 0;
2624                        md.dmg_lv=ATK_FLEE;
2625                }
2626        }
2627
2628        if(md.damage && tsd && !(nk&NK_NO_CARDFIX_DEF)){
2629                int cardfix = 10000;
2630                int race2 = status_get_race2(src);
2631                if (!(nk&NK_NO_ELEFIX))
2632                        cardfix=cardfix*(100-tsd->subele[s_ele])/100;
2633                cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100;
2634                cardfix=cardfix*(100-tsd->subrace2[race2])/100;
2635                cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100;
2636                cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100;
2637                cardfix=cardfix*(100-tsd->misc_def_rate)/100;
2638                if(md.flag&BF_SHORT)
2639                        cardfix=cardfix*(100-tsd->near_attack_def_rate)/100;
2640                else    // BF_LONG (there's no other choice)
2641                        cardfix=cardfix*(100-tsd->long_attack_def_rate)/100;
2642
2643                if (cardfix != 10000)
2644                        md.damage=md.damage*cardfix/10000;
2645        }
2646
2647        if (sd && (i = pc_skillatk_bonus(sd, skill_num)))
2648                md.damage += md.damage*i/100;
2649
2650        if(md.damage < 0)
2651                md.damage = 0;
2652        else if(md.damage && tstatus->mode&MD_PLANT)
2653                md.damage = 1;
2654
2655        if(!(nk&NK_NO_ELEFIX))
2656                md.damage=battle_attr_fix(src, target, md.damage, s_ele, tstatus->def_ele, tstatus->ele_lv);
2657
2658        md.damage=battle_calc_damage(src,target,md.damage,md.div_,skill_num,skill_lv,md.flag);
2659        if (map_flag_gvg2(target->m))
2660                md.damage=battle_calc_gvg_damage(src,target,md.damage,md.div_,skill_num,skill_lv,md.flag);
2661
2662        if (skill_num == NJ_ZENYNAGE && sd)
2663        {       //Time to Pay Up.
2664                if ( md.damage > sd->status.zeny )
2665                        md.damage=sd->status.zeny;
2666                pc_payzeny(sd, md.damage);
2667        }
2668
2669        return md;
2670}
2671/*==========================================
2672 * ƒ_E?[ƒWŒvŽZˆêЇ?E?—p
2673 *------------------------------------------*/
2674struct Damage battle_calc_attack(int attack_type,struct block_list *bl,struct block_list *target,int skill_num,int skill_lv,int count)
2675{
2676        struct Damage d;
2677        switch(attack_type) {
2678        case BF_WEAPON: d = battle_calc_weapon_attack(bl,target,skill_num,skill_lv,count); break;
2679        case BF_MAGIC:  d = battle_calc_magic_attack(bl,target,skill_num,skill_lv,count);  break;
2680        case BF_MISC:   d = battle_calc_misc_attack(bl,target,skill_num,skill_lv,count);   break;
2681        default:
2682                ShowError("battle_calc_attack: unknown attack type! %d\n",attack_type);
2683                memset(&d,0,sizeof(d));
2684                break;
2685        }
2686        if (d.damage + d.damage2 < 1)
2687        {       //Miss/Absorbed
2688                //Weapon attacks should go through to cause additional effects.
2689                if (d.dmg_lv != ATK_LUCKY && attack_type&(BF_MAGIC|BF_MISC))
2690                        d.dmg_lv = ATK_FLEE;
2691                d.dmotion = 0;
2692        }
2693        return d;
2694}
2695
2696//Calculates BF_WEAPON returned damage.
2697int battle_calc_return_damage(struct block_list* bl, int damage, int flag)
2698{
2699        struct map_session_data* sd = NULL;
2700        int rdamage = 0;
2701
2702        sd = BL_CAST(BL_PC, bl);
2703
2704        //Bounces back part of the damage.
2705        if (flag & BF_SHORT) {
2706                struct status_change* sc;
2707                if (sd && sd->short_weapon_damage_return)
2708                {
2709                        rdamage += damage * sd->short_weapon_damage_return / 100;
2710                        if(rdamage < 1) rdamage = 1;
2711                }
2712                sc = status_get_sc(bl);
2713                if (sc && sc->data[SC_REFLECTSHIELD])
2714                {
2715                        rdamage += damage * sc->data[SC_REFLECTSHIELD]->val2 / 100;
2716                        if (rdamage < 1) rdamage = 1;
2717                }
2718        } else {
2719                if (sd && sd->long_weapon_damage_return)
2720                {
2721                        rdamage += damage * sd->long_weapon_damage_return / 100;
2722                        if (rdamage < 1) rdamage = 1;
2723                }
2724        }
2725        return rdamage;
2726}
2727
2728void battle_drain(TBL_PC *sd, struct block_list *tbl, int rdamage, int ldamage, int race, int boss)
2729{
2730        struct weapon_data *wd;
2731        int type, thp = 0, tsp = 0, rhp = 0, rsp = 0, hp, sp, i, *damage;
2732        for (i = 0; i < 4; i++) {
2733                //First two iterations: Right hand
2734                if (i < 2) { wd = &sd->right_weapon; damage = &rdamage; }
2735                else { wd = &sd->left_weapon; damage = &ldamage; }
2736                if (*damage <= 0) continue;
2737                //First and Third iterations: race, other two boss/nonboss state
2738                if (i == 0 || i == 2) 
2739                        type = race;
2740                else
2741                        type = boss?RC_BOSS:RC_NONBOSS;
2742               
2743                hp = wd->hp_drain[type].value;
2744                if (wd->hp_drain[type].rate)
2745                        hp += battle_calc_drain(*damage, wd->hp_drain[type].rate, wd->hp_drain[type].per);
2746
2747                sp = wd->sp_drain[type].value;
2748                if (wd->sp_drain[type].rate)
2749                        sp += battle_calc_drain(*damage, wd->sp_drain[type].rate, wd->sp_drain[type].per);
2750
2751                if (hp) {
2752                        if (wd->hp_drain[type].type)
2753                                rhp += hp;
2754                        thp += hp;
2755                }
2756                if (sp) {
2757                        if (wd->sp_drain[type].type)
2758                                rsp += sp;
2759                        tsp += sp;
2760                }
2761        }
2762
2763        if (sd->sp_vanish_rate && rand()%1000 < sd->sp_vanish_rate)
2764                status_percent_damage(&sd->bl, tbl, 0, (unsigned char)sd->sp_vanish_per, false);
2765        if (!thp && !tsp) return;
2766
2767        status_heal(&sd->bl, thp, tsp, battle_config.show_hp_sp_drain?3:1);
2768       
2769        if (rhp || rsp)
2770                status_zap(tbl, rhp, rsp);
2771}
2772
2773/*==========================================
2774 * ’Ê?EUŒ‚?E?‚܂Ƃß
2775 *------------------------------------------*/
2776enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* target, unsigned int tick, int flag)
2777{
2778        struct map_session_data *sd = NULL, *tsd = NULL;
2779        struct status_data *sstatus, *tstatus;
2780        struct status_change *sc, *tsc;
2781        int damage,rdamage=0,rdelay=0;
2782        int skillv;
2783        struct Damage wd;
2784
2785        nullpo_retr(ATK_NONE, src);
2786        nullpo_retr(ATK_NONE, target);
2787
2788        if (src->prev == NULL || target->prev == NULL)
2789                return ATK_NONE;
2790
2791        sd = BL_CAST(BL_PC, src);
2792        tsd = BL_CAST(BL_PC, target);
2793
2794        sstatus = status_get_status_data(src);
2795        tstatus = status_get_status_data(target);
2796
2797        sc = status_get_sc(src);
2798        tsc = status_get_sc(target);
2799
2800        if (sc && !sc->count) //Avoid sc checks when there's none to check for. [Skotlex]
2801                sc = NULL;
2802        if (tsc && !tsc->count)
2803                tsc = NULL;
2804       
2805        if (sd)
2806        {
2807                sd->state.arrow_atk = (sd->status.weapon == W_BOW || (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE));
2808                if (sd->state.arrow_atk)
2809                {
2810                        int index = sd->equip_index[EQI_AMMO];
2811                        if (index<0) {
2812                                clif_arrow_fail(sd,0);
2813                                return ATK_NONE;
2814                        }
2815                        //Ammo check by Ishizu-chan
2816                        if (sd->inventory_data[index])
2817                        switch (sd->status.weapon) {
2818                        case W_BOW:
2819                                if (sd->inventory_data[index]->look != A_ARROW) {
2820                                        clif_arrow_fail(sd,0);
2821                                        return ATK_NONE;
2822                                }
2823                        break;
2824                        case W_REVOLVER:
2825                        case W_RIFLE:
2826                        case W_GATLING:
2827                        case W_SHOTGUN:
2828                                if (sd->inventory_data[index]->look != A_BULLET) {
2829                                        clif_arrow_fail(sd,0);
2830                                        return ATK_NONE;
2831                                }
2832                        break;
2833                        case W_GRENADE:
2834                                if (sd->inventory_data[index]->look != A_GRENADE) {
2835                                        clif_arrow_fail(sd,0);
2836                                        return ATK_NONE;
2837                                }
2838                        break;
2839                        }
2840                }
2841        }
2842
2843        if (sc && sc->data[SC_CLOAKING] && !(sc->data[SC_CLOAKING]->val4&2))
2844                status_change_end(src,SC_CLOAKING,-1);
2845
2846        //Check for counter attacks that block your attack. [Skotlex]
2847        if(tsc)
2848        {
2849                if(tsc->data[SC_AUTOCOUNTER] &&
2850                        status_check_skilluse(target, src, KN_AUTOCOUNTER, 1)
2851                )       {
2852                        int dir = map_calc_dir(target,src->x,src->y);
2853                        int t_dir = unit_getdir(target);
2854                        int dist = distance_bl(src, target);
2855                        if(dist <= 0 || (!map_check_dir(dir,t_dir) && dist <= tstatus->rhw.range+1))
2856                        {
2857                                int skilllv = tsc->data[SC_AUTOCOUNTER]->val1;
2858                                clif_skillcastcancel(target); //Remove the casting bar. [Skotlex]
2859                                clif_damage(src, target, tick, sstatus->amotion, 1, 0, 1, 0, 0); //Display MISS.
2860                                status_change_end(target,SC_AUTOCOUNTER,-1);
2861                                skill_attack(BF_WEAPON,target,target,src,KN_AUTOCOUNTER,skilllv,tick,0);
2862                                return ATK_NONE;
2863                        }
2864                }
2865                if (tsc->data[SC_BLADESTOP_WAIT] && !is_boss(src)) {
2866                        int skilllv = tsc->data[SC_BLADESTOP_WAIT]->val1;
2867                        int duration = skill_get_time2(MO_BLADESTOP,skilllv);
2868                        status_change_end(target, SC_BLADESTOP_WAIT, -1);
2869                        if(sc_start4(src, SC_BLADESTOP, 100, sd?pc_checkskill(sd, MO_BLADESTOP):5, 0, 0, (int)target, duration))
2870                        {       //Target locked.
2871                                clif_damage(src, target, tick, sstatus->amotion, 1, 0, 1, 0, 0); //Display MISS.
2872                                clif_bladestop(target,src,1);
2873                                sc_start4(target, SC_BLADESTOP, 100, skilllv, 0, 0,(int)src, duration);
2874                                return ATK_NONE;
2875                        }
2876                }
2877        }
2878
2879        if(sd && (skillv = pc_checkskill(sd,MO_TRIPLEATTACK)) > 0)
2880        {
2881                int triple_rate= 30 - skillv; //Base Rate
2882                if (sc && sc->data[SC_SKILLRATE_UP] && sc->data[SC_SKILLRATE_UP]->val1 == MO_TRIPLEATTACK)
2883                {
2884                        triple_rate+= triple_rate*(sc->data[SC_SKILLRATE_UP]->val2)/100;
2885                        status_change_end(src,SC_SKILLRATE_UP,-1);
2886                }
2887                if (rand()%100 < triple_rate)
2888                        //FIXME: invalid return type!
2889                        return (damage_lv)skill_attack(BF_WEAPON,src,src,target,MO_TRIPLEATTACK,skillv,tick,0);
2890        }
2891
2892        if (sc)
2893        {
2894                if (sc->data[SC_SACRIFICE])
2895                        //FIXME: invalid return type!
2896                        return (damage_lv)skill_attack(BF_WEAPON,src,src,target,PA_SACRIFICE,sc->data[SC_SACRIFICE]->val1,tick,0);
2897                if (sc->data[SC_MAGICALATTACK])
2898                        //FIXME: invalid return type!
2899                        return (damage_lv)skill_attack(BF_MAGIC,src,src,target,NPC_MAGICALATTACK,sc->data[SC_MAGICALATTACK]->val1,tick,0);
2900        }
2901
2902        wd = battle_calc_weapon_attack(src, target, 0, 0, flag);
2903
2904        if (sd && sd->state.arrow_atk) //Consume arrow.
2905                battle_consume_ammo(sd, 0, 0);
2906
2907        damage = wd.damage + wd.damage2;
2908        if (damage > 0 && src != target) {
2909                rdamage = battle_calc_return_damage(target, damage, wd.flag);
2910                if (rdamage > 0) {
2911                        rdelay = clif_damage(src, src, tick, wd.amotion, sstatus->dmotion, rdamage, 1, 4, 0);
2912                        //Use Reflect Shield to signal this kind of skill trigger. [Skotlex]
2913                        skill_additional_effect(target,src,CR_REFLECTSHIELD,1,BF_WEAPON|BF_SHORT|BF_NORMAL,tick);
2914                }
2915        }
2916
2917        wd.dmotion = clif_damage(src, target, tick, wd.amotion, wd.dmotion, wd.damage, wd.div_ , wd.type, wd.damage2);
2918
2919        if (sd && sd->splash_range > 0 && damage > 0)
2920                skill_castend_damage_id(src, target, 0, 1, tick, 0);
2921
2922        map_freeblock_lock();
2923
2924        battle_delay_damage(tick, wd.amotion, src, target, wd.flag, 0, 0, damage, wd.dmg_lv, wd.dmotion);
2925
2926        if (sc && sc->data[SC_AUTOSPELL] && rand()%100 < sc->data[SC_AUTOSPELL]->val4) {
2927                int sp = 0;
2928                int skillid = sc->data[SC_AUTOSPELL]->val2;
2929                int skilllv = sc->data[SC_AUTOSPELL]->val3;
2930                int i = rand()%100;
2931                if (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_SAGE)
2932                        i = 0; //Max chance, no skilllv reduction. [Skotlex]
2933                if (i >= 50) skilllv -= 2;
2934                else if (i >= 15) skilllv--;
2935                if (skilllv < 1) skilllv = 1;
2936                sp = skill_get_sp(skillid,skilllv) * 2 / 3;
2937
2938                if (status_charge(src, 0, sp)) {
2939                        switch (skill_get_casttype(skillid)) {
2940                                case CAST_GROUND:
2941                                        skill_castend_pos2(src, target->x, target->y, skillid, skilllv, tick, flag);
2942                                        break;
2943                                case CAST_NODAMAGE:
2944                                        skill_castend_nodamage_id(src, target, skillid, skilllv, tick, flag);
2945                                        break;
2946                                case CAST_DAMAGE:
2947                                        skill_castend_damage_id(src, target, skillid, skilllv, tick, flag);
2948                                        break;
2949                        }
2950                }
2951        }
2952        if (sd) {
2953                if (wd.flag & BF_WEAPON && src != target && damage > 0) {
2954                        if (battle_config.left_cardfix_to_right)
2955                                battle_drain(sd, target, wd.damage, wd.damage, tstatus->race, is_boss(target));
2956                        else
2957                                battle_drain(sd, target, wd.damage, wd.damage2, tstatus->race, is_boss(target));
2958                }
2959        }
2960        if (rdamage > 0) { //By sending attack type "none" skill_additional_effect won't be invoked. [Skotlex]
2961                if(tsd && src != target)
2962                        battle_drain(tsd, src, rdamage, rdamage, sstatus->race, is_boss(src));
2963                battle_delay_damage(tick, wd.amotion, target, src, 0, 0, 0, rdamage, ATK_DEF, rdelay);
2964        }
2965
2966        if (tsc) {
2967                if (tsc->data[SC_POISONREACT] && 
2968                        (rand()%100 < tsc->data[SC_POISONREACT]->val3
2969                        || sstatus->def_ele == ELE_POISON) &&
2970//                      check_distance_bl(src, target, tstatus->rhw.range+1) && Doesn't checks range! o.O;
2971                        status_check_skilluse(target, src, TF_POISON, 0)
2972                ) {     //Poison React
2973                        struct status_change_entry *sce = tsc->data[SC_POISONREACT];
2974                        if (sstatus->def_ele == ELE_POISON) {
2975                                sce->val2 = 0;
2976                                skill_attack(BF_WEAPON,target,target,src,AS_POISONREACT,sce->val1,tick,0);
2977                        } else {
2978                                skill_attack(BF_WEAPON,target,target,src,TF_POISON, 5, tick, 0);
2979                                --sce->val2;
2980                        }
2981                        if (sce->val2 <= 0)
2982                                status_change_end(target, SC_POISONREACT, -1);
2983                }
2984        }
2985        map_freeblock_unlock();
2986        return wd.dmg_lv;
2987}
2988
2989int battle_check_undead(int race,int element)
2990{
2991        if(battle_config.undead_detect_type == 0) {
2992                if(element == ELE_UNDEAD)
2993                        return 1;
2994        }
2995        else if(battle_config.undead_detect_type == 1) {
2996                if(race == RC_UNDEAD)
2997                        return 1;
2998        }
2999        else {
3000                if(element == ELE_UNDEAD || race == RC_UNDEAD)
3001                        return 1;
3002        }
3003        return 0;
3004}
3005
3006//Returns the upmost level master starting with the given object
3007struct block_list* battle_get_master(struct block_list *src)
3008{
3009        struct block_list *prev; //Used for infinite loop check (master of yourself?)
3010        do {
3011                prev = src;
3012                switch (src->type) {
3013                        case BL_PET:
3014                                if (((TBL_PET*)src)->msd)
3015                                        src = (struct block_list*)((TBL_PET*)src)->msd;
3016                                break;
3017                        case BL_MOB:
3018                                if (((TBL_MOB*)src)->master_id)
3019                                        src = map_id2bl(((TBL_MOB*)src)->master_id);
3020                                break;
3021                        case BL_HOM:
3022                                if (((TBL_HOM*)src)->master)
3023                                        src = (struct block_list*)((TBL_HOM*)src)->master;
3024                                break;
3025                        case BL_SKILL:
3026                                if (((TBL_SKILL*)src)->group && ((TBL_SKILL*)src)->group->src_id)
3027                                        src = map_id2bl(((TBL_SKILL*)src)->group->src_id);
3028                                break;
3029                }
3030        } while (src && src != prev);
3031        return prev;
3032}
3033
3034/*==========================================
3035 * Checks the state between two targets (rewritten by Skotlex)
3036 * (enemy, friend, party, guild, etc)
3037 * See battle.h for possible values/combinations
3038 * to be used here (BCT_* constants)
3039 * Return value is:
3040 * 1: flag holds true (is enemy, party, etc)
3041 * -1: flag fails
3042 * 0: Invalid target (non-targetable ever)
3043 *------------------------------------------*/
3044int battle_check_target( struct block_list *src, struct block_list *target,int flag)
3045{
3046        int m,state = 0; //Initial state none
3047        int strip_enemy = 1; //Flag which marks whether to remove the BCT_ENEMY status if it's also friend/ally.
3048        struct block_list *s_bl= src, *t_bl= target;
3049
3050        nullpo_retr(0, src);
3051        nullpo_retr(0, target);
3052
3053        m = target->m;
3054        if (flag&BCT_ENEMY && !map_flag_gvg(m) && !(status_get_mode(src)&MD_BOSS))
3055        {       //No offensive stuff while in Basilica.
3056                if (map_getcell(m,src->x,src->y,CELL_CHKBASILICA) ||
3057                        map_getcell(m,target->x,target->y,CELL_CHKBASILICA))
3058                        return -1;
3059        }
3060
3061        //t_bl/s_bl hold the 'master' of the attack, while src/target are the actual
3062        //objects involved.
3063        if ((t_bl = battle_get_master(target)) == NULL)
3064                t_bl = target;
3065
3066        if ((s_bl = battle_get_master(src)) == NULL)
3067                s_bl = src;
3068
3069        switch (target->type)
3070        {       //Checks on actual target
3071                case BL_PC:
3072                        if (((TBL_PC*)target)->invincible_timer != -1 || pc_isinvisible((TBL_PC*)target))
3073                                return -1; //Cannot be targeted yet.
3074                        break;
3075                case BL_MOB:
3076                        if((((TBL_MOB*)target)->special_state.ai == 2 || //Marine Spheres
3077                                (((TBL_MOB*)target)->special_state.ai == 3 && battle_config.summon_flora&1)) && //Floras
3078                                s_bl->type == BL_PC && src->type != BL_MOB)
3079                        {       //Targettable by players
3080                                state |= BCT_ENEMY;
3081                                strip_enemy = 0;
3082                        }
3083                        break;
3084                case BL_SKILL:
3085                {
3086                        TBL_SKILL *su = (TBL_SKILL*)target;
3087                        if (!su->group)
3088                                return 0;
3089                        if (skill_get_inf2(su->group->skill_id)&INF2_TRAP)
3090                        {       //Only a few skills can target traps...
3091                                switch (battle_getcurrentskill(src))
3092                                {
3093                                        case HT_REMOVETRAP:
3094                                        case AC_SHOWER:
3095                                        case WZ_SIGHTRASHER:
3096                                        case WZ_SIGHTBLASTER:
3097                                        case SM_MAGNUM:
3098                                                state |= BCT_ENEMY;
3099                                                strip_enemy = 0;
3100                                                break;
3101                                        default:
3102                                                return 0;
3103                                }
3104                        } else if (su->group->skill_id==WZ_ICEWALL)
3105                        {
3106                                state |= BCT_ENEMY;
3107                                strip_enemy = 0;
3108                        } else  //Excepting traps and icewall, you should not be able to target skills.
3109                                return 0;
3110                }
3111                        break;
3112                //Valid targets with no special checks here.
3113                case BL_HOM:
3114                        break;
3115                //All else not specified is an invalid target.
3116                default:       
3117                        return 0;
3118        }
3119
3120        switch (t_bl->type)
3121        {       //Checks on target master
3122                case BL_PC:
3123                {
3124                        TBL_PC *sd = (TBL_PC*)t_bl;
3125                        if (sd->status.karma && t_bl != s_bl && s_bl->type == BL_PC &&
3126                                ((TBL_PC*)s_bl)->status.karma)
3127                                state |= BCT_ENEMY; //Characters with bad karma may fight amongst them.
3128                        if (sd->state.monster_ignore && t_bl != s_bl && flag&BCT_ENEMY)
3129                                return 0; //Global inmunity to attacks.
3130                        if (sd->state.killable && t_bl != s_bl)
3131                        {
3132                                state |= BCT_ENEMY; //Universal Victim
3133                                strip_enemy = 0;
3134                        }
3135                        // Sketchy - begin
3136                if (sd->state.god && t_bl != s_bl && s_bl->type == BL_PC && ((TBL_PC*)s_bl)->state.demon && map[m].flag.hostile) {
3137                state |= BCT_ENEMY;
3138                strip_enemy = 0;
3139                }
3140
3141                if (sd->state.demon && t_bl != s_bl && s_bl->type == BL_PC && ((TBL_PC*)s_bl)->state.god && map[m].flag.hostile) {
3142                state |= BCT_ENEMY;
3143                strip_enemy = 0;
3144                }
3145                // Sketchy -end
3146                        break;
3147                }
3148                case BL_MOB:
3149                {
3150                        TBL_MOB *md = (TBL_MOB*)t_bl;
3151
3152                        if (!(agit_flag && map[m].flag.gvg_castle) && md->guardian_data && md->guardian_data->guild_id)
3153                                return 0; //Disable guardians/emperiums owned by Guilds on non-woe times.
3154
3155                        if( md->barricade && !md->barricade->killable )
3156                                return 0;
3157                        break;
3158                }
3159        }
3160
3161        switch(src->type)
3162        {       //Checks on actual src type
3163                case BL_PET:
3164                        if (t_bl->type != BL_MOB && flag&BCT_ENEMY)
3165                                return 0; //Pet may not attack non-mobs.
3166                        if (t_bl->type == BL_MOB && ((TBL_MOB*)t_bl)->guardian_data && flag&BCT_ENEMY)
3167                                return 0; //pet may not attack Guardians/Emperium
3168                        break;
3169                case BL_SKILL:
3170                {
3171                        struct skill_unit *su = (struct skill_unit *)src;
3172                        if (!su->group)
3173                                return 0;
3174
3175                        if (su->group->src_id == target->id)
3176                        {
3177                                int inf2;
3178                                inf2 = skill_get_inf2(su->group->skill_id);
3179                                if (inf2&INF2_NO_TARGET_SELF)
3180                                        return -1;
3181                                if (inf2&INF2_TARGET_SELF)
3182                                        return 1;
3183                        }
3184                        break;
3185                }
3186        }
3187
3188        switch (s_bl->type)
3189        {       //Checks on source master
3190                case BL_PC:
3191                {
3192                        TBL_PC *sd = (TBL_PC*) s_bl;
3193                        if( s_bl != t_bl )
3194                        {
3195                                if( sd->state.killer )
3196                                {
3197                                        state |= BCT_ENEMY; //Is on a killing rampage :O
3198                                        strip_enemy = 0;
3199                                }
3200                                else if( sd->duel_group && !((!battle_config.duel_allow_pvp && map[m].flag.pvp) || (!battle_config.duel_allow_gvg && map_flag_gvg(m))) )
3201                                {
3202                                        if (t_bl->type == BL_PC &&
3203                                                (sd->duel_group == ((TBL_PC*)t_bl)->duel_group))
3204                                                //Duel targets can ONLY be your enemy, nothing else.
3205                                                return (BCT_ENEMY&flag)?1:-1;
3206                                        else // You can't target anything out of your duel
3207                                                return 0;
3208                                }
3209                        }
3210                        if (map_flag_gvg(m) && !sd->status.guild_id &&
3211                                t_bl->type == BL_MOB && ((TBL_MOB*)t_bl)->guardian_data)
3212                                return 0; //If you don't belong to a guild, can't target guardians/emperium.
3213                        if (t_bl->type != BL_PC)
3214                                state |= BCT_ENEMY; //Natural enemy.
3215                        break;
3216                }
3217                case BL_MOB:
3218                {
3219                        TBL_MOB*md = (TBL_MOB*)s_bl;
3220                        if (!(agit_flag && map[m].flag.gvg_castle) && md->guardian_data && md->guardian_data->guild_id)
3221                                return 0; //Disable guardians/emperium owned by Guilds on non-woe times.
3222                        if(md->state.killer/* || !(battle_config.mob_ai&0x400)*/)
3223                                state |= BCT_ENEMY; //By default everyone hates mobs.
3224                        else
3225                        {       //Smart enemy criteria.
3226                                if (!md->special_state.ai) { //Normal mobs.
3227                                        if (t_bl->type == BL_MOB && !((TBL_MOB*)t_bl)->special_state.ai)
3228                                                state |= BCT_PARTY; //Normal mobs with no ai are friends.
3229                                        else
3230                                                state |= BCT_ENEMY; //However, all else are enemies.
3231                                } else {
3232                                        if (t_bl->type == BL_MOB && !((TBL_MOB*)t_bl)->special_state.ai)
3233                                                state |= BCT_ENEMY; //Natural enemy for AI mobs are normal mobs.
3234                                }
3235                        }
3236                        break;
3237                }
3238                default:
3239                //Need some sort of default behaviour for unhandled types.
3240                        if (t_bl->type != s_bl->type)
3241                                state |= BCT_ENEMY;
3242                        break;
3243        }
3244       
3245        if ((flag&BCT_ALL) == BCT_ALL) { //All actually stands for all attackable chars
3246                if (target->type&BL_CHAR)
3247                        return 1;
3248                else
3249                        return -1;
3250        } else
3251        if (flag == BCT_NOONE) //Why would someone use this? no clue.
3252                return -1;
3253       
3254        if (t_bl == s_bl)
3255        {       //No need for further testing.
3256                state |= BCT_SELF|BCT_PARTY|BCT_GUILD;
3257                if (state&BCT_ENEMY && strip_enemy)
3258                        state&=~BCT_ENEMY;
3259                return (flag&state)?1:-1;
3260        }
3261       
3262        if (map_flag_vs(m)) { //Check rivalry settings.
3263                if (flag&(BCT_PARTY|BCT_ENEMY)) {
3264                        int s_party = status_get_party_id(s_bl);
3265                        if (
3266                                !(map[m].flag.pvp && map[m].flag.pvp_noparty) &&
3267                                !(map_flag_gvg(m) && map[m].flag.gvg_noparty) &&
3268                                s_party && s_party == status_get_party_id(t_bl)
3269                        )
3270                                state |= BCT_PARTY;
3271                        else
3272                                state |= BCT_ENEMY;
3273                }
3274                if (flag&(BCT_GUILD|BCT_ENEMY)) {
3275                        int s_guild = status_get_guild_id(s_bl);
3276                        int t_guild = status_get_guild_id(t_bl);
3277                        if (
3278                                !(map[m].flag.pvp && map[m].flag.pvp_noguild) &&
3279                                s_guild && t_guild && (s_guild == t_guild || guild_isallied(s_guild, t_guild))
3280                        )
3281                                state |= BCT_GUILD;
3282                        else
3283                                state |= BCT_ENEMY;
3284                }
3285                if (state&BCT_ENEMY && battle_config.pk_mode && !map_flag_gvg(m) &&
3286                        s_bl->type == BL_PC && t_bl->type == BL_PC)
3287                {       //Prevent novice engagement on pk_mode (feature by Valaris)
3288                        TBL_PC *sd = (TBL_PC*)s_bl, *sd2 = (TBL_PC*)t_bl;
3289                        if (
3290                                (sd->class_&MAPID_UPPERMASK) == MAPID_NOVICE ||
3291                                (sd2->class_&MAPID_UPPERMASK) == MAPID_NOVICE ||
3292                                (int)sd->status.base_level < battle_config.pk_min_level ||
3293                                (int)sd2->status.base_level < battle_config.pk_min_level ||
3294                                (battle_config.pk_level_range && abs((int)sd->status.base_level - (int)sd2->status.base_level) > battle_config.pk_level_range)
3295                        )
3296                                state&=~BCT_ENEMY;
3297                }
3298        } else { //Non pvp/gvg, check party/guild settings.
3299                if (flag&BCT_PARTY || state&BCT_ENEMY) {
3300                        int s_party = status_get_party_id(s_bl);
3301                        if(s_party && s_party == status_get_party_id(t_bl))
3302                                state |= BCT_PARTY;
3303                }
3304                if (flag&BCT_GUILD || state&BCT_ENEMY) {
3305                        int s_guild = status_get_guild_id(s_bl);
3306                        int t_guild = status_get_guild_id(t_bl);
3307                        if(s_guild && t_guild && (s_guild == t_guild || guild_isallied(s_guild, t_guild)))
3308                                state |= BCT_GUILD;
3309                }
3310        }
3311       
3312        if (!state) //If not an enemy, nor a guild, nor party, nor yourself, it's neutral.
3313                state = BCT_NEUTRAL;
3314        //Alliance state takes precedence over enemy one.
3315        else if (state&BCT_ENEMY && strip_enemy && state&(BCT_SELF|BCT_PARTY|BCT_GUILD))
3316                state&=~BCT_ENEMY;
3317
3318        return (flag&state)?1:-1;
3319}
3320/*==========================================
3321 * ŽË’ö”»’è
3322 *------------------------------------------*/
3323bool battle_check_range(struct block_list *src,struct block_list *bl,int range)
3324{
3325        int d;
3326        nullpo_retr(false, src);
3327        nullpo_retr(false, bl);
3328
3329        if(src->m != bl->m)     // ˆá‚€ƒ}ƒbƒv
3330                return false;
3331
3332        if (!check_distance_bl(src, bl, range))
3333                return false;
3334
3335        if((d=distance_bl(src, bl)) < 2) //No need for path checking.
3336                return true;
3337
3338        if (d> AREA_SIZE)
3339                return false; //Avoid targetting objects beyond your range of sight.
3340
3341        // ?áŠQ•š”»’è
3342        return path_search_long(NULL,src->m,src->x,src->y,bl->x,bl->y,CELL_CHKWALL);
3343}
3344
3345static const struct _battle_data {
3346        const char* str;
3347        int* val;
3348        int defval;
3349        int min;
3350        int max;
3351} battle_data[] = {
3352        { "warp_point_debug",                   &battle_config.warp_point_debug,                0,      0,      1,              },
3353        { "enable_critical",                    &battle_config.enable_critical,                 BL_PC,  BL_NUL, BL_ALL,         },
3354        { "mob_critical_rate",                  &battle_config.mob_critical_rate,               100,    0,      INT_MAX,        },
3355        { "critical_rate",                      &battle_config.critical_rate,                   100,    0,      INT_MAX,        },
3356        { "enable_baseatk",                     &battle_config.enable_baseatk,                  BL_PC|BL_HOM, BL_NUL, BL_ALL,   },
3357        { "enable_perfect_flee",                &battle_config.enable_perfect_flee,             BL_PC|BL_PET, BL_NUL, BL_ALL,   },
3358        { "casting_rate",                       &battle_config.cast_rate,                       100,    0,      INT_MAX,        },
3359        { "delay_rate",                         &battle_config.delay_rate,                      100,    0,      INT_MAX,        },
3360        { "delay_dependon_dex",                 &battle_config.delay_dependon_dex,              0,      0,      1,              },
3361        { "delay_dependon_agi",                 &battle_config.delay_dependon_agi,              0,      0,      1,              },
3362        { "skill_delay_attack_enable",          &battle_config.sdelay_attack_enable,            0,      0,      1,              },
3363        { "left_cardfix_to_right",              &battle_config.left_cardfix_to_right,           0,      0,      1,              },
3364        { "skill_add_range",                    &battle_config.skill_add_range,                 0,      0,      INT_MAX,        },
3365        { "skill_out_range_consume",            &battle_config.skill_out_range_consume,         1,      0,      1,              },
3366        { "skillrange_by_distance",             &battle_config.skillrange_by_distance,          ~BL_PC, BL_NUL, BL_ALL,         },
3367        { "skillrange_from_weapon",             &battle_config.use_weapon_skill_range,          ~BL_PC, BL_NUL, BL_ALL,         },
3368        { "player_damage_delay_rate",           &battle_config.pc_damage_delay_rate,            100,    0,      INT_MAX,        },
3369        { "defunit_not_enemy",                  &battle_config.defnotenemy,                     0,      0,      1,              },
3370        { "gvg_traps_target_all",               &battle_config.vs_traps_bctall,                 BL_PC,  BL_NUL, BL_ALL,         },
3371        { "traps_setting",                      &battle_config.traps_setting,                   0,      0,      1,              },
3372        { "summon_flora_setting",               &battle_config.summon_flora,                    1|2,    0,      1|2,            },
3373        { "clear_skills_on_death",              &battle_config.clear_unit_ondeath,              BL_NUL, BL_NUL, BL_ALL,         },
3374        { "clear_skills_on_warp",               &battle_config.clear_unit_onwarp,               BL_ALL, BL_NUL, BL_ALL,         },
3375        { "random_monster_checklv",             &battle_config.random_monster_checklv,          1,      0,      1,              },
3376        { "attribute_recover",                  &battle_config.attr_recover,                    1,      0,      1,              },
3377        { "flooritem_lifetime",                 &battle_config.flooritem_lifetime,              60000,  1000,   INT_MAX,        },
3378        { "item_auto_get",                      &battle_config.item_auto_get,                   0,      0,      1,              },
3379        { "item_first_get_time",                &battle_config.item_first_get_time,             3000,   0,      INT_MAX,        },
3380        { "item_second_get_time",               &battle_config.item_second_get_time,            1000,   0,      INT_MAX,        },
3381        { "item_third_get_time",                &battle_config.item_third_get_time,             1000,   0,      INT_MAX,        },
3382        { "mvp_item_first_get_time",            &battle_config.mvp_item_first_get_time,         10000,  0,      INT_MAX,        },
3383        { "mvp_item_second_get_time",           &battle_config.mvp_item_second_get_time,        10000,  0,      INT_MAX,        },
3384        { "mvp_item_third_get_time",            &battle_config.mvp_item_third_get_time,         2000,   0,      INT_MAX,        },
3385        { "drop_rate0item",                     &battle_config.drop_rate0item,                  0,      0,      1,              },
3386        { "base_exp_rate",                      &battle_config.base_exp_rate,                   100,    0,      INT_MAX,        },
3387        { "job_exp_rate",                       &battle_config.job_exp_rate,                    100,    0,      INT_MAX,        },
3388        { "pvp_exp",                            &battle_config.pvp_exp,                         1,      0,      1,              },
3389        { "death_penalty_type",                 &battle_config.death_penalty_type,              0,      0,      2,              },
3390        { "death_penalty_base",                 &battle_config.death_penalty_base,              0,      0,      INT_MAX,        },
3391        { "death_penalty_job",                  &battle_config.death_penalty_job,               0,      0,      INT_MAX,        },
3392        { "zeny_penalty",                       &battle_config.zeny_penalty,                    0,      0,      INT_MAX,        },
3393        { "hp_rate",                            &battle_config.hp_rate,                         100,    1,      INT_MAX,        },
3394        { "sp_rate",                            &battle_config.sp_rate,                         100,    1,      INT_MAX,        },
3395        { "restart_hp_rate",                    &battle_config.restart_hp_rate,                 0,      0,      100,            },
3396        { "restart_sp_rate",                    &battle_config.restart_sp_rate,                 0,      0,      100,            },
3397        { "guild_aura",                         &battle_config.guild_aura,                      31,     0,      31,             },
3398        { "mvp_hp_rate",                        &battle_config.mvp_hp_rate,                     100,    1,      INT_MAX,        },
3399        { "mvp_exp_rate",                       &battle_config.mvp_exp_rate,                    100,    0,      INT_MAX,        },
3400        { "monster_hp_rate",                    &battle_config.monster_hp_rate,                 100,    1,      INT_MAX,        },
3401        { "monster_max_aspd",                   &battle_config.monster_max_aspd,                199,    100,    199,            },
3402        { "view_range_rate",                    &battle_config.view_range_rate,                 100,    0,      INT_MAX,        },
3403        { "chase_range_rate",                   &battle_config.chase_range_rate,                100,    0,      INT_MAX,        },
3404        { "gtb_sc_immunity",                    &battle_config.gtb_sc_immunity,                 50,     0,      INT_MAX,        },
3405        { "guild_max_castles",                  &battle_config.guild_max_castles,               0,      0,      INT_MAX,        },
3406        { "guild_skill_relog_delay",            &battle_config.guild_skill_relog_delay,         0,      0,      1,              },
3407        { "emergency_call",                     &battle_config.emergency_call,                  11,     0,      31,             },
3408        { "atcommand_gm_only",                  &battle_config.atc_gmonly,                      0,      0,      1,              },
3409        { "atcommand_spawn_quantity_limit",     &battle_config.atc_spawn_quantity_limit,        100,    0,      INT_MAX,        },
3410        { "atcommand_slave_clone_limit",        &battle_config.atc_slave_clone_limit,           25,     0,      INT_MAX,        },
3411        { "partial_name_scan",                  &battle_config.partial_name_scan,               0,      0,      1,              },
3412        { "gm_all_skill",                       &battle_config.gm_allskill,                     0,      0,      100,            },
3413        { "gm_all_equipment",                   &battle_config.gm_allequip,                     0,      0,      100,            },
3414        { "gm_skill_unconditional",             &battle_config.gm_skilluncond,                  0,      0,      100,            },
3415        { "gm_join_chat",                       &battle_config.gm_join_chat,                    0,      0,      100,            },
3416        { "gm_kick_chat",                       &battle_config.gm_kick_chat,                    0,      0,      100,            },
3417        { "player_skillfree",                   &battle_config.skillfree,                       0,      0,      1,              },
3418        { "player_skillup_limit",               &battle_config.skillup_limit,                   1,      0,      1,              },
3419        { "weapon_produce_rate",                &battle_config.wp_rate,                         100,    0,      INT_MAX,        },
3420        { "potion_produce_rate",                &battle_config.pp_rate,                         100,    0,      INT_MAX,        },
3421        { "monster_active_enable",              &battle_config.monster_active_enable,           1,      0,      1,              },
3422        { "monster_damage_delay_rate",          &battle_config.monster_damage_delay_rate,       100,    0,      INT_MAX,        },
3423        { "monster_loot_type",                  &battle_config.monster_loot_type,               0,      0,      1,              },
3424//      { "mob_skill_use",                      &battle_config.mob_skill_use,                   1,      0,      1,              }, //Deprecated
3425        { "mob_skill_rate",                     &battle_config.mob_skill_rate,                  100,    0,      INT_MAX,        },
3426        { "mob_skill_delay",                    &battle_config.mob_skill_delay,                 100,    0,      INT_MAX,        },
3427        { "mob_count_rate",                     &battle_config.mob_count_rate,                  100,    0,      INT_MAX,        },
3428        { "mob_spawn_delay",                    &battle_config.mob_spawn_delay,                 100,    0,      INT_MAX,        },
3429        { "plant_spawn_delay",                  &battle_config.plant_spawn_delay,               100,    0,      INT_MAX,        },
3430        { "boss_spawn_delay",                   &battle_config.boss_spawn_delay,                100,    0,      INT_MAX,        },
3431        { "no_spawn_on_player",                 &battle_config.no_spawn_on_player,              0,      0,      100,            },
3432        { "force_random_spawn",                 &battle_config.force_random_spawn,              0,      0,      1,              },
3433        { "slaves_inherit_mode",                &battle_config.slaves_inherit_mode,             2,      0,      3,              },
3434        { "slaves_inherit_speed",               &battle_config.slaves_inherit_speed,            3,      0,      3,              },
3435        { "summons_trigger_autospells",         &battle_config.summons_trigger_autospells,      1,      0,      1,              },
3436        { "pc_damage_walk_delay_rate",          &battle_config.pc_walk_delay_rate,              20,     0,      INT_MAX,        },
3437        { "damage_walk_delay_rate",             &battle_config.walk_delay_rate,                 100,    0,      INT_MAX,        },
3438        { "multihit_delay",                     &battle_config.multihit_delay,                  80,     0,      INT_MAX,        },
3439        { "quest_skill_learn",                  &battle_config.quest_skill_learn,               0,      0,      1,              },
3440        { "quest_skill_reset",                  &battle_config.quest_skill_reset,               0,      0,      1,              },
3441        { "basic_skill_check",                  &battle_config.basic_skill_check,               1,      0,      1,              },
3442        { "guild_emperium_check",               &battle_config.guild_emperium_check,            1,      0,      1,              },
3443        { "guild_exp_limit",                    &battle_config.guild_exp_limit,                 50,     0,      99,             },
3444        { "player_invincible_time",             &battle_config.pc_invincible_time,              5000,   0,      INT_MAX,        },
3445        { "pet_catch_rate",                     &battle_config.pet_catch_rate,                  100,    0,      INT_MAX,        },
3446        { "pet_rename",                         &battle_config.pet_rename,                      0,      0,      1,              },
3447        { "pet_friendly_rate",                  &battle_config.pet_friendly_rate,               100,    0,      INT_MAX,        },
3448        { "pet_hungry_delay_rate",              &battle_config.pet_hungry_delay_rate,           100,    10,     INT_MAX,        },
3449        { "pet_hungry_friendly_decrease",       &battle_config.pet_hungry_friendly_decrease,    5,      0,      INT_MAX,        },
3450        { "pet_status_support",                 &battle_config.pet_status_support,              0,      0,      1,              },
3451        { "pet_attack_support",                 &battle_config.pet_attack_support,              0,      0,      1,              },
3452        { "pet_damage_support",                 &battle_config.pet_damage_support,              0,      0,      1,              },
3453        { "pet_support_min_friendly",           &battle_config.pet_support_min_friendly,        900,    0,      950,            },
3454        { "pet_support_rate",                   &battle_config.pet_support_rate,                100,    0,      INT_MAX,        },
3455        { "pet_attack_exp_to_master",           &battle_config.pet_attack_exp_to_master,        0,      0,      1,              },
3456        { "pet_attack_exp_rate",                &battle_config.pet_attack_exp_rate,             100,    0,      INT_MAX,        },
3457        { "pet_lv_rate",                        &battle_config.pet_lv_rate,                     0,      0,      INT_MAX,        },
3458        { "pet_max_stats",                      &battle_config.pet_max_stats,                   99,     0,      INT_MAX,        },
3459        { "pet_max_atk1",                       &battle_config.pet_max_atk1,                    750,    0,      INT_MAX,        },
3460        { "pet_max_atk2",                       &battle_config.pet_max_atk2,                    1000,   0,      INT_MAX,        },
3461        { "pet_disable_in_gvg",                 &battle_config.pet_no_gvg,                      0,      0,      1,              },
3462        { "skill_min_damage",                   &battle_config.skill_min_damage,                2|4,    0,      1|2|4,          },
3463        { "finger_offensive_type",              &battle_config.finger_offensive_type,           0,      0,      1,              },
3464        { "heal_exp",                           &battle_config.heal_exp,                        0,      0,      INT_MAX,        },
3465        { "resurrection_exp",                   &battle_config.resurrection_exp,                0,      0,      INT_MAX,        },
3466        { "shop_exp",                           &battle_config.shop_exp,                        0,      0,      INT_MAX,        },
3467        { "max_heal_lv",                        &battle_config.max_heal_lv,                     11,     1,      INT_MAX,        },
3468        { "max_heal",                           &battle_config.max_heal,                        9999,   0,      INT_MAX,        },
3469        { "combo_delay_rate",                   &battle_config.combo_delay_rate,                100,    0,      INT_MAX,        },
3470        { "item_check",                         &battle_config.item_check,                      0,      0,      1,              },
3471        { "item_use_interval",                  &battle_config.item_use_interval,               100,    0,      INT_MAX,        },
3472        { "wedding_modifydisplay",              &battle_config.wedding_modifydisplay,           0,      0,      1,              },
3473        { "wedding_ignorepalette",              &battle_config.wedding_ignorepalette,           0,      0,      1,              },
3474        { "xmas_ignorepalette",                 &battle_config.xmas_ignorepalette,              0,      0,      1,              },
3475        { "summer_ignorepalette",               &battle_config.summer_ignorepalette,            0,      0,      1,              },
3476        { "natural_healhp_interval",            &battle_config.natural_healhp_interval,         6000,   NATURAL_HEAL_INTERVAL, INT_MAX, },
3477        { "natural_healsp_interval",            &battle_config.natural_healsp_interval,         8000,   NATURAL_HEAL_INTERVAL, INT_MAX, },
3478        { "natural_heal_skill_interval",        &battle_config.natural_heal_skill_interval,     10000,  NATURAL_HEAL_INTERVAL, INT_MAX, },
3479        { "natural_heal_weight_rate",           &battle_config.natural_heal_weight_rate,        50,     50,     101             },
3480        { "arrow_decrement",                    &battle_config.arrow_decrement,                 1,      0,      2,              },
3481        { "max_aspd",                           &battle_config.max_aspd,                        199,    100,    199,            },
3482        { "max_walk_speed",                     &battle_config.max_walk_speed,                  300,    100,    100*DEFAULT_WALK_SPEED, },
3483        { "max_lv",                             &battle_config.max_lv,                          99,     0,      127,            },
3484        { "aura_lv",                            &battle_config.aura_lv,                         99,     0,      INT_MAX,        },
3485        { "max_hp",                             &battle_config.max_hp,                          32500,  100,    1000000000,     },
3486        { "max_sp",                             &battle_config.max_sp,                          32500,  100,    1000000000,     },
3487        { "max_cart_weight",                    &battle_config.max_cart_weight,                 8000,   100,    1000000,        },
3488        { "max_parameter",                      &battle_config.max_parameter,                   99,     10,     10000,          },
3489        { "max_baby_parameter",                 &battle_config.max_baby_parameter,              80,     10,     10000,          },
3490        { "max_def",                            &battle_config.max_def,                         99,     0,      INT_MAX,        },
3491        { "over_def_bonus",                     &battle_config.over_def_bonus,                  0,      0,      1000,           },
3492        { "skill_log",                          &battle_config.skill_log,                       BL_NUL, BL_NUL, BL_ALL,         },
3493        { "battle_log",                         &battle_config.battle_log,                      0,      0,      1,              },
3494        { "save_log",                           &battle_config.save_log,                        0,      0,      1,              },
3495        { "etc_log",                            &battle_config.etc_log,                         1,      0,      1,              },
3496        { "save_clothcolor",                    &battle_config.save_clothcolor,                 1,      0,      1,              },
3497        { "undead_detect_type",                 &battle_config.undead_detect_type,              0,      0,      2,              },
3498        { "auto_counter_type",                  &battle_config.auto_counter_type,               BL_ALL, BL_NUL, BL_ALL,         },
3499        { "min_hitrate",                        &battle_config.min_hitrate,                     5,      0,      100,            },
3500        { "max_hitrate",                        &battle_config.max_hitrate,                     100,    0,      100,            },
3501        { "agi_penalty_target",                 &battle_config.agi_penalty_target,              BL_PC,  BL_NUL, BL_ALL,         },
3502        { "agi_penalty_type",                   &battle_config.agi_penalty_type,                1,      0,      2,              },
3503        { "agi_penalty_count",                  &battle_config.agi_penalty_count,               3,      2,      INT_MAX,        },
3504        { "agi_penalty_num",                    &battle_config.agi_penalty_num,                 10,     0,      INT_MAX,        },
3505        { "agi_penalty_count_lv",               &battle_config.agi_penalty_count_lv,            ATK_FLEE, 0,    INT_MAX,        },
3506        { "vit_penalty_target",                 &battle_config.vit_penalty_target,              BL_PC,  BL_NUL, BL_ALL,         },
3507        { "vit_penalty_type",                   &battle_config.vit_penalty_type,                1,      0,      2,              },
3508        { "vit_penalty_count",                  &battle_config.vit_penalty_count,               3,      2,      INT_MAX,        },
3509        { "vit_penalty_num",                    &battle_config.vit_penalty_num,                 5,      0,      INT_MAX,        },
3510        { "vit_penalty_count_lv",               &battle_config.vit_penalty_count_lv,            ATK_DEF, 0,     INT_MAX,        },
3511        { "weapon_defense_type",                &battle_config.weapon_defense_type,             0,      0,      INT_MAX,        },
3512        { "magic_defense_type",                 &battle_config.magic_defense_type,              0,      0,      INT_MAX,        },
3513        { "skill_reiteration",                  &battle_config.skill_reiteration,               BL_NUL, BL_NUL, BL_ALL,         },
3514        { "skill_nofootset",                    &battle_config.skill_nofootset,                 BL_PC,  BL_NUL, BL_ALL,         },
3515        { "player_cloak_check_type",            &battle_config.pc_cloak_check_type,             1,      0,      1|2|4,          },
3516        { "monster_cloak_check_type",           &battle_config.monster_cloak_check_type,        4,      0,      1|2|4,          },
3517        { "sense_type",                         &battle_config.estimation_type,                 1|2,    0,      1|2,            },
3518        { "gvg_eliminate_time",                 &battle_config.gvg_eliminate_time,              7000,   0,      INT_MAX,        },
3519        { "gvg_short_attack_damage_rate",       &battle_config.gvg_short_damage_rate,           80,     0,      INT_MAX,        },
3520        { "gvg_long_attack_damage_rate",        &battle_config.gvg_long_damage_rate,            80,     0,      INT_MAX,        },
3521        { "gvg_weapon_attack_damage_rate",      &battle_config.gvg_weapon_damage_rate,          60,     0,      INT_MAX,        },
3522        { "gvg_magic_attack_damage_rate",       &battle_config.gvg_magic_damage_rate,           60,     0,      INT_MAX,        },
3523        { "gvg_misc_attack_damage_rate",        &battle_config.gvg_misc_damage_rate,            60,     0,      INT_MAX,        },
3524        { "gvg_flee_penalty",                   &battle_config.gvg_flee_penalty,                20,     0,      INT_MAX,        },
3525        { "pk_short_attack_damage_rate",        &battle_config.pk_short_damage_rate,            80,     0,      INT_MAX,        },
3526        { "pk_long_attack_damage_rate",         &battle_config.pk_long_damage_rate,             70,     0,      INT_MAX,        },
3527        { "pk_weapon_attack_damage_rate",       &battle_config.pk_weapon_damage_rate,           60,     0,      INT_MAX,        },
3528        { "pk_magic_attack_damage_rate",        &battle_config.pk_magic_damage_rate,            60,     0,      INT_MAX,        },
3529        { "pk_misc_attack_damage_rate",         &battle_config.pk_misc_damage_rate,             60,     0,      INT_MAX,        },
3530        { "mob_changetarget_byskill",           &battle_config.mob_changetarget_byskill,        0,      0,      1,              },
3531        { "attack_direction_change",            &battle_config.attack_direction_change,         BL_ALL, BL_NUL, BL_ALL,         },
3532        { "land_skill_limit",                   &battle_config.land_skill_limit,                BL_ALL, BL_NUL, BL_ALL,         },
3533        { "monster_class_change_full_recover",  &battle_config.monster_class_change_recover,    1,      0,      1,              },
3534        { "produce_item_name_input",            &battle_config.produce_item_name_input,         0x1|0x2, 0,     0x9F,           },
3535        { "display_skill_fail",                 &battle_config.display_skill_fail,              2,      0,      1|2|4|8,        },
3536        { "chat_warpportal",                    &battle_config.chat_warpportal,                 0,      0,      1,              },
3537        { "mob_warp",                           &battle_config.mob_warp,                        0,      0,      1|2|4,          },
3538        { "dead_branch_active",                 &battle_config.dead_branch_active,              1,      0,      1,              },
3539        { "vending_max_value",                  &battle_config.vending_max_value,               10000000, 1,    MAX_ZENY,       },
3540        { "vending_over_max",                   &battle_config.vending_over_max,                1,      0,      1,              },
3541        { "show_steal_in_same_party",           &battle_config.show_steal_in_same_party,        0,      0,      1,              },
3542        { "party_hp_mode",                      &battle_config.party_hp_mode,                   0,      0,      1,              },
3543        { "show_party_share_picker",            &battle_config.party_show_share_picker,         0,      0,      1,              },
3544        { "party_update_interval",              &battle_config.party_update_interval,           1000,   100,    INT_MAX,        },
3545        { "party_item_share_type",              &battle_config.party_share_type,                0,      0,      1|2|3,          },
3546        { "attack_attr_none",                   &battle_config.attack_attr_none,                ~BL_PC, BL_NUL, BL_ALL,         },
3547        { "gx_allhit",                          &battle_config.gx_allhit,                       0,      0,      1,              },
3548        { "gx_disptype",                        &battle_config.gx_disptype,                     1,      0,      1,              },
3549        { "devotion_level_difference",          &battle_config.devotion_level_difference,       10,     0,      INT_MAX,        },
3550        { "player_skill_partner_check",         &battle_config.player_skill_partner_check,      1,      0,      1,              },
3551        { "hide_GM_session",                    &battle_config.hide_GM_session,                 0,      0,      1,              },
3552        { "invite_request_check",               &battle_config.invite_request_check,            1,      0,      1,              },
3553        { "skill_removetrap_type",              &battle_config.skill_removetrap_type,           0,      0,      1,              },
3554        { "disp_experience",                    &battle_config.disp_experience,                 0,      0,      1,              },
3555        { "disp_zeny",                          &battle_config.disp_zeny,                       0,      0,      1,              },
3556        { "castle_defense_rate",                &battle_config.castle_defense_rate,             100,    0,      100,            },
3557        { "gm_cant_drop_min_lv",                &battle_config.gm_cant_drop_min_lv,             1,      0,      100,            },
3558        { "gm_cant_drop_max_lv",                &battle_config.gm_cant_drop_max_lv,             0,      0,      100,            },
3559        { "disp_hpmeter",                       &battle_config.disp_hpmeter,                    0,      0,      100,            },
3560        { "bone_drop",                          &battle_config.bone_drop,                       0,      0,      2,              },
3561        { "buyer_name",                         &battle_config.buyer_name,                      1,      0,      1,              },
3562        { "skill_wall_check",                   &battle_config.skill_wall_check,                1,      0,      1,              },
3563        { "cell_stack_limit",                   &battle_config.cell_stack_limit,                1,      1,      255,            },
3564// eAthena additions
3565        { "item_logarithmic_drops",             &battle_config.logarithmic_drops,               0,      0,      1,              },
3566        { "item_drop_common_min",               &battle_config.item_drop_common_min,            1,      1,      10000,          },
3567        { "item_drop_common_max",               &battle_config.item_drop_common_max,            10000,  1,      10000,          },
3568        { "item_drop_equip_min",                &battle_config.item_drop_equip_min,             1,      1,      10000,          },
3569        { "item_drop_equip_max",                &battle_config.item_drop_equip_max,             10000,  1,      10000,          },
3570        { "item_drop_card_min",                 &battle_config.item_drop_card_min,              1,      1,      10000,          },
3571        { "item_drop_card_max",                 &battle_config.item_drop_card_max,              10000,  1,      10000,          },
3572        { "item_drop_mvp_min",                  &battle_config.item_drop_mvp_min,               1,      1,      10000,          },
3573        { "item_drop_mvp_max",                  &battle_config.item_drop_mvp_max,               10000,  1,      10000,          },
3574        { "item_drop_heal_min",                 &battle_config.item_drop_heal_min,              1,      1,      10000,          },
3575        { "item_drop_heal_max",                 &battle_config.item_drop_heal_max,              10000,  1,      10000,          },
3576        { "item_drop_use_min",                  &battle_config.item_drop_use_min,               1,      1,      10000,          },
3577        { "item_drop_use_max",                  &battle_config.item_drop_use_max,               10000,  1,      10000,          },
3578        { "item_drop_add_min",                  &battle_config.item_drop_adddrop_min,           1,      1,      10000,          },
3579        { "item_drop_add_max",                  &battle_config.item_drop_adddrop_max,           10000,  1,      10000,          },
3580        { "item_drop_treasure_min",             &battle_config.item_drop_treasure_min,          1,      1,      10000,          },
3581        { "item_drop_treasure_max",             &battle_config.item_drop_treasure_max,          10000,  1,      10000,          },
3582        { "item_rate_mvp",                      &battle_config.item_rate_mvp,                   100,    0,      1000000,        },
3583        { "item_rate_common",                   &battle_config.item_rate_common,                100,    0,      1000000,        },
3584        { "item_rate_common_boss",              &battle_config.item_rate_common_boss,           100,    0,      1000000,        },
3585        { "item_rate_equip",                    &battle_config.item_rate_equip,                 100,    0,      1000000,        },
3586        { "item_rate_equip_boss",               &battle_config.item_rate_equip_boss,            100,    0,      1000000,        },
3587        { "item_rate_card",                     &battle_config.item_rate_card,                  100,    0,      1000000,        },
3588        { "item_rate_card_boss",                &battle_config.item_rate_card_boss,             100,    0,      1000000,        },
3589        { "item_rate_heal",                     &battle_config.item_rate_heal,                  100,    0,      1000000,        },
3590        { "item_rate_heal_boss",                &battle_config.item_rate_heal_boss,             100,    0,      1000000,        },
3591        { "item_rate_use",                      &battle_config.item_rate_use,                   100,    0,      1000000,        },
3592        { "item_rate_use_boss",                 &battle_config.item_rate_use_boss,              100,    0,      1000000,        },
3593        { "item_rate_adddrop",                  &battle_config.item_rate_adddrop,               100,    0,      1000000,        },
3594        { "item_rate_treasure",                 &battle_config.item_rate_treasure,              100,    0,      1000000,        },
3595        { "prevent_logout",                     &battle_config.prevent_logout,                  10000,  0,      60000,          },
3596        { "alchemist_summon_reward",            &battle_config.alchemist_summon_reward,         1,      0,      2,              },
3597        { "drops_by_luk",                       &battle_config.drops_by_luk,                    0,      0,      INT_MAX,        },
3598        { "drops_by_luk2",                      &battle_config.drops_by_luk2,                   0,      0,      INT_MAX,        },
3599        { "equip_natural_break_rate",           &battle_config.equip_natural_break_rate,        0,      0,      INT_MAX,        },
3600        { "equip_self_break_rate",              &battle_config.equip_self_break_rate,           100,    0,      INT_MAX,        },
3601        { "equip_skill_break_rate",             &battle_config.equip_skill_break_rate,          100,    0,      INT_MAX,        },
3602        { "pk_mode",                            &battle_config.pk_mode,                         0,      0,      1,              },
3603        { "pk_level_range",                     &battle_config.pk_level_range,                  0,      0,      INT_MAX,        },
3604        { "manner_system",                      &battle_config.manner_system,                   0xFFF,  0,      0xFFF,          },
3605        { "pet_equip_required",                 &battle_config.pet_equip_required,              0,      0,      1,              },
3606        { "multi_level_up",                     &battle_config.multi_level_up,                  0,      0,      1,              },
3607        { "max_exp_gain_rate",                  &battle_config.max_exp_gain_rate,               0,      0,      INT_MAX,        },
3608        { "backstab_bow_penalty",               &battle_config.backstab_bow_penalty,            0,      0,      1,              },
3609        { "night_at_start",                     &battle_config.night_at_start,                  0,      0,      1,              },
3610        { "show_mob_info",                      &battle_config.show_mob_info,                   0,      0,      1|2|4,          },
3611        { "ban_hack_trade",                     &battle_config.ban_hack_trade,                  0,      0,      INT_MAX,        },
3612        { "hack_info_GM_level",                 &battle_config.hack_info_GM_level,              60,     0,      100,            },
3613        { "any_warp_GM_min_level",              &battle_config.any_warp_GM_min_level,           20,     0,      100,            },
3614        { "who_display_aid",                    &battle_config.who_display_aid,                 40,     0,      100,            },
3615        { "packet_ver_flag",                    &battle_config.packet_ver_flag,                 0xFFFF, 0x0000, 0xFFFF,         },
3616        { "min_hair_style",                     &battle_config.min_hair_style,                  0,      0,      INT_MAX,        },
3617        { "max_hair_style",                     &battle_config.max_hair_style,                  23,     0,      INT_MAX,        },
3618        { "min_hair_color",                     &battle_config.min_hair_color,                  0,      0,      INT_MAX,        },
3619        { "max_hair_color",                     &battle_config.max_hair_color,                  9,      0,      INT_MAX,        },
3620        { "min_cloth_color",                    &battle_config.min_cloth_color,                 0,      0,      INT_MAX,        },
3621        { "max_cloth_color",                    &battle_config.max_cloth_color,                 4,      0,      INT_MAX,        },
3622        { "pet_hair_style",                     &battle_config.pet_hair_style,                  100,    0,      INT_MAX,        },
3623        { "castrate_dex_scale",                 &battle_config.castrate_dex_scale,              150,    1,      INT_MAX,        },
3624        { "area_size",                          &battle_config.area_size,                       14,     0,      INT_MAX,        },
3625        { "zeny_from_mobs",                     &battle_config.zeny_from_mobs,                  0,      0,      1,              },
3626        { "mobs_level_up",                      &battle_config.mobs_level_up,                   0,      0,      1,              },
3627        { "mobs_level_up_exp_rate",             &battle_config.mobs_level_up_exp_rate,          1,      1,      INT_MAX,        },
3628        { "pk_min_level",                       &battle_config.pk_min_level,                    55,     1,      INT_MAX,        },
3629        { "skill_steal_max_tries",              &battle_config.skill_steal_max_tries,           0,      0,      UCHAR_MAX,      },
3630        { "motd_type",                          &battle_config.motd_type,                       0,      0,      1,              },
3631        { "finding_ore_rate",                   &battle_config.finding_ore_rate,                100,    0,      INT_MAX,        },
3632        { "exp_calc_type",                      &battle_config.exp_calc_type,                   0,      0,      1,              },
3633        { "exp_bonus_attacker",                 &battle_config.exp_bonus_attacker,              25,     0,      INT_MAX,        },
3634        { "exp_bonus_max_attacker",             &battle_config.exp_bonus_max_attacker,          12,     2,      INT_MAX,        },
3635        { "min_skill_delay_limit",              &battle_config.min_skill_delay_limit,           100,    10,     INT_MAX,        },
3636        { "default_walk_delay",                 &battle_config.default_walk_delay,              300,    0,      INT_MAX,        },
3637        { "no_skill_delay",                     &battle_config.no_skill_delay,                  BL_MOB, BL_NUL, BL_ALL,         },
3638        { "attack_walk_delay",                  &battle_config.attack_walk_delay,               BL_ALL, BL_NUL, BL_ALL,         },
3639        { "require_glory_guild",                &battle_config.require_glory_guild,             0,      0,      1,              },
3640        { "idle_no_share",                      &battle_config.idle_no_share,                   0,      0,      INT_MAX,        },
3641        { "party_even_share_bonus",             &battle_config.party_even_share_bonus,          0,      0,      INT_MAX,        }, 
3642        { "delay_battle_damage",                &battle_config.delay_battle_damage,             1,      0,      1,              },
3643        { "hide_woe_damage",                    &battle_config.hide_woe_damage,                 0,      0,      1,              },
3644        { "display_version",                    &battle_config.display_version,                 1,      0,      1,              },
3645        { "display_hallucination",              &battle_config.display_hallucination,           1,      0,      1,              },
3646        { "use_statpoint_table",                &battle_config.use_statpoint_table,             1,      0,      1,              },
3647        { "ignore_items_gender",                &battle_config.ignore_items_gender,             1,      0,      1,              },
3648        { "copyskill_restrict",                 &battle_config.copyskill_restrict,              2,      0,      2,              },
3649        { "berserk_cancels_buffs",              &battle_config.berserk_cancels_buffs,           0,      0,      1,              },
3650        { "debuff_on_logout",                   &battle_config.debuff_on_logout,                1|2,    0,      1|2,            },
3651        { "monster_ai",                         &battle_config.mob_ai,                          0x000,  0x000,  0x77F,          },
3652        { "hom_setting",                        &battle_config.hom_setting,                     0xFFFF, 0x0000, 0xFFFF,         },
3653        { "dynamic_mobs",                       &battle_config.dynamic_mobs,                    1,      0,      1,              },
3654        { "mob_remove_damaged",                 &battle_config.mob_remove_damaged,              1,      0,      1,              },
3655        { "show_hp_sp_drain",                   &battle_config.show_hp_sp_drain,                0,      0,      1,              },
3656        { "show_hp_sp_gain",                    &battle_config.show_hp_sp_gain,                 1,      0,      1,              },
3657        { "mob_npc_event_type",                 &battle_config.mob_npc_event_type,              1,      0,      1,              },
3658        { "mob_clear_delay",                    &battle_config.mob_clear_delay,                 0,      0,      INT_MAX,        },
3659        { "character_size",                     &battle_config.character_size,                  1|2,    0,      1|2,            },
3660        { "mob_max_skilllvl",                   &battle_config.mob_max_skilllvl,                MAX_SKILL_LEVEL, 1, MAX_SKILL_LEVEL, },
3661        { "retaliate_to_master",                &battle_config.retaliate_to_master,             1,      0,      1,              },
3662        { "rare_drop_announce",                 &battle_config.rare_drop_announce,              0,      0,      10000,          },
3663        { "title_lvl1",                         &battle_config.title_lvl1,                      1,      0,      100,            },
3664        { "title_lvl2",                         &battle_config.title_lvl2,                      10,     0,      100,            },
3665        { "title_lvl3",                         &battle_config.title_lvl3,                      20,     0,      100,            },
3666        { "title_lvl4",                         &battle_config.title_lvl4,                      40,     0,      100,            },
3667        { "title_lvl5",                         &battle_config.title_lvl5,                      50,     0,      100,            },
3668        { "title_lvl6",                         &battle_config.title_lvl6,                      60,     0,      100,            },
3669        { "title_lvl7",                         &battle_config.title_lvl7,                      80,     0,      100,            },
3670        { "title_lvl8",                         &battle_config.title_lvl8,                      99,     0,      100,            },
3671        { "duel_allow_pvp",                     &battle_config.duel_allow_pvp,                  0,      0,      1,              },
3672        { "duel_allow_gvg",                     &battle_config.duel_allow_gvg,                  0,      0,      1,              },
3673        { "duel_allow_teleport",                &battle_config.duel_allow_teleport,             0,      0,      1,              },
3674        { "duel_autoleave_when_die",            &battle_config.duel_autoleave_when_die,         1,      0,      1,              },
3675        { "duel_time_interval",                 &battle_config.duel_time_interval,              60,     0,      INT_MAX,        },
3676        { "duel_only_on_same_map",              &battle_config.duel_only_on_same_map,           0,      0,      1,              },
3677        { "skip_teleport_lv1_menu",             &battle_config.skip_teleport_lv1_menu,          0,      0,      1,              },
3678        { "allow_skill_without_day",            &battle_config.allow_skill_without_day,         0,      0,      1,              },
3679        { "allow_es_magic_player",              &battle_config.allow_es_magic_pc,               0,      0,      1,              },
3680        { "skill_caster_check",                 &battle_config.skill_caster_check,              1,      0,      1,              },
3681        { "status_cast_cancel",                 &battle_config.sc_castcancel,                   BL_NUL, BL_NUL, BL_ALL,         },
3682        { "pc_status_def_rate",                 &battle_config.pc_sc_def_rate,                  100,    0,      INT_MAX,        },
3683        { "mob_status_def_rate",                &battle_config.mob_sc_def_rate,                 100,    0,      INT_MAX,        },
3684        { "pc_luk_status_def",                  &battle_config.pc_luk_sc_def,                   300,    1,      INT_MAX,        },
3685        { "mob_luk_status_def",                 &battle_config.mob_luk_sc_def,                  300,    1,      INT_MAX,        },
3686        { "pc_max_status_def",                  &battle_config.pc_max_sc_def,                   100,    0,      INT_MAX,        },
3687        { "mob_max_status_def",                 &battle_config.mob_max_sc_def,                  100,    0,      INT_MAX,        },
3688        { "sg_miracle_skill_ratio",             &battle_config.sg_miracle_skill_ratio,          1,      0,      10000,          },
3689        { "sg_angel_skill_ratio",               &battle_config.sg_angel_skill_ratio,            10,     0,      10000,          },
3690        { "autospell_stacking",                 &battle_config.autospell_stacking,              0,      0,      1,              },
3691        { "override_mob_names",                 &battle_config.override_mob_names,              0,      0,      2,              },
3692        { "min_chat_delay",                     &battle_config.min_chat_delay,                  0,      0,      INT_MAX,        },
3693        { "friend_auto_add",                    &battle_config.friend_auto_add,                 1,      0,      1,              },
3694        { "hom_rename",                         &battle_config.hom_rename,                      0,      0,      1,              },
3695        { "homunculus_show_growth",             &battle_config.homunculus_show_growth,          0,      0,      1,              },
3696        { "homunculus_friendly_rate",           &battle_config.homunculus_friendly_rate,        100,    0,      INT_MAX,        },
3697        { "vending_tax",                        &battle_config.vending_tax,                     0,      0,      10000,          },
3698        { "day_duration",                       &battle_config.day_duration,                    0,      0,      INT_MAX,        },
3699        { "night_duration",                     &battle_config.night_duration,                  0,      0,      INT_MAX,        },
3700        { "mob_remove_delay",                   &battle_config.mob_remove_delay,                60000,  1000,   INT_MAX,        },
3701        { "mob_active_time",                    &battle_config.mob_active_time,                 0,      0,      INT_MAX,        },
3702        { "boss_active_time",                   &battle_config.boss_active_time,                0,      0,      INT_MAX,        },
3703        { "sg_miracle_skill_duration",          &battle_config.sg_miracle_skill_duration,       3600000, 0,     INT_MAX,        },
3704        { "hvan_explosion_intimate",            &battle_config.hvan_explosion_intimate,         45000,  0,      100000,         },
3705        { "quest_exp_rate",                     &battle_config.quest_exp_rate,                  100,    0,      INT_MAX,        },
3706        { "at_mapflag",                         &battle_config.autotrade_mapflag,               0,      0,      1,              },
3707        { "at_timeout",                         &battle_config.at_timeout,                      0,      0,      INT_MAX,        },
3708        { "homunculus_autoloot",                &battle_config.homunculus_autoloot,             0,      0,      1,              },
3709        { "idle_no_autoloot",                   &battle_config.idle_no_autoloot,                0,      0,      INT_MAX,        },
3710        { "max_guild_alliance",                 &battle_config.max_guild_alliance,              3,      1,      3,              },
3711        { "ksprotection",                       &battle_config.ksprotection,                    5000,   0,      INT_MAX,        },
3712        { "auction_feeperhour",                 &battle_config.auction_feeperhour,              12000,  0,      INT_MAX,        },
3713        { "auction_maximumprice",               &battle_config.auction_maximumprice,            500000000, 0,   MAX_ZENY,       },
3714        { "gm_viewequip_min_lv",                &battle_config.gm_viewequip_min_lv,             0,      0,      99,             },
3715};
3716
3717
3718int battle_set_value(const char* w1, const char* w2)
3719{
3720        int val = config_switch(w2);
3721
3722        int i;
3723        ARR_FIND(0, ARRAYLENGTH(battle_data), i, strcmpi(w1, battle_data[i].str) == 0);
3724        if (i == ARRAYLENGTH(battle_data))
3725                return 0; // not found
3726
3727        if (val < battle_data[i].min || val > battle_data[i].max)
3728        {
3729                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);
3730                val = battle_data[i].defval;
3731        }
3732
3733        *battle_data[i].val = val;
3734        return 1;
3735}
3736
3737int battle_get_value(const char* w1)
3738{
3739        int i;
3740        ARR_FIND(0, ARRAYLENGTH(battle_data), i, strcmpi(w1, battle_data[i].str) == 0);
3741        if (i == ARRAYLENGTH(battle_data))
3742                return 0; // not found
3743        else
3744                return *battle_data[i].val;
3745}
3746
3747void battle_set_defaults()
3748{
3749        int i;
3750        for (i = 0; i < ARRAYLENGTH(battle_data); i++)
3751                *battle_data[i].val = battle_data[i].defval;
3752}
3753
3754void battle_adjust_conf()
3755{
3756        battle_config.monster_max_aspd = 2000 - battle_config.monster_max_aspd*10;
3757        battle_config.max_aspd = 2000 - battle_config.max_aspd*10;
3758        battle_config.max_walk_speed = 100*DEFAULT_WALK_SPEED/battle_config.max_walk_speed;     
3759        battle_config.max_cart_weight *= 10;
3760       
3761        if(battle_config.max_def > 100 && !battle_config.weapon_defense_type)    // added by [Skotlex]
3762                battle_config.max_def = 100;
3763
3764        if(battle_config.min_hitrate > battle_config.max_hitrate)
3765                battle_config.min_hitrate = battle_config.max_hitrate;
3766               
3767        if(battle_config.pet_max_atk1 > battle_config.pet_max_atk2)     //Skotlex
3768                battle_config.pet_max_atk1 = battle_config.pet_max_atk2;
3769       
3770        if (battle_config.day_duration && battle_config.day_duration < 60000) // added by [Yor]
3771                battle_config.day_duration = 60000;
3772        if (battle_config.night_duration && battle_config.night_duration < 60000) // added by [Yor]
3773                battle_config.night_duration = 60000;
3774       
3775#ifndef CELL_NOSTACK
3776        if (battle_config.cell_stack_limit != 1)
3777                ShowWarning("Battle setting 'cell_stack_limit' takes no effect as this server was compiled without Cell Stack Limit support.\n");
3778#endif
3779}
3780
3781int battle_config_read(const char* cfgName)
3782{
3783        char line[1024], w1[1024], w2[1024];
3784        FILE* fp;
3785        static int count = 0;
3786
3787        if (count == 0)
3788                battle_set_defaults();
3789
3790        count++;
3791
3792        fp = fopen(cfgName,"r");
3793        if (fp == NULL)
3794                ShowError("File not found: %s\n", cfgName);
3795        else
3796        {
3797                while(fgets(line, sizeof(line), fp))
3798                {
3799                        if (line[0] == '/' && line[1] == '/')
3800                                continue;
3801                        if (sscanf(line, "%1023[^:]:%1023s", w1, w2) != 2)
3802                                continue;
3803                        if (strcmpi(w1, "import") == 0)
3804                                battle_config_read(w2);
3805                        else
3806                        if (battle_set_value(w1, w2) == 0)
3807                                ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName);
3808                }
3809
3810                fclose(fp);
3811        }
3812
3813        count--;
3814
3815        if (count == 0)
3816                battle_adjust_conf();
3817
3818        return 0;
3819}
3820
3821void do_init_battle(void)
3822{
3823        delay_damage_ers = ers_new(sizeof(struct delay_damage));
3824        add_timer_func_list(battle_delay_damage_sub, "battle_delay_damage_sub");
3825}
3826
3827void do_final_battle(void)
3828{
3829        ers_destroy(delay_damage_ers);
3830}
Note: See TracBrowser for help on using the browser.