root/src/map/battle.c @ 21

Revision 19, 153.4 kB (checked in by jinshiro, 17 years ago)

Now Compiles with Cygwin GCC

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