root/src/map/battle.c @ 18

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