root/src/map/battle.c

Revision 24, 154.9 kB (checked in by jinshiro, 17 years ago)
Line 
1// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
2// For more information, see LICENCE in the main folder
3
4#include "../common/cbasetypes.h"
5#include "../common/timer.h"
6#include "../common/nullpo.h"
7#include "../common/malloc.h"
8#include "../common/showmsg.h"
9#include "../common/ers.h"
10#include "../common/strlib.h"
11#include "../common/utils.h"
12
13#include "map.h"
14#include "path.h"
15#include "pc.h"
16#include "status.h"
17#include "skill.h"
18#include "mercenary.h"
19#include "mob.h"
20#include "itemdb.h"
21#include "clif.h"
22#include "pet.h"
23#include "guild.h"
24#include "party.h"
25#include "battle.h"
26
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <math.h>
31
32int attr_fix_table[4][ELE_MAX][ELE_MAX];
33
34struct Battle_Config battle_config;
35static struct eri *delay_damage_ers; //For battle delay damage structures.
36
37int battle_getcurrentskill(struct block_list *bl)
38{       //Returns the current/last skill in use by this bl.
39        struct unit_data *ud;
40
41        if (bl->type == BL_SKILL) {
42                struct skill_unit * su = (struct skill_unit*)bl;
43                return su->group?su->group->skill_id:0;
44        }
45        ud = unit_bl2ud(bl);
46        return ud?ud->skillid:0;
47}
48
49/*==========================================
50 * Get random targetting enemy
51 *------------------------------------------*/
52static int battle_gettargeted_sub(struct block_list *bl, va_list ap)
53{
54        struct block_list **bl_list;
55        struct unit_data *ud;
56        int target_id;
57        int *c;
58
59        bl_list = va_arg(ap, struct block_list **);
60        c = va_arg(ap, int *);
61        target_id = va_arg(ap, int);
62
63        if (bl->id == target_id)
64                return 0;
65        if (*c >= 24)
66                return 0;
67
68        ud = unit_bl2ud(bl);
69        if (!ud) return 0;
70
71        if (ud->target == target_id || ud->skilltarget == target_id) {
72                bl_list[(*c)++] = bl;
73                return 1;
74        }
75        return 0;       
76}
77
78struct block_list* battle_gettargeted(struct block_list *target)
79{
80        struct block_list *bl_list[24];
81        int c = 0;
82        nullpo_retr(NULL, target);
83
84        memset(bl_list, 0, sizeof(bl_list));
85        map_foreachinrange(battle_gettargeted_sub, target, AREA_SIZE, BL_CHAR, bl_list, &c, target->id);
86        if (c == 0 || c > 24)
87                return NULL;
88        return bl_list[rand()%c];
89}
90
91
92//Returns the id of the current targetted character of the passed bl. [Skotlex]
93int battle_gettarget(struct block_list* bl)
94{
95        switch (bl->type)
96        {
97                case BL_PC:  return ((struct map_session_data*)bl)->ud.target;
98                case BL_MOB: return ((struct mob_data*)bl)->target_id;
99                case BL_PET: return ((struct pet_data*)bl)->target_id;
100                case BL_HOM: return ((struct homun_data*)bl)->ud.target;
101        }
102        return 0;
103}
104
105static int battle_getenemy_sub(struct block_list *bl, va_list ap)
106{
107        struct block_list **bl_list;
108        struct block_list *target;
109        int *c;
110
111        bl_list = va_arg(ap, struct block_list **);
112        c = va_arg(ap, int *);
113        target = va_arg(ap, struct block_list *);
114
115        if (bl->id == target->id)
116                return 0;
117        if (*c >= 24)
118                return 0;
119        if (status_isdead(bl))
120                return 0;
121        if (battle_check_target(target, bl, BCT_ENEMY) > 0) {
122                bl_list[(*c)++] = bl;
123                return 1;
124        }
125        return 0;       
126}
127
128// Picks a random enemy of the given type (BL_PC, BL_CHAR, etc) within the range given. [Skotlex]
129struct block_list* battle_getenemy(struct block_list *target, int type, int range)
130{
131        struct block_list *bl_list[24];
132        int c = 0;
133        memset(bl_list, 0, sizeof(bl_list));
134        map_foreachinrange(battle_getenemy_sub, target, range, type, bl_list, &c, target);
135        if (c == 0 || c > 24)
136                return NULL;
137        return bl_list[rand()%c];
138}
139
140// ƒ_ƒ??[ƒ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 //AT Field is Irrelevant, I believe.
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                if (((sce=sc->data[SC_UTSUSEMI]) || sc->data[SC_BUNSINJYUTSU])
400                && 
401                        flag&BF_WEAPON && !(skill_get_nk(skill_num)&NK_NO_CARDFIX_ATK))
402                {
403                        if (sce) {
404                                clif_specialeffect(bl, 462, AREA);
405                                skill_blown(src,bl,sce->val3,-1,0);
406                        }
407                        //Both need to be consumed if they are active.
408                        if (sce && --(sce->val2) <= 0)
409                                status_change_end(bl, SC_UTSUSEMI, -1);
410                        if ((sce=sc->data[SC_BUNSINJYUTSU]) && --(sce->val2) <= 0)
411                                status_change_end(bl, SC_BUNSINJYUTSU, -1);
412                        return 0;
413                }
414
415                //Now damage increasing effects
416                if(sc->data[SC_AETERNA] && skill_num != PF_SOULBURN){
417                        damage<<=1;
418                        //Shouldn't end until Breaker's non-weapon part connects.
419                        if (skill_num != ASC_BREAKER || !(flag&BF_WEAPON))
420                                status_change_end( bl,SC_AETERNA,-1 );
421                }
422
423                //Finally damage reductions....
424                if(sc->data[SC_ASSUMPTIO]){
425                        if(map_flag_vs(bl->m))
426                                damage=damage*2/3; //Receive 66% damage
427                        else
428                                damage>>=1; //Receive 50% damage
429                }
430
431                if(sc->data[SC_DEFENDER] &&
432                        (flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON))
433                        damage=damage*(100-sc->data[SC_DEFENDER]->val2)/100;
434
435                if(sc->data[SC_ADJUSTMENT] &&
436                        (flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON))
437                        damage -= 20*damage/100;
438
439                if(sc->data[SC_FOGWALL]) {
440                        if(flag&BF_SKILL) //25% reduction
441                                damage -= 25*damage/100;
442                        else if ((flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON))
443                                damage >>= 2; //75% reduction
444                }
445
446                if((sce=sc->data[SC_ARMOR]) && //NPC_DEFENDER
447                        sce->val3&flag && sce->val4&flag)
448                        damage -= damage*sc->data[SC_ARMOR]->val2/100;
449
450                if(sc->data[SC_ENERGYCOAT] && flag&BF_WEAPON
451                        && skill_num != WS_CARTTERMINATION)
452                {
453                        struct status_data *status = status_get_status_data(bl);
454                        int per = 100*status->sp / status->max_sp -1; //100% should be counted as the 80~99% interval
455                        per /=20; //Uses 20% SP intervals.
456                        //SP Cost: 1% + 0.5% per every 20% SP
457                        if (!status_charge(bl, 0, (10+5*per)*status->max_sp/1000))
458                                status_change_end( bl,SC_ENERGYCOAT,-1 );
459                        //Reduction: 6% + 6% every 20%
460                        damage -= damage * 6 * (1+per) / 100;
461                }
462
463                if((sce=sc->data[SC_REJECTSWORD]) && flag&BF_WEAPON &&
464                        // Fixed the condition check [Aalye]
465                        (src->type!=BL_PC || (
466                                ((TBL_PC *)src)->status.weapon == W_DAGGER ||
467                                ((TBL_PC *)src)->status.weapon == W_1HSWORD ||
468                                ((TBL_PC *)src)->status.weapon == W_2HSWORD
469                        )) &&
470                        rand()%100 < sce->val2
471                ){
472                        damage = damage*50/100;
473                        status_fix_damage(bl,src,damage,clif_damage(bl,src,gettick(),0,0,damage,0,0,0));
474                        clif_skill_nodamage(bl,bl,ST_REJECTSWORD,sce->val1,1);
475                        if(--(sce->val3)<=0)
476                                status_change_end(bl, SC_REJECTSWORD, -1);
477                }
478
479                //Finally Kyrie because it may, or not, reduce damage to 0.
480                if((sce = sc->data[SC_KYRIE]) && damage > 0){
481                        sce->val2-=damage;
482                        if(flag&BF_WEAPON || skill_num == TF_THROWSTONE){
483                                if(sce->val2>=0)
484                                        damage=0;
485                                else
486                                        damage=-sce->val2;
487                        }
488                        if((--sce->val3)<=0 || (sce->val2<=0) || skill_num == AL_HOLYLIGHT)
489                                status_change_end(bl, SC_KYRIE, -1);
490                }
491
492                if (!damage) return 0;
493
494                //Probably not the most correct place, but it'll do here
495                //(since battle_drain is strictly for players currently)
496                if ((sce=sc->data[SC_BLOODLUST]) && flag&BF_WEAPON && damage > 0 &&
497                        rand()%100 < sce->val3)
498                        status_heal(src, damage*sce->val4/100, 0, 3);
499
500        }
501        //SC effects from caster side. Currently none.
502/*     
503        sc = status_get_sc(src);
504        if (sc && sc->count) {
505        }
506*/     
507        if (battle_config.pk_mode && sd && bl->type == BL_PC && damage)
508        {
509                if (flag & BF_SKILL) { //Skills get a different reduction than non-skills. [Skotlex]
510                        if (flag&BF_WEAPON)
511                                damage = damage * battle_config.pk_weapon_damage_rate/100;
512                        if (flag&BF_MAGIC)
513                                damage = damage * battle_config.pk_magic_damage_rate/100;
514                        if (flag&BF_MISC)
515                                damage = damage * battle_config.pk_misc_damage_rate/100;
516                } else { //Normal attacks get reductions based on range.
517                        if (flag & BF_SHORT)
518                                damage = damage * battle_config.pk_short_damage_rate/100;
519                        if (flag & BF_LONG)
520                                damage = damage * battle_config.pk_long_damage_rate/100;
521                }
522                if(!damage) damage  = 1;
523        }
524
525        if(battle_config.skill_min_damage && damage > 0 && damage < div_)
526        {
527                if ((flag&BF_WEAPON && battle_config.skill_min_damage&1)
528                        || (flag&BF_MAGIC && battle_config.skill_min_damage&2)
529                        || (flag&BF_MISC && battle_config.skill_min_damage&4)
530                )
531                        damage = div_;
532        }
533
534        if( bl->type == BL_MOB && !status_isdead(bl) && src != bl) {
535          if (damage > 0 )
536                        mobskill_event((TBL_MOB*)bl,src,gettick(),flag);
537          if (skill_num)
538                        mobskill_event((TBL_MOB*)bl,src,gettick(),MSC_SKILLUSED|(skill_num<<16));
539        }
540
541        return damage;
542}
543
544/*==========================================
545 * Calculates GVG related damage adjustments.
546 *------------------------------------------*/
547int battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int damage,int div_,int skill_num,int skill_lv,int flag)
548{
549        struct mob_data *md = NULL;
550        int class_;
551
552        if (!damage) //No reductions to make.
553                return 0;
554       
555        class_ = status_get_class(bl);
556
557        if (bl->type == BL_MOB)
558                md=(struct mob_data *)bl;
559       
560        if(md && md->guardian_data) {
561                if(class_ == MOBID_EMPERIUM && flag&BF_SKILL)
562                //Skill immunity.
563                        switch (skill_num) {
564                        case MO_TRIPLEATTACK:
565                        case HW_GRAVITATION:
566                                break;
567                        default:
568                                return 0;
569                }
570                if(src->type != BL_MOB) {
571                        struct guild *g=guild_search(status_get_guild_id(src));
572                        if (!g) return 0;
573                        if (class_ == MOBID_EMPERIUM && guild_checkskill(g,GD_APPROVAL) <= 0)
574                                return 0;
575                        if (battle_config.guild_max_castles &&
576                                guild_checkcastles(g)>=battle_config.guild_max_castles)
577                                return 0; // [MouseJstr]
578                }
579        }
580
581        switch (skill_num) {
582        //Skills with no damage reduction.
583        case PA_PRESSURE:
584        case HW_GRAVITATION:
585        case NJ_ZENYNAGE:
586                break;
587        default:
588                if (md && md->guardian_data) {
589                        damage -= damage * (md->guardian_data->castle->defense/100) * battle_config.castle_defense_rate/100;
590                }
591                if (flag & BF_SKILL) { //Skills get a different reduction than non-skills. [Skotlex]
592                        if (flag&BF_WEAPON)
593                                damage = damage * battle_config.gvg_weapon_damage_rate/100;
594                        if (flag&BF_MAGIC)
595                                damage = damage * battle_config.gvg_magic_damage_rate/100;
596                        if (flag&BF_MISC)
597                                damage = damage * battle_config.gvg_misc_damage_rate/100;
598                } else { //Normal attacks get reductions based on range.
599                        if (flag & BF_SHORT)
600                                damage = damage * battle_config.gvg_short_damage_rate/100;
601                        if (flag & BF_LONG)
602                                damage = damage * battle_config.gvg_long_damage_rate/100;
603                }
604                if(!damage) damage  = 1;
605        }
606        return damage;
607}
608
609/*==========================================
610 * HP/SP‹zŽû‚ÌŒvŽZ
611 *------------------------------------------*/
612static int battle_calc_drain(int damage, int rate, int per)
613{
614        int diff = 0;
615
616        if (per && rand()%1000 < rate) {
617                diff = (damage * per) / 100;
618                if (diff == 0) {
619                        if (per > 0)
620                                diff = 1;
621                        else
622                                diff = -1;
623                }
624        }
625        return diff;
626}
627
628/*==========================================
629 * ?C—ûƒ_ƒ??[ƒW
630 *------------------------------------------*/
631int battle_addmastery(struct map_session_data *sd,struct block_list *target,int dmg,int type)
632{
633        int damage,skill;
634        struct status_data *status = status_get_status_data(target);
635        int weapon;
636        damage = dmg;
637
638        nullpo_retr(0, sd);
639
640        if((skill = pc_checkskill(sd,AL_DEMONBANE)) > 0 &&
641                target->type == BL_MOB && //This bonus doesnt work against players.
642                (battle_check_undead(status->race,status->def_ele) || 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//AMIDOINITRITE?! V seems okay.
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; //I wonder if it will accept that?
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                        }
1610
1611                        ATK_RATE(skillratio);
1612
1613                        //Constant/misc additions from skills
1614                        switch (skill_num) {
1615                                case MO_EXTREMITYFIST:
1616                                        ATK_ADD(250 + 150*skill_lv);
1617                                        break;
1618                                case TK_DOWNKICK:
1619                                case TK_STORMKICK:
1620                                case TK_TURNKICK:
1621                                case TK_COUNTER:
1622                                case TK_JUMPKICK:
1623                                        //TK_RUN kick damage bonus.
1624                                        if(sd && sd->weapontype1 == W_FIST && sd->weapontype2 == W_FIST)
1625                                                ATK_ADD(10*pc_checkskill(sd, TK_RUN));
1626                                        break;
1627                                case GS_MAGICALBULLET:
1628                                        if(sstatus->matk_max>sstatus->matk_min) {
1629                                                ATK_ADD(sstatus->matk_min+rand()%(sstatus->matk_max-sstatus->matk_min));
1630                                        } else {
1631                                                ATK_ADD(sstatus->matk_min);
1632                                        }
1633                                        break;
1634                                case NJ_SYURIKEN:
1635                                        ATK_ADD(4*skill_lv);
1636                                        break;
1637                        }
1638                }
1639                //Div fix.
1640                damage_div_fix(wd.damage, wd.div_);
1641
1642                //The following are applied on top of current damage and are stackable.
1643                if (sc) {
1644                        if(sc->data[SC_TRUESIGHT])
1645                                ATK_ADDRATE(2*sc->data[SC_TRUESIGHT]->val1);
1646
1647                        if(sc->data[SC_EDP] &&
1648                                skill_num != ASC_BREAKER &&
1649                                skill_num != ASC_METEORASSAULT &&
1650                                skill_num != AS_SPLASHER &&
1651                                skill_num != AS_VENOMKNIFE)
1652                                ATK_ADDRATE(sc->data[SC_EDP]->val3);
1653                }
1654
1655                switch (skill_num) {
1656                        case AS_SONICBLOW:
1657                                if (sc && sc->data[SC_SPIRIT] &&
1658                                        sc->data[SC_SPIRIT]->val2 == SL_ASSASIN)
1659                                        ATK_ADDRATE(map_flag_gvg(src->m)?25:100); //+25% dmg on woe/+100% dmg on nonwoe
1660
1661                                if(sd && pc_checkskill(sd,AS_SONICACCEL)>0)
1662                                        ATK_ADDRATE(10);
1663                        break;
1664                        case CR_SHIELDBOOMERANG:
1665                                if(sc && sc->data[SC_SPIRIT] &&
1666                                        sc->data[SC_SPIRIT]->val2 == SL_CRUSADER)
1667                                        ATK_ADDRATE(100);
1668                                break;
1669                }
1670               
1671                if(sd)
1672                {
1673                        if (skill_num && (i = pc_skillatk_bonus(sd, skill_num)))
1674                                ATK_ADDRATE(i);
1675
1676                        if(skill_num != PA_SACRIFICE && skill_num != MO_INVESTIGATE &&
1677                                skill_num != CR_GRANDCROSS && skill_num != NPC_GRANDDARKNESS &&
1678                                skill_num != PA_SHIELDCHAIN
1679                                && !flag.cri)
1680                        {       //Elemental/Racial adjustments
1681                                if(sd->right_weapon.def_ratio_atk_ele & (1<<tstatus->def_ele) ||
1682                                        sd->right_weapon.def_ratio_atk_race & (1<<tstatus->race) ||
1683                                        sd->right_weapon.def_ratio_atk_race & (1<<(is_boss(target)?RC_BOSS:RC_NONBOSS))
1684                                )
1685                                        flag.pdef = 1;
1686
1687                                if(sd->left_weapon.def_ratio_atk_ele & (1<<tstatus->def_ele) ||
1688                                        sd->left_weapon.def_ratio_atk_race & (1<<tstatus->race) ||
1689                                        sd->left_weapon.def_ratio_atk_race & (1<<(is_boss(target)?RC_BOSS:RC_NONBOSS))
1690                                ) {     //Pass effect onto right hand if configured so. [Skotlex]
1691                                        if (battle_config.left_cardfix_to_right && flag.rh)
1692                                                flag.pdef = 1;
1693                                        else
1694                                                flag.pdef2 = 1;
1695                                }
1696                        }
1697
1698                        if (skill_num != CR_GRANDCROSS && skill_num != NPC_GRANDDARKNESS)
1699                        {       //Ignore Defense?
1700                                if (!flag.idef && (
1701                                        sd->right_weapon.ignore_def_ele & (1<<tstatus->def_ele) ||
1702                                        sd->right_weapon.ignore_def_race & (1<<tstatus->race) ||
1703                                        sd->right_weapon.ignore_def_race & (is_boss(target)?1<<RC_BOSS:1<<RC_NONBOSS)
1704                                ))
1705                                        flag.idef = 1;
1706
1707                                if (!flag.idef2 && (
1708                                        sd->left_weapon.ignore_def_ele & (1<<tstatus->def_ele) ||
1709                                        sd->left_weapon.ignore_def_race & (1<<tstatus->race) ||
1710                                        sd->left_weapon.ignore_def_race & (is_boss(target)?1<<RC_BOSS:1<<RC_NONBOSS)
1711                                )) {
1712                                                if(battle_config.left_cardfix_to_right && flag.rh) //Move effect to right hand. [Skotlex]
1713                                                        flag.idef = 1;
1714                                                else
1715                                                        flag.idef2 = 1;
1716                                }
1717                        }
1718                }
1719
1720                if (!flag.idef || !flag.idef2)
1721                {       //Defense reduction
1722                        short vit_def;
1723                        signed char def1 = status_get_def(target); //Don't use tstatus->def1 due to skill timer reductions.
1724                        short def2 = (short)tstatus->def2;
1725                        if(battle_config.vit_penalty_type &&
1726                                battle_config.vit_penalty_target&target->type)
1727                        {
1728                                unsigned char target_count; //256 max targets should be a sane max
1729                                target_count = unit_counttargeted(target,battle_config.vit_penalty_count_lv);
1730                                if(target_count >= battle_config.vit_penalty_count) {
1731                                        if(battle_config.vit_penalty_type == 1) {
1732                                                def1 = (def1 * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100;
1733                                                def2 = (def2 * (100 - (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num))/100;
1734                                        } else { //Assume type 2
1735                                                def1 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num;
1736                                                def2 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num;
1737                                        }
1738                                }
1739                                if(skill_num == AM_ACIDTERROR) def1 = 0; //Acid Terror ignores only armor defense. [Skotlex]
1740                                if(def2 < 1) def2 = 1;
1741                        }
1742                        //Vitality reduction from rodatazone: http://rodatazone.simgaming.net/mechanics/substats.php#def       
1743                        if (tsd)        //Sd vit-eq
1744                        {       //[VIT*0.5] + rnd([VIT*0.3], max([VIT*0.3],[VIT^2/150]-1))
1745                                vit_def = def2*(def2-15)/150;
1746                                vit_def = def2/2 + (vit_def>0?rand()%vit_def:0);
1747                               
1748                                if((battle_check_undead(sstatus->race,sstatus->def_ele) || sstatus->race==RC_DEMON) && //This bonus already doesnt work vs players
1749                                        src->type == BL_MOB && (skill=pc_checkskill(tsd,AL_DP)) > 0)
1750                                        vit_def += skill*(int)(3 +(tsd->status.base_level+1)*0.04);   // submitted by orn
1751                        } else { //Mob-Pet vit-eq
1752                                //VIT + rnd(0,[VIT/20]^2-1)
1753                                vit_def = (def2/20)*(def2/20);
1754                                vit_def = def2 + (vit_def>0?rand()%vit_def:0);
1755                        }
1756                       
1757                        if (battle_config.weapon_defense_type) {
1758                                vit_def += def1*battle_config.weapon_defense_type;
1759                                def1 = 0;
1760                        }
1761                        if (def1 > 100) def1 = 100;
1762                        ATK_RATE2(
1763                                flag.idef ?100:
1764                                (flag.pdef ?flag.pdef *(def1 + vit_def):
1765                                100-def1),
1766                                flag.idef2?100:
1767                                (flag.pdef2?flag.pdef2*(def1 + vit_def):
1768                                100-def1)
1769                        );
1770                        ATK_ADD2(
1771                                flag.idef ||flag.pdef ?0:-vit_def,
1772                                flag.idef2||flag.pdef2?0:-vit_def
1773                        );
1774                }
1775
1776                //Post skill/vit reduction damage increases
1777                if (sc && skill_num != LK_SPIRALPIERCE)
1778                {       //SC skill damages
1779                        if(sc->data[SC_AURABLADE]) 
1780                                ATK_ADD(20*sc->data[SC_AURABLADE]->val1);
1781                }
1782
1783                //Refine bonus
1784                if (sd && flag.weapon && skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST) {
1785                        if (skill_num == MO_FINGEROFFENSIVE) //Counts refine bonus multiple times
1786                        {
1787                                ATK_ADD2(wd.div_*sstatus->rhw.atk2, wd.div_*sstatus->lhw.atk2);
1788                        } else {
1789                                ATK_ADD2(sstatus->rhw.atk2, sstatus->lhw.atk2);
1790                        }
1791                }
1792
1793                //Set to min of 1
1794                if (flag.rh && wd.damage < 1) wd.damage = 1;
1795                if (flag.lh && wd.damage2 < 1) wd.damage2 = 1;
1796
1797                if (sd && flag.weapon &&
1798                        skill_num != MO_INVESTIGATE &&
1799                        skill_num != MO_EXTREMITYFIST &&
1800                        skill_num != CR_GRANDCROSS)
1801                {       //Add mastery damage
1802                        if(skill_num != ASC_BREAKER && sd->status.weapon == W_KATAR &&
1803                                (skill=pc_checkskill(sd,ASC_KATAR)) > 0)
1804                        {       //Adv Katar Mastery is does not applies to ASC_BREAKER,
1805                                // but other masteries DO apply >_>
1806                                ATK_ADDRATE(10+ 2*skill);
1807                        }
1808
1809                        wd.damage = battle_addmastery(sd,target,wd.damage,0);
1810                        if (flag.lh)
1811                                wd.damage2 = battle_addmastery(sd,target,wd.damage2,1);
1812
1813                        if (sc && sc->data[SC_MIRACLE]) i = 2; //Star anger
1814                        else
1815                        ARR_FIND(0, 3, i, t_class == sd->hate_mob[i]);
1816                        if (i < 3 && (skill=pc_checkskill(sd,sg_info[i].anger_id))) 
1817                        {
1818                                skillratio = sd->status.base_level + sstatus->dex + sstatus->luk;
1819                                if (i == 2) skillratio += sstatus->str; //Star Anger
1820                                if (skill<4)
1821                                        skillratio /= 12-3*skill;
1822                                ATK_ADDRATE(skillratio);
1823                        }
1824                        if (skill_num == NJ_SYURIKEN && (skill = pc_checkskill(sd,NJ_TOBIDOUGU)) > 0)
1825                                ATK_ADD(3*skill);
1826                        if (skill_num == NJ_KUNAI)
1827                                ATK_ADD(60);
1828                }
1829        } //Here ends flag.hit section, the rest of the function applies to both hitting and missing attacks
1830        else if(wd.div_ < 0) //Since the attack missed...
1831                wd.div_ *= -1; 
1832
1833        if(skill_num == CR_GRANDCROSS || skill_num == NPC_GRANDDARKNESS)
1834                return wd; //Enough, rest is not needed.
1835
1836        if(sd && (skill=pc_checkskill(sd,BS_WEAPONRESEARCH)) > 0) 
1837                ATK_ADD(skill*2);
1838
1839        if(skill_num==TF_POISON)
1840                ATK_ADD(15*skill_lv);
1841
1842        if(!(nk&NK_NO_ELEFIX || (s_ele == ELE_NEUTRAL &&
1843                battle_config.attack_attr_none&src->type)))
1844        {       //Elemental attribute fix
1845                if (wd.damage > 0)
1846                {
1847                        wd.damage=battle_attr_fix(src,target,wd.damage,s_ele,tstatus->def_ele, tstatus->ele_lv);
1848                        if(skill_num==MC_CARTREVOLUTION) //Cart Revolution applies the element fix once more with neutral element
1849                                wd.damage = battle_attr_fix(src,target,wd.damage,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv);
1850                        if(skill_num== GS_GROUNDDRIFT) //Additional 50*lv Neutral damage.
1851                                wd.damage+= battle_attr_fix(src,target,50*skill_lv,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv);
1852                }
1853                if (flag.lh && wd.damage2 > 0)
1854                        wd.damage2 = battle_attr_fix(src,target,wd.damage2,s_ele_,tstatus->def_ele, tstatus->ele_lv);
1855                if(sc && sc->data[SC_WATK_ELEMENT])
1856                {       //Descriptions indicate this means adding a percent of a normal attack in another element. [Skotlex]
1857                        int damage= battle_calc_base_damage(sstatus, &sstatus->rhw, sc, tstatus->size, sd, (flag.arrow?2:0));
1858                        damage = damage*sc->data[SC_WATK_ELEMENT]->val2/100;
1859                        damage = battle_attr_fix(src,target,damage,sc->data[SC_WATK_ELEMENT]->val1,tstatus->def_ele, tstatus->ele_lv);
1860                        ATK_ADD(damage);
1861                }
1862        }
1863
1864        if (sd)
1865        {
1866                if (skill_num != CR_SHIELDBOOMERANG) //Only Shield boomerang doesn't takes the Star Crumbs bonus.
1867                        ATK_ADD2(wd.div_*sd->right_weapon.star, wd.div_*sd->left_weapon.star);
1868                if (skill_num==MO_FINGEROFFENSIVE) { //The finger offensive spheres on moment of attack do count. [Skotlex]
1869                        ATK_ADD(wd.div_*sd->spiritball_old*3);
1870                } else {
1871                        ATK_ADD(wd.div_*sd->spiritball*3);
1872                }
1873
1874                //Card Fix, sd side
1875                if ((wd.damage || wd.damage2) && !(nk&NK_NO_CARDFIX_ATK))
1876                {
1877                        int cardfix = 1000, cardfix_ = 1000;
1878                        int t_race2 = status_get_race2(target); 
1879                        if(sd->state.arrow_atk)
1880                        {
1881                                cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race]+sd->arrow_addrace[tstatus->race])/100;
1882                                if (!(nk&NK_NO_ELEFIX))
1883                                        cardfix=cardfix*(100+sd->right_weapon.addele[tstatus->def_ele]+sd->arrow_addele[tstatus->def_ele])/100;
1884                                cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size]+sd->arrow_addsize[tstatus->size])/100;
1885                                cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2])/100;
1886                                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;
1887                        } else {        //Melee attack
1888                                if(!battle_config.left_cardfix_to_right)
1889                                {
1890                                        cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race])/100;
1891                                        if (!(nk&NK_NO_ELEFIX))
1892                                                cardfix=cardfix*(100+sd->right_weapon.addele[tstatus->def_ele])/100;
1893                                        cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size])/100;
1894                                        cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2])/100;
1895                                        cardfix=cardfix*(100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100;
1896
1897                                        if (flag.lh)
1898                                        {
1899                                                cardfix_=cardfix_*(100+sd->left_weapon.addrace[tstatus->race])/100;
1900                                                if (!(nk&NK_NO_ELEFIX))
1901                                                        cardfix_=cardfix_*(100+sd->left_weapon.addele[tstatus->def_ele])/100;
1902                                                cardfix_=cardfix_*(100+sd->left_weapon.addsize[tstatus->size])/100;
1903                                                cardfix_=cardfix_*(100+sd->left_weapon.addrace2[t_race2])/100;
1904                                                cardfix_=cardfix_*(100+sd->left_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100;
1905                                        }
1906                                } else {
1907                                        cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race]+sd->left_weapon.addrace[tstatus->race])/100;
1908                                        cardfix=cardfix*(100+sd->right_weapon.addele[tstatus->def_ele]+sd->left_weapon.addele[tstatus->def_ele])/100;
1909                                        cardfix=cardfix*(100+sd->right_weapon.addsize[tstatus->size]+sd->left_weapon.addsize[tstatus->size])/100;
1910                                        cardfix=cardfix*(100+sd->right_weapon.addrace2[t_race2]+sd->left_weapon.addrace2[t_race2])/100;
1911                                        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;
1912                                }
1913                        }
1914
1915                        for(i=0;i<ARRAYLENGTH(sd->right_weapon.add_dmg) && sd->right_weapon.add_dmg[i].rate;i++) {
1916                                if(sd->right_weapon.add_dmg[i].class_ == t_class) {
1917                                        cardfix=cardfix*(100+sd->right_weapon.add_dmg[i].rate)/100;
1918                                        break;
1919                                }
1920                        }
1921
1922                        if (flag.lh)
1923                        {
1924                                for(i=0;i<ARRAYLENGTH(sd->left_weapon.add_dmg) && sd->left_weapon.add_dmg[i].rate;i++) {
1925                                        if(sd->left_weapon.add_dmg[i].class_ == t_class) {
1926                                                cardfix_=cardfix_*(100+sd->left_weapon.add_dmg[i].rate)/100;
1927                                                break;
1928                                        }
1929                                }
1930                        }
1931
1932                        if(wd.flag&BF_LONG)
1933                                cardfix=cardfix*(100+sd->long_attack_atk_rate)/100;
1934
1935                        if (cardfix != 1000 || cardfix_ != 1000)
1936                                ATK_RATE2(cardfix/10, cardfix_/10);     //What happens if you use right-to-left and there's no right weapon, only left?
1937                }
1938               
1939                if (skill_num == CR_SHIELDBOOMERANG || skill_num == PA_SHIELDCHAIN) { //Refine bonus applies after cards and elements.
1940                        short index= sd->equip_index[EQI_HAND_L];
1941                        if (index >= 0 &&
1942                                sd->inventory_data[index] &&
1943                                sd->inventory_data[index]->type == IT_ARMOR)
1944                                ATK_ADD(10*sd->status.inventory[index].refine);
1945                }
1946        } //if (sd)
1947
1948        //Card Fix, tsd sid
1949        if (tsd && !(nk&NK_NO_CARDFIX_DEF))
1950        {
1951                short s_race2,s_class;
1952                short cardfix=1000;
1953
1954                s_race2 = status_get_race2(src);
1955                s_class = status_get_class(src);
1956
1957                if (!(nk&NK_NO_ELEFIX))
1958                {
1959                        cardfix=cardfix*(100-tsd->subele[s_ele])/100;
1960                        if (flag.lh && s_ele_ != s_ele)
1961                                cardfix=cardfix*(100-tsd->subele[s_ele_])/100;
1962                }
1963                cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100;
1964                cardfix=cardfix*(100-tsd->subrace2[s_race2])/100;
1965                cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100;
1966                cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100;
1967                for(i=0; i < ARRAYLENGTH(tsd->add_def) && tsd->add_def[i].rate;i++) {
1968                        if(tsd->add_def[i].class_ == s_class) {
1969                                cardfix=cardfix*(100-tsd->add_def[i].rate)/100;
1970                                break;
1971                        }
1972                }
1973
1974                if(wd.flag&BF_SHORT)
1975                        cardfix=cardfix*(100-tsd->near_attack_def_rate)/100;
1976                else    // BF_LONG (there's no other choice)
1977                        cardfix=cardfix*(100-tsd->long_attack_def_rate)/100;
1978
1979                if( tsd->sc.data[SC_DEF_RATE] )
1980                        cardfix=cardfix*(100-tsd->sc.data[SC_DEF_RATE]->val1)/100;
1981
1982                if (cardfix != 1000)
1983                        ATK_RATE(cardfix/10);
1984        }
1985
1986        if(flag.infdef)
1987        { //Plants receive 1 damage when hit
1988                if (flag.rh && (flag.hit || wd.damage>0))
1989                        wd.damage = 1;
1990                if (flag.lh && (flag.hit || wd.damage2>0))
1991                        wd.damage2 = 1;
1992                if (!(battle_config.skill_min_damage&1)) 
1993                        //Do not return if you are supposed to deal greater damage to plants than 1. [Skotlex]
1994                        return wd;
1995        }
1996
1997        if(sd && !skill_num && !flag.cri)
1998        {       //Check for double attack.
1999                if(((skill_lv = pc_checkskill(sd,TF_DOUBLE)) > 0 && sd->weapontype1 == W_DAGGER)
2000                        ||(sd->double_rate > 0 && sd->weapontype1 != W_FIST)) //Will fail bare-handed
2001                {       //Success chance is not added, the higher one is used [Skotlex]
2002                        if (rand()%100 < (5*skill_lv>sd->double_rate?5*skill_lv:sd->double_rate))
2003                        {
2004                                wd.div_=skill_get_num(TF_DOUBLE,skill_lv?skill_lv:1);
2005                                damage_div_fix(wd.damage, wd.div_);
2006                                wd.type = 0x08;
2007                        }
2008                } else
2009                if (sd->weapontype1 == W_REVOLVER &&
2010                        (skill_lv = pc_checkskill(sd,GS_CHAINACTION)) > 0 &&
2011                        (rand()%100 < 5*skill_lv)
2012                        )
2013                {
2014                        wd.div_=skill_get_num(GS_CHAINACTION,skill_lv);
2015                        damage_div_fix(wd.damage, wd.div_);
2016                        wd.type = 0x08;
2017                }
2018        }
2019
2020        if (sd)
2021        {
2022                if (!flag.rh && flag.lh) 
2023                {       //Move lh damage to the rh
2024                        wd.damage = wd.damage2;
2025                        wd.damage2 = 0;
2026                        flag.rh=1;
2027                        flag.lh=0;
2028                } else if(flag.rh && flag.lh)
2029                {       //Dual-wield
2030                        if (wd.damage)
2031                        {
2032                                skill = pc_checkskill(sd,AS_RIGHT);
2033                                wd.damage = wd.damage * (50 + (skill * 10))/100;
2034                                if(wd.damage < 1) wd.damage = 1;
2035                        }
2036                        if (wd.damage2)
2037                        {
2038                                skill = pc_checkskill(sd,AS_LEFT);
2039                                wd.damage2 = wd.damage2 * (30 + (skill * 10))/100;
2040                                if(wd.damage2 < 1) wd.damage2 = 1;
2041                        }
2042                } else if(sd->status.weapon == W_KATAR && !skill_num)
2043                { //Katars (offhand damage only applies to normal attacks, tested on Aegis 10.2)
2044                        skill = pc_checkskill(sd,TF_DOUBLE);
2045                        wd.damage2 = wd.damage * (1 + (skill * 2))/100;
2046
2047                        if(wd.damage && !wd.damage2) wd.damage2 = 1;
2048                        flag.lh = 1;
2049                }
2050        }
2051
2052        if(!flag.rh && wd.damage)
2053                wd.damage=0;
2054
2055        if(!flag.lh && wd.damage2)
2056                wd.damage2=0;
2057
2058        if(wd.damage + wd.damage2)
2059        {       //There is a total damage value
2060                if(!wd.damage2) {
2061                        wd.damage=battle_calc_damage(src,target,wd.damage,wd.div_,skill_num,skill_lv,wd.flag);
2062                        if (map_flag_gvg2(target->m))
2063                                wd.damage=battle_calc_gvg_damage(src,target,wd.damage,wd.div_,skill_num,skill_lv,wd.flag);
2064                } else
2065                if(!wd.damage) {
2066                        wd.damage2=battle_calc_damage(src,target,wd.damage2,wd.div_,skill_num,skill_lv,wd.flag);
2067                        if (map_flag_gvg2(target->m))
2068                                wd.damage2=battle_calc_gvg_damage(src,target,wd.damage2,wd.div_,skill_num,skill_lv,wd.flag);
2069                } else
2070                {
2071                        int d1=wd.damage+wd.damage2,d2=wd.damage2;
2072                        wd.damage=battle_calc_damage(src,target,d1,wd.div_,skill_num,skill_lv,wd.flag);
2073                        if (map_flag_gvg2(target->m))
2074                                wd.damage=battle_calc_gvg_damage(src,target,wd.damage,wd.div_,skill_num,skill_lv,wd.flag);
2075                        wd.damage2=(d2*100/d1)*wd.damage/100;
2076                        if(wd.damage > 1 && wd.damage2 < 1) wd.damage2=1;
2077                        wd.damage-=wd.damage2;
2078                }
2079        }
2080
2081        if(skill_num==ASC_BREAKER)
2082        {       //Breaker's int-based damage (a misc attack?)
2083                struct Damage md = battle_calc_misc_attack(src, target, skill_num, skill_lv, wflag);
2084                wd.damage += md.damage;
2085        }
2086
2087        if (wd.damage || wd.damage2) {
2088                if (sd && battle_config.equip_self_break_rate)
2089                {       // Self weapon breaking
2090                        int breakrate = battle_config.equip_natural_break_rate;
2091                        if (sc) {
2092                                if(sc->data[SC_OVERTHRUST])
2093                                        breakrate += 10;
2094                                if(sc->data[SC_MAXOVERTHRUST])
2095                                        breakrate += 10;
2096                        }
2097                        if (breakrate)
2098                                skill_break_equip(src, EQP_WEAPON, breakrate, BCT_SELF);
2099                }
2100                //Cart Termination/Tomahawk won't trigger breaking data. Why? No idea, go ask Gravity.
2101                if (battle_config.equip_skill_break_rate && skill_num != WS_CARTTERMINATION && skill_num != ITM_TOMAHAWK)
2102                {       // Target equipment breaking
2103                        int breakrate[2] = {0,0}; // weapon = 0, armor = 1
2104                        if (sd) {       // Break rate from equipment
2105                                breakrate[0] += sd->break_weapon_rate;
2106                                breakrate[1] += sd->break_armor_rate;
2107                        }
2108                        if (sc) {
2109                                if (sc->data[SC_MELTDOWN]) {
2110                                        breakrate[0] += sc->data[SC_MELTDOWN]->val2;
2111                                        breakrate[1] += sc->data[SC_MELTDOWN]->val3;
2112                                }
2113                        }       
2114                        if (breakrate[0])
2115                                skill_break_equip(target, EQP_WEAPON, breakrate[0], BCT_ENEMY);
2116                        if (breakrate[1])
2117                                skill_break_equip(target, EQP_ARMOR, breakrate[1], BCT_ENEMY);
2118                }
2119        }
2120
2121        //SG_FUSION hp penalty [Komurka]
2122        if (sc && sc->data[SC_FUSION])
2123        {
2124                int hp= sstatus->max_hp;
2125                if (sd && tsd) {
2126                        hp = 8*hp/100;
2127                        if (100*sstatus->hp <= 20*sstatus->max_hp)
2128                                hp = sstatus->hp;
2129                } else
2130                        hp = 5*hp/1000;
2131                status_zap(src, hp, 0);
2132        }
2133
2134        return wd;
2135}
2136
2137/*==========================================
2138 * battle_calc_magic_attack [DracoRPG]
2139 *------------------------------------------*/
2140struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list *target,int skill_num,int skill_lv,int mflag)
2141{
2142        int i, nk;
2143        short s_ele;
2144        unsigned int skillratio = 100;  //Skill dmg modifiers.
2145
2146        struct map_session_data *sd, *tsd;
2147        struct Damage ad;
2148        struct status_data *sstatus = status_get_status_data(src);
2149        struct status_data *tstatus = status_get_status_data(target);
2150        struct {
2151                unsigned imdef : 1;
2152                unsigned infdef : 1;
2153        }       flag;
2154
2155        memset(&ad,0,sizeof(ad));
2156        memset(&flag,0,sizeof(flag));
2157
2158        if(src==NULL || target==NULL)
2159        {
2160                nullpo_info(NLP_MARK);
2161                return ad;
2162        }
2163        //Initial Values
2164        ad.damage = 1;
2165        ad.div_=skill_get_num(skill_num,skill_lv);
2166        ad.amotion=skill_get_inf(skill_num)&INF_GROUND_SKILL?0:sstatus->amotion; //Amotion should be 0 for ground skills.
2167        ad.dmotion=tstatus->dmotion;
2168        ad.blewcount = skill_get_blewcount(skill_num,skill_lv);
2169        ad.flag=BF_MAGIC|BF_SKILL;
2170        ad.dmg_lv=ATK_DEF;
2171        nk = skill_get_nk(skill_num);
2172        flag.imdef = nk&NK_IGNORE_DEF?1:0;
2173
2174        sd = BL_CAST(BL_PC, src);
2175        tsd = BL_CAST(BL_PC, target);
2176
2177        //Initialize variables that will be used afterwards
2178        s_ele = skill_get_ele(skill_num, skill_lv);
2179
2180        if (s_ele == -1) // pl=-1 : the skill takes the weapon's element
2181                s_ele = sstatus->rhw.ele;
2182        else if (s_ele == -2) //Use status element
2183                s_ele = status_get_attack_sc_element(src,status_get_sc(src));
2184       
2185        //Set miscellaneous data that needs be filled
2186        if(sd) {
2187                sd->state.arrow_atk = 0;
2188                ad.blewcount += battle_blewcount_bonus(sd, skill_num);
2189        }
2190
2191        //Skill Range Criteria
2192        ad.flag |= battle_range_type(src, target, skill_num, skill_lv);
2193        flag.infdef=(tstatus->mode&MD_PLANT?1:0);
2194               
2195        switch(skill_num)
2196        {
2197                case MG_FIREWALL:
2198                case NJ_KAENSIN:
2199                        ad.dmotion = 0; //No flinch animation.
2200                        if ( tstatus->def_ele == ELE_FIRE || battle_check_undead(tstatus->race, tstatus->def_ele) )
2201                                ad.blewcount = 0; //No knockback
2202                        break;
2203                case PR_SANCTUARY:
2204                        ad.dmotion = 0; //No flinch animation.
2205                        break;
2206        }
2207
2208        if (!flag.infdef) //No need to do the math for plants
2209        {
2210
2211//MATK_RATE scales the damage. 100 = no change. 50 is halved, 200 is doubled, etc
2212#define MATK_RATE( a ) { ad.damage= ad.damage*(a)/100; }
2213//Adds dmg%. 100 = +100% (double) damage. 10 = +10% damage
2214#define MATK_ADDRATE( a ) { ad.damage+= ad.damage*(a)/100; }
2215//Adds an absolute value to damage. 100 = +100 damage
2216#define MATK_ADD( a ) { ad.damage+= a; }
2217
2218                switch (skill_num)
2219                {       //Calc base damage according to skill
2220                        case AL_HEAL:
2221                        case PR_BENEDICTIO: //Accidentally deleted the :, replaced it. No difference, so dont worry about this.
2222                        case AD_DARKHEAL: // Adept Dark Heal
2223                        //Is this a good place for dark heal, i wonder? Seems fine though.
2224                                ad.damage = skill_calc_heal(src, target, skill_lv)/2;
2225                                break;
2226                        case PR_ASPERSIO:
2227                                ad.damage = 40;
2228                                break;
2229                        case PR_SANCTUARY:
2230                                ad.damage = (skill_lv>6)?388:skill_lv*50;
2231                                break;
2232                        case ALL_RESURRECTION:
2233                        case PR_TURNUNDEAD:
2234                                //Undead check is on skill_castend_damageid code.
2235                                i = 20*skill_lv + sstatus->luk + sstatus->int_ + status_get_lv(src)
2236                                        + 200 - 200*tstatus->hp/tstatus->max_hp;
2237                                if(i > 700) i = 700;
2238                                if(rand()%1000 < i && !(tstatus->mode&MD_BOSS))
2239                                        ad.damage = tstatus->hp;
2240                                else
2241                                        ad.damage = status_get_lv(src) + sstatus->int_ + skill_lv * 10;
2242                                break;
2243                        case PF_SOULBURN:
2244                                ad.damage = tstatus->sp * 2;
2245                                break;
2246                        default:
2247                        {
2248                                if (sstatus->matk_max > sstatus->matk_min) {
2249                                        MATK_ADD(sstatus->matk_min+rand()%(1+sstatus->matk_max-sstatus->matk_min));
2250                                } else {
2251                                        MATK_ADD(sstatus->matk_min);
2252                                }
2253
2254                                if(nk&NK_SPLASHSPLIT){ // Divide MATK in case of multiple targets skill
2255                                        if(mflag>0)
2256                                                ad.damage/= mflag;
2257                                        else
2258                                                ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_num, skill_get_name(skill_num));
2259                                }
2260
2261                                switch(skill_num){
2262                                        case MG_NAPALMBEAT:
2263                                        case MG_FIREBALL:
2264                                                skillratio += skill_lv*10-30;
2265                                                break;
2266                                        case MG_SOULSTRIKE:
2267                                                if (battle_check_undead(tstatus->race,tstatus->def_ele))
2268                                                        skillratio += 5*skill_lv;
2269                                                break;
2270                                        case MG_FIREWALL:
2271                                                skillratio -= 50;
2272                                                break;
2273                                        case MG_THUNDERSTORM:
2274                                                skillratio -= 20;
2275                                                break;
2276                                        case MG_FROSTDIVER:
2277                                                skillratio += 10*skill_lv;
2278                                                break;
2279                                        case AL_HOLYLIGHT:
2280                                                skillratio += 25;
2281                                                if (sd && sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_PRIEST)
2282                                                        skillratio *= 5; //Does 5x damage include bonuses from other skills?
2283                                                break;
2284                                        case AL_RUWACH:
2285                                                skillratio += 45;
2286                                                break;
2287                                        case WZ_FROSTNOVA:
2288                                                skillratio += (100+skill_lv*10)*2/3-100;
2289                                                break;
2290                                        case WZ_FIREPILLAR:
2291                                                if (skill_lv > 10)
2292                                                        skillratio += 100;
2293                                                else
2294                                                        skillratio -= 80;
2295                                                break;
2296                                        case WZ_SIGHTRASHER:
2297                                                skillratio += 20*skill_lv;
2298                                                break;
2299                                        case WZ_VERMILION:
2300                                                skillratio += 20*skill_lv-20;
2301                                                break;
2302                                        case WZ_WATERBALL:
2303                                                skillratio += 30*skill_lv;
2304                                                break;
2305                                        case WZ_STORMGUST:
2306                                                skillratio += 40*skill_lv;
2307                                                break;
2308                                        case HW_NAPALMVULCAN:
2309                                                skillratio += 10*skill_lv-30;
2310                                                break;
2311                                        case SL_STIN:
2312                                                skillratio += (tstatus->size?-99:10*skill_lv); //target size must be small (0) for full damage.
2313                                                break;
2314                                        case SL_STUN:
2315                                                skillratio += (tstatus->size!=2?5*skill_lv:-99); //Full damage is dealt on small/medium targets
2316                                                break;
2317                                        case SL_SMA:
2318                                                skillratio += -60 + status_get_lv(src); //Base damage is 40% + lv%
2319                                                break;
2320                                        case NJ_KOUENKA:
2321                                                skillratio -= 10;
2322                                                break;
2323                                        case NJ_KAENSIN:
2324                                                skillratio -= 50;
2325                                                break;
2326                                        case NJ_BAKUENRYU:
2327                                                skillratio += 50*(skill_lv-1);
2328                                                break;
2329                                        case NJ_HYOUSYOURAKU:
2330                                                skillratio += 50*skill_lv;
2331                                                break;
2332                                        case NJ_RAIGEKISAI:
2333                                                skillratio += 60 + 40*skill_lv;
2334                                                break;
2335                                        case NJ_KAMAITACHI:
2336                                        case NPC_ENERGYDRAIN:
2337                                                skillratio += 100*skill_lv;
2338                                                break;
2339                                        case NPC_EARTHQUAKE:
2340                                                skillratio += 100 +100*skill_lv +100*(skill_lv/2);
2341                                                break;
2342                                               
2343//NOTE: All the skills below here did NOT work before, may have been a stupid mistake but this is for reference.
2344                                        case NC_DRAINLIFE: // Necro Drain Life [Brain]
2345                                                skillratio += 25*skill_lv;
2346                                                break;
2347                                        case WL_HELLFIRE: // Warlock Hellfire [Brain]
2348                                                skillratio += 25*skill_lv;
2349                                                break;
2350                                        case WL_SHADOWBURN: // Warlock Shadow Burn [Brain]
2351                                                skillratio += 20*skill_lv;
2352                                                break;
2353                                        case WL_CURSEDOOM: // Warlock Curse of Doom [Brain]
2354                                                skillratio += 400 + 300*skill_lv; //max 20*matk dmg after 60 seconds
2355                                                break;
2356                                        case WL_SEARING: // Warlock Searing Pain [Brain]
2357                                                if(status_get_sc(target)->data[SC_SEARING])
2358                                                        skillratio = 10*pc_checkskill(sd,WL_SEARING);//10% * skilllv
2359                                                break; //Else 100% Matk
2360                                        case WL_IMMOLATE: // Warlock Immolate [Brain]
2361                                                if(status_get_sc(target)->data[SC_IMMOLATE])
2362                                                        skillratio += 10*pc_checkskill(sd,WL_SEARING);//100% +10 * searing lv
2363                                                else skillratio += -20 + 20*skill_lv;// Else 80% + 20% * skill lv
2364                                                break;
2365                                        case WL_CONFLAGRATE: // Warlock Conflagrate [Brain]
2366                                                skillratio += 100 + 60*skill_lv + //damage bonus from other fire skills
2367                                                        10*pc_checkskill(sd,WL_SEARING) + 10*pc_checkskill(sd,WL_IMMOLATE);
2368                                                break;
2369
2370                                }
2371
2372                                MATK_RATE(skillratio);
2373                       
2374                                //Constant/misc additions from skills
2375                                if (skill_num == WZ_FIREPILLAR)
2376                                        MATK_ADD(50);
2377                        }
2378                }
2379
2380                if(sd) {
2381                        //Damage bonuses
2382                        if ((i = pc_skillatk_bonus(sd, skill_num)))
2383                                ad.damage += ad.damage*i/100;
2384
2385                        //Ignore Defense?
2386                        if (!flag.imdef && (
2387                                sd->ignore_mdef_ele & (1<<tstatus->def_ele) ||
2388                                sd->ignore_mdef_race & (1<<tstatus->race) ||
2389                                sd->ignore_mdef_race & (is_boss(target)?1<<RC_BOSS:1<<RC_NONBOSS)
2390                        ))
2391                                flag.imdef = 1;
2392                }
2393
2394                if(!flag.imdef){
2395                        char mdef = tstatus->mdef;
2396                        int mdef2= tstatus->mdef2;
2397                        if(sd) {
2398                                i = sd->ignore_mdef[is_boss(target)?RC_BOSS:RC_NONBOSS];
2399                                i+= sd->ignore_mdef[tstatus->race];
2400                                if (i)
2401                                {
2402                                        if (i > 100) i = 100;
2403                                        mdef -= mdef * i/100;
2404                                        //mdef2-= mdef2* i/100;
2405                                }
2406                        }
2407                        if(battle_config.magic_defense_type)
2408                                ad.damage = ad.damage - mdef*battle_config.magic_defense_type - mdef2;
2409                        else
2410                                ad.damage = ad.damage * (100-mdef)/100 - mdef2;
2411                }
2412
2413                if(skill_num == CR_GRANDCROSS || skill_num == NPC_GRANDDARKNESS)
2414                {       //Apply the physical part of the skill's damage. [Skotlex]
2415                        struct Damage wd = battle_calc_weapon_attack(src,target,skill_num,skill_lv,mflag);
2416                        ad.damage = (wd.damage + ad.damage) * (100 + 40*skill_lv)/100;
2417                        if(src==target)
2418                        {
2419                                if (src->type == BL_PC)
2420                                        ad.damage = ad.damage/2;
2421                                else
2422                                        ad.damage = 0;
2423                        }
2424                }
2425               
2426                if (skill_num == NPC_EARTHQUAKE)
2427                {       //Adds atk2 to the damage, should be influenced by number of hits and skill-ratio, but not mdef reductions. [Skotlex]
2428                        //Also divide the extra bonuses from atk2 based on the number in range [Kevin]
2429                        if(mflag>0)
2430                                ad.damage+= (sstatus->rhw.atk2*skillratio/100)/mflag;
2431                        else
2432                                ShowError("Zero range by %d:%s, divide per 0 avoided!\n", skill_num, skill_get_name(skill_num));
2433                }
2434
2435                if(ad.damage<1)
2436                        ad.damage=1;
2437
2438                if (!(nk&NK_NO_ELEFIX))
2439                        ad.damage=battle_attr_fix(src, target, ad.damage, s_ele, tstatus->def_ele, tstatus->ele_lv);
2440//Take this into account for errors. It looks out of place/outdated but I will not look further into it until I know.
2441                if(skill_num == WL_SHADOWBURN) { // Warlock Shadow Burn [Brain]
2442                        // This is where we calculate the secondary damage
2443                        if(ad.damage<1) ad.damage=1;
2444                        struct Damage md = battle_calc_misc_attack(src,target,skill_num,skill_lv, mflag);
2445                        if(md.damage<1) md.damage=1;
2446                        ad.damage += md.damage;
2447                }
2448                if (sd && !(nk&NK_NO_CARDFIX_ATK)) {
2449                        short t_class = status_get_class(target);
2450                        short cardfix=1000;
2451
2452                        cardfix=cardfix*(100+sd->magic_addrace[tstatus->race])/100;
2453                        if (!(nk&NK_NO_ELEFIX))
2454                                cardfix=cardfix*(100+sd->magic_addele[tstatus->def_ele])/100;
2455                        cardfix=cardfix*(100+sd->magic_addsize[tstatus->size])/100;
2456                        cardfix=cardfix*(100+sd->magic_addrace[is_boss(target)?RC_BOSS:RC_NONBOSS])/100;
2457                        for(i=0; i< ARRAYLENGTH(sd->add_mdmg) && sd->add_mdmg[i].rate;i++) {
2458                                if(sd->add_mdmg[i].class_ == t_class) {
2459                                        cardfix=cardfix*(100+sd->add_mdmg[i].rate)/100;
2460                                        continue;
2461                                }
2462                        }
2463                        if (cardfix != 1000)
2464                                MATK_RATE(cardfix/10);
2465                }
2466
2467                if (tsd && !(nk&NK_NO_CARDFIX_DEF))
2468                {       //Target cards.
2469                        short s_race2=status_get_race2(src);
2470                        short s_class= status_get_class(src);
2471                        int cardfix=1000;
2472
2473                        if (!(nk&NK_NO_ELEFIX))
2474                                cardfix=cardfix*(100-tsd->subele[s_ele])/100;
2475                        cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100;
2476                        cardfix=cardfix*(100-tsd->subrace2[s_race2])/100;
2477                        cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100;
2478                        cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100;
2479                        for(i=0; i < ARRAYLENGTH(tsd->add_mdef) && tsd->add_mdef[i].rate;i++) {
2480                                if(tsd->add_mdef[i].class_ == s_class) {
2481                                        cardfix=cardfix*(100-tsd->add_mdef[i].rate)/100;
2482                                        break;
2483                                }
2484                        }
2485                        //It was discovered that ranged defense also counts vs magic! [Skotlex]
2486                        if (ad.flag&BF_SHORT)
2487                                cardfix=cardfix*(100-tsd->near_attack_def_rate)/100;
2488                        else
2489                                cardfix=cardfix*(100-tsd->long_attack_def_rate)/100;
2490
2491                        cardfix=cardfix*(100-tsd->magic_def_rate)/100;
2492
2493                        if( tsd->sc.data[SC_MDEF_RATE] )
2494                                cardfix=cardfix*(100-tsd->sc.data[SC_MDEF_RATE]->val1)/100;
2495
2496                        if (cardfix != 1000)
2497                                MATK_RATE(cardfix/10);
2498                }
2499        }
2500
2501        damage_div_fix(ad.damage, ad.div_);
2502       
2503        if (flag.infdef && ad.damage)
2504                ad.damage = ad.damage>0?1:-1;
2505               
2506        ad.damage=battle_calc_damage(src,target,ad.damage,ad.div_,skill_num,skill_lv,ad.flag);
2507        if (map_flag_gvg2(target->m))
2508                ad.damage=battle_calc_gvg_damage(src,target,ad.damage,ad.div_,skill_num,skill_lv,ad.flag);
2509        return ad;
2510}
2511
2512/*==========================================
2513 * ‚»‚Ì‘Œƒ_ƒ??[ƒWŒvŽZ
2514 *------------------------------------------*/
2515struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *target,int skill_num,int skill_lv,int mflag)
2516{
2517        int skill;
2518        short i, nk;
2519        short s_ele;
2520
2521        struct map_session_data *sd, *tsd;
2522        struct Damage md; //DO NOT CONFUSE with md of mob_data!
2523        struct status_data *sstatus = status_get_status_data(src);
2524        struct status_data *tstatus = status_get_status_data(target);
2525
2526        memset(&md,0,sizeof(md));
2527
2528        if( src == NULL || target == NULL ){
2529                nullpo_info(NLP_MARK);
2530                return md;
2531        }
2532
2533        //Some initial values
2534        md.amotion=skill_get_inf(skill_num)&INF_GROUND_SKILL?0:sstatus->amotion;
2535        md.dmotion=tstatus->dmotion;
2536        md.div_=skill_get_num( skill_num,skill_lv );
2537        md.blewcount=skill_get_blewcount(skill_num,skill_lv);
2538        md.dmg_lv=ATK_DEF;
2539        md.flag=BF_MISC|BF_SKILL;
2540
2541        nk = skill_get_nk(skill_num);
2542       
2543        sd = BL_CAST(BL_PC, src);
2544        tsd = BL_CAST(BL_PC, target);
2545       
2546        if(sd) {
2547                sd->state.arrow_atk = 0;
2548                md.blewcount += battle_blewcount_bonus(sd, skill_num);
2549        }
2550
2551        s_ele = skill_get_ele(skill_num, skill_lv);
2552        if (s_ele < 0) //Attack that takes weapon's element for misc attacks? Make it neutral [Skotlex]
2553                s_ele = ELE_NEUTRAL;
2554
2555        //Skill Range Criteria
2556        md.flag |= battle_range_type(src, target, skill_num, skill_lv);
2557
2558        switch(skill_num){
2559        case HT_LANDMINE:
2560                md.damage=skill_lv*(sstatus->dex+75)*(100+sstatus->int_)/100;
2561                break;
2562        case HT_BLASTMINE:
2563                md.damage=skill_lv*(sstatus->dex/2+50)*(100+sstatus->int_)/100;
2564                break;
2565        case HT_CLAYMORETRAP:
2566                md.damage=skill_lv*(sstatus->dex/2+75)*(100+sstatus->int_)/100;
2567                break;
2568        case HT_BLITZBEAT:
2569        case SN_FALCONASSAULT:
2570                //Blitz-beat Damage.
2571                if(!sd || (skill = pc_checkskill(sd,HT_STEELCROW)) <= 0)
2572                        skill=0;
2573                md.damage=(sstatus->dex/10+sstatus->int_/2+skill*3+40)*2;
2574                if(mflag > 1) //Autocasted Blitz.
2575                        nk|=NK_SPLASHSPLIT;
2576               
2577                if (skill_num == SN_FALCONASSAULT)
2578                {
2579                        //Div fix of Blitzbeat
2580                        skill = skill_get_num(HT_BLITZBEAT, 5);
2581                        damage_div_fix(md.damage, skill); 
2582
2583                        //Falcon Assault Modifier
2584                        md.damage=md.damage*(150+70*skill_lv)/100;
2585                }
2586                break;
2587        case TF_THROWSTONE:
2588                md.damage=50;
2589                break;
2590        case BA_DISSONANCE:
2591                md.damage=30+skill_lv*10;
2592                if (sd)
2593                        md.damage+= 3*pc_checkskill(sd,BA_MUSICALLESSON);
2594                break;
2595        case NPC_SELFDESTRUCTION:
2596                md.damage = sstatus->hp;
2597                break;
2598        case NPC_SMOKING:
2599                md.damage=3;
2600                break;
2601        case NPC_DARKBREATH:
2602                md.damage = 500 + (skill_lv-1)*1000 + rand()%1000;
2603                if(md.damage > 9999) md.damage = 9999;
2604                break;
2605        case PA_PRESSURE:
2606                md.damage=500+300*skill_lv;
2607                break;
2608        case PA_GOSPEL:
2609                md.damage = 1+rand()%9999;
2610                break;
2611        case CR_ACIDDEMONSTRATION: // updated the formula based on a Japanese formula found to be exact [Reddozen]
2612                if(tstatus->vit+sstatus->int_) //crash fix
2613                        md.damage = 7*tstatus->vit*sstatus->int_*sstatus->int_ / (10*(tstatus->vit+sstatus->int_));
2614                else
2615                        md.damage = 0;
2616                if (tsd) md.damage>>=1;
2617                if (md.damage < 0 || md.damage > INT_MAX>>1)
2618                //Overflow prevention, will anyone whine if I cap it to a few billion?
2619                //Not capped to INT_MAX to give some room for further damage increase.
2620                        md.damage = INT_MAX>>1;
2621                break;
2622        case NJ_ZENYNAGE:
2623                md.damage = skill_get_zeny(skill_num ,skill_lv);
2624                if (!md.damage) md.damage = 2;
2625                md.damage = md.damage + rand()%md.damage;
2626                if (is_boss(target))
2627                        md.damage=md.damage/3;
2628                else if (tsd)
2629                        md.damage=md.damage/2;
2630                break;
2631        case GS_FLING:
2632                md.damage = sd?sd->status.job_level:status_get_lv(src);
2633                break;
2634        case HVAN_EXPLOSION:    //[orn]
2635                md.damage = sstatus->max_hp * (50 + 50 * skill_lv) / 100 ;
2636                break ;
2637        case ASC_BREAKER:
2638                md.damage = 500+rand()%500 + 5*skill_lv * sstatus->int_;
2639                nk|=NK_IGNORE_FLEE|NK_NO_ELEFIX; //These two are not properties of the weapon based part.
2640                break;
2641        case HW_GRAVITATION:
2642                md.damage = 200+200*skill_lv;
2643                md.dmotion = 0; //No flinch animation.
2644                break;
2645        case NPC_EVILLAND:
2646                md.damage = (skill_lv>6)?666:skill_lv*100;
2647//Why the hell is this supposed to be above the break?
2648        case WL_SHADOWBURN: // Warlock ShadowBurn dark element damage [Brain]
2649                s_ele = ELE_DARK;
2650                md.damage = ((300 + 20*skill_lv)/100)*((sstatus->int_*(rand()%300+500))/100); //Fixed between min and max matk for now
2651                break;
2652               
2653// Wouldn't this work better?
2654
2655/*      case WL_SHADOWBURN: // Warlock ShadowBurn dark element damage [Brain]
2656                s_ele = ELE_DARK;
2657                md.damage = ((300 + 20*skill_lv)/100)*((sstatus->int_*(rand()%300+500))/100); //Fixed between min and max matk for now
2658break;*/
2659        }
2660
2661        if (nk&NK_SPLASHSPLIT){ // Divide ATK among targets
2662                if(mflag>0)
2663                        md.damage/= mflag;
2664                else
2665                        ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_num, skill_get_name(skill_num));
2666        }
2667
2668        damage_div_fix(md.damage, md.div_);
2669       
2670        if (!(nk&NK_IGNORE_FLEE))
2671        {
2672                struct status_change *sc = status_get_sc(target);
2673                i = 0; //Temp for "hit or no hit"
2674                if(sc && sc->opt1 && sc->opt1 != OPT1_STONEWAIT)
2675                        i = 1;
2676                else {
2677                        short
2678                                flee = tstatus->flee,
2679                                hitrate=80; //Default hitrate
2680
2681                        if(battle_config.agi_penalty_type && 
2682                                battle_config.agi_penalty_target&target->type)
2683                        {       
2684                                unsigned char attacker_count; //256 max targets should be a sane max
2685                                attacker_count = unit_counttargeted(target,battle_config.agi_penalty_count_lv);
2686                                if(attacker_count >= battle_config.agi_penalty_count)
2687                                {
2688                                        if (battle_config.agi_penalty_type == 1)
2689                                                flee = (flee * (100 - (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num))/100;
2690                                        else //asume type 2: absolute reduction
2691                                                flee -= (attacker_count - (battle_config.agi_penalty_count - 1))*battle_config.agi_penalty_num;
2692                                        if(flee < 1) flee = 1;
2693                                }
2694                        }
2695
2696                        hitrate+= sstatus->hit - flee;
2697                        hitrate = cap_value(hitrate, battle_config.min_hitrate, battle_config.max_hitrate);
2698
2699                        if(rand()%100 < hitrate)
2700                                i = 1;
2701                }
2702                if (!i) {
2703                        md.damage = 0;
2704                        md.dmg_lv=ATK_FLEE;
2705                }
2706        }
2707
2708        if(md.damage && tsd && !(nk&NK_NO_CARDFIX_DEF)){
2709                int cardfix = 10000;
2710                int race2 = status_get_race2(src);
2711                if (!(nk&NK_NO_ELEFIX))
2712                        cardfix=cardfix*(100-tsd->subele[s_ele])/100;
2713                cardfix=cardfix*(100-tsd->subsize[sstatus->size])/100;
2714                cardfix=cardfix*(100-tsd->subrace2[race2])/100;
2715                cardfix=cardfix*(100-tsd->subrace[sstatus->race])/100;
2716                cardfix=cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS])/100;
2717                cardfix=cardfix*(100-tsd->misc_def_rate)/100;
2718                if(md.flag&BF_SHORT)
2719                        cardfix=cardfix*(100-tsd->near_attack_def_rate)/100;
2720                else    // BF_LONG (there's no other choice)
2721                        cardfix=cardfix*(100-tsd->long_attack_def_rate)/100;
2722
2723                if (cardfix != 10000)
2724                        md.damage=md.damage*cardfix/10000;
2725        }
2726
2727        if (sd && (i = pc_skillatk_bonus(sd, skill_num)))
2728                md.damage += md.damage*i/100;
2729
2730        if(md.damage < 0)
2731                md.damage = 0;
2732        else if(md.damage && tstatus->mode&MD_PLANT)
2733                md.damage = 1;
2734
2735        if(!(nk&NK_NO_ELEFIX))
2736                md.damage=battle_attr_fix(src, target, md.damage, s_ele, tstatus->def_ele, tstatus->ele_lv);
2737
2738        md.damage=battle_calc_damage(src,target,md.damage,md.div_,skill_num,skill_lv,md.flag);
2739        if (map_flag_gvg2(target->m))
2740                md.damage=battle_calc_gvg_damage(src,target,md.damage,md.div_,skill_num,skill_lv,md.flag);
2741
2742        if (skill_num == NJ_ZENYNAGE && sd)
2743        {       //Time to Pay Up.
2744                if ( md.damage > sd->status.zeny )
2745                        md.damage=sd->status.zeny;
2746                pc_payzeny(sd, md.damage);
2747        }
2748
2749        return md;
2750}
2751/*==========================================
2752 * ƒ_ƒ??[ƒWŒvŽZˆêЇ?ˆ—?—p
2753 *------------------------------------------*/
2754struct Damage battle_calc_attack(int attack_type,struct block_list *bl,struct block_list *target,int skill_num,int skill_lv,int count)
2755{
2756        struct Damage d;
2757        switch(attack_type) {
2758        case BF_WEAPON: d = battle_calc_weapon_attack(bl,target,skill_num,skill_lv,count); break;
2759        case BF_MAGIC:  d = battle_calc_magic_attack(bl,target,skill_num,skill_lv,count);  break;
2760        case BF_MISC:   d = battle_calc_misc_attack(bl,target,skill_num,skill_lv,count);   break;
2761        default:
2762                ShowError("battle_calc_attack: unknown attack type! %d\n",attack_type);
2763                memset(&d,0,sizeof(d));
2764                break;
2765        }
2766        if (d.damage + d.damage2 < 1)
2767        {       //Miss/Absorbed
2768                //Weapon attacks should go through to cause additional effects.
2769                if (d.dmg_lv != ATK_LUCKY && attack_type&(BF_MAGIC|BF_MISC))
2770                        d.dmg_lv = ATK_FLEE;
2771                d.dmotion = 0;
2772        }
2773        return d;
2774}
2775
2776//Calculates BF_WEAPON returned damage.
2777int battle_calc_return_damage(struct block_list* bl, int damage, int flag)
2778{
2779        struct map_session_data* sd = NULL;
2780        int rdamage = 0;
2781
2782        sd = BL_CAST(BL_PC, bl);
2783
2784        //Bounces back part of the damage.
2785        if (flag & BF_SHORT) {
2786                struct status_change* sc;
2787                if (sd && sd->short_weapon_damage_return)
2788                {
2789                        rdamage += damage * sd->short_weapon_damage_return / 100;
2790                        if(rdamage < 1) rdamage = 1;
2791                }
2792                sc = status_get_sc(bl);
2793                if (sc && sc->data[SC_REFLECTSHIELD])
2794                {
2795                        rdamage += damage * sc->data[SC_REFLECTSHIELD]->val2 / 100;
2796                        if (rdamage < 1) rdamage = 1;
2797                }
2798        } else {
2799                if (sd && sd->long_weapon_damage_return)
2800                {
2801                        rdamage += damage * sd->long_weapon_damage_return / 100;
2802                        if (rdamage < 1) rdamage = 1;
2803                }
2804        }
2805        return rdamage;
2806}
2807
2808void battle_drain(TBL_PC *sd, struct block_list *tbl, int rdamage, int ldamage, int race, int boss)
2809{
2810        struct weapon_data *wd;
2811        int type, thp = 0, tsp = 0, rhp = 0, rsp = 0, hp, sp, i, *damage;
2812        for (i = 0; i < 4; i++) {
2813                //First two iterations: Right hand
2814                if (i < 2) { wd = &sd->right_weapon; damage = &rdamage; }
2815                else { wd = &sd->left_weapon; damage = &ldamage; }
2816                if (*damage <= 0) continue;
2817                //First and Third iterations: race, other two boss/nonboss state
2818                if (i == 0 || i == 2) 
2819                        type = race;
2820                else
2821                        type = boss?RC_BOSS:RC_NONBOSS;
2822               
2823                hp = wd->hp_drain[type].value;
2824                if (wd->hp_drain[type].rate)
2825                        hp += battle_calc_drain(*damage, wd->hp_drain[type].rate, wd->hp_drain[type].per);
2826
2827                sp = wd->sp_drain[type].value;
2828                if (wd->sp_drain[type].rate)
2829                        sp += battle_calc_drain(*damage, wd->sp_drain[type].rate, wd->sp_drain[type].per);
2830
2831                if (hp) {
2832                        if (wd->hp_drain[type].type)
2833                                rhp += hp;
2834                        thp += hp;
2835                }
2836                if (sp) {
2837                        if (wd->sp_drain[type].type)
2838                                rsp += sp;
2839                        tsp += sp;
2840                }
2841        }
2842
2843        if (sd->sp_vanish_rate && rand()%1000 < sd->sp_vanish_rate)
2844                status_percent_damage(&sd->bl, tbl, 0, (unsigned char)sd->sp_vanish_per, false);
2845//I don't know about this. But it looks like it fits fine
2846        // Adept Blood Pact drains 5% damage per hit [FlavioJS/Brain]
2847        if( pc_checkskill(sd, AD_BLOODPACT) > 0 )
2848                thp += battle_calc_drain(rdamage,1000,5);
2849
2850        // Warlock Soul Steal drains 1%*skilllv damage per hit [Brain]
2851        if( pc_checkskill(sd, WL_SOULSTEAL) > 0 )
2852                tsp += battle_calc_drain(rdamage,1000,pc_checkskill(sd,WL_SOULSTEAL));
2853        // Warlock Touch of Corruption burns 1%*skilllv damage as SP per hit [Brain]
2854        if( pc_checkskill(sd, WL_CORRUPTION) > 0 ) {// This is the opener, whoops lol.
2855                int corrupt_sp;
2856                corrupt_sp = battle_calc_drain(rdamage,1000,pc_checkskill(sd,WL_CORRUPTION));
2857                if(status_damage(NULL, tbl, 0, corrupt_sp, 0, 3))
2858                        rhp += corrupt_sp;//If SP damage was caused, increase HP damage too
2859        }// Where does this bracket open?
2860
2861        if (!thp && !tsp) return;
2862
2863        status_heal(&sd->bl, thp, tsp, battle_config.show_hp_sp_drain?3:1);
2864       
2865        if (rhp || rsp)
2866                status_zap(tbl, rhp, rsp);
2867}
2868
2869/*==========================================
2870 * ’Ê?í?UŒ‚?ˆ—?‚܂Ƃß
2871 *------------------------------------------*/
2872enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* target, unsigned int tick, int flag)
2873{
2874        struct map_session_data *sd = NULL, *tsd = NULL;
2875        struct status_data *sstatus, *tstatus;
2876        struct status_change *sc, *tsc;
2877        int damage,rdamage=0,rdelay=0;
2878        int skillv;
2879        struct Damage wd;
2880
2881        nullpo_retr(ATK_NONE, src);
2882        nullpo_retr(ATK_NONE, target);
2883
2884        if (src->prev == NULL || target->prev == NULL)
2885                return ATK_NONE;
2886
2887        sd = BL_CAST(BL_PC, src);
2888        tsd = BL_CAST(BL_PC, target);
2889
2890        sstatus = status_get_status_data(src);
2891        tstatus = status_get_status_data(target);
2892
2893        sc = status_get_sc(src);
2894        tsc = status_get_sc(target);
2895
2896        if (sc && !sc->count) //Avoid sc checks when there's none to check for. [Skotlex]
2897                sc = NULL;
2898        if (tsc && !tsc->count)
2899                tsc = NULL;
2900       
2901        if (sd)
2902        {
2903                sd->state.arrow_atk = (sd->status.weapon == W_BOW || (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE));
2904                if (sd->state.arrow_atk)
2905                {
2906                        int index = sd->equip_index[EQI_AMMO];
2907                        if (index<0) {
2908                                clif_arrow_fail(sd,0);
2909                                return ATK_NONE;
2910                        }
2911                        //Ammo check by Ishizu-chan
2912                        if (sd->inventory_data[index])
2913                        switch (sd->status.weapon) {
2914                        case W_BOW:
2915                                if (sd->inventory_data[index]->look != A_ARROW) {
2916                                        clif_arrow_fail(sd,0);
2917                                        return ATK_NONE;
2918                                }
2919                        break;
2920                        case W_REVOLVER:
2921                        case W_RIFLE:
2922                        case W_GATLING:
2923                        case W_SHOTGUN:
2924                                if (sd->inventory_data[index]->look != A_BULLET) {
2925                                        clif_arrow_fail(sd,0);
2926                                        return ATK_NONE;
2927                                }
2928                        break;
2929                        case W_GRENADE:
2930                                if (sd->inventory_data[index]->look != A_GRENADE) {
2931                                        clif_arrow_fail(sd,0);
2932                                        return ATK_NONE;
2933                                }
2934                        break;
2935                        }
2936                }
2937        }
2938
2939        if (sc && sc->data[SC_CLOAKING] && !(sc->data[SC_CLOAKING]->val4&2))
2940                status_change_end(src,SC_CLOAKING,-1);
2941
2942        //Check for counter attacks that block your attack. [Skotlex]
2943        if(tsc)
2944        {
2945                if(tsc->data[SC_AUTOCOUNTER] &&
2946                        status_check_skilluse(target, src, KN_AUTOCOUNTER, 1)
2947                )       {
2948                        int dir = map_calc_dir(target,src->x,src->y);
2949                        int t_dir = unit_getdir(target);
2950                        int dist = distance_bl(src, target);
2951                        if(dist <= 0 || (!map_check_dir(dir,t_dir) && dist <= tstatus->rhw.range+1))
2952                        {
2953                                int skilllv = tsc->data[SC_AUTOCOUNTER]->val1;
2954                                clif_skillcastcancel(target); //Remove the casting bar. [Skotlex]
2955                                clif_damage(src, target, tick, sstatus->amotion, 1, 0, 1, 0, 0); //Display MISS.
2956                                status_change_end(target,SC_AUTOCOUNTER,-1);
2957                                skill_attack(BF_WEAPON,target,target,src,KN_AUTOCOUNTER,skilllv,tick,0);
2958                                return ATK_NONE;
2959                        }
2960                }
2961                if (tsc->data[SC_BLADESTOP_WAIT] && !is_boss(src)) {
2962                        int skilllv = tsc->data[SC_BLADESTOP_WAIT]->val1;
2963                        int duration = skill_get_time2(MO_BLADESTOP,skilllv);
2964                        status_change_end(target, SC_BLADESTOP_WAIT, -1);
2965                        if(sc_start4(src, SC_BLADESTOP, 100, sd?pc_checkskill(sd, MO_BLADESTOP):5, 0, 0, (int)target, duration))
2966                        {       //Target locked.
2967                                clif_damage(src, target, tick, sstatus->amotion, 1, 0, 1, 0, 0); //Display MISS.
2968                                clif_bladestop(target,src,1);
2969                                sc_start4(target, SC_BLADESTOP, 100, skilllv, 0, 0,(int)src, duration);
2970                                return ATK_NONE;
2971                        }
2972                }
2973        }
2974
2975        if(sd && (skillv = pc_checkskill(sd,MO_TRIPLEATTACK)) > 0)
2976        {
2977                int triple_rate= 30 - skillv; //Base Rate
2978                if (sc && sc->data[SC_SKILLRATE_UP] && sc->data[SC_SKILLRATE_UP]->val1 == MO_TRIPLEATTACK)
2979                {
2980                        triple_rate+= triple_rate*(sc->data[SC_SKILLRATE_UP]->val2)/100;
2981                        status_change_end(src,SC_SKILLRATE_UP,-1);
2982                }
2983                if (rand()%100 < triple_rate)
2984                        //FIXME: invalid return type!
2985                        return (damage_lv)skill_attack(BF_WEAPON,src,src,target,MO_TRIPLEATTACK,skillv,tick,0);
2986        }
2987
2988        if (sc)
2989        {
2990                if (sc->data[SC_SACRIFICE])
2991                        //FIXME: invalid return type!
2992                        return (damage_lv)skill_attack(BF_WEAPON,src,src,target,PA_SACRIFICE,sc->data[SC_SACRIFICE]->val1,tick,0);
2993                if (sc->data[SC_MAGICALATTACK])
2994                        //FIXME: invalid return type!
2995                        return (damage_lv)skill_attack(BF_MAGIC,src,src,target,NPC_MAGICALATTACK,sc->data[SC_MAGICALATTACK]->val1,tick,0);
2996        }
2997
2998        wd = battle_calc_weapon_attack(src, target, 0, 0, flag);
2999
3000        if (sd && sd->state.arrow_atk) //Consume arrow.
3001                battle_consume_ammo(sd, 0, 0);
3002
3003        damage = wd.damage + wd.damage2;
3004        if (damage > 0 && src != target) {
3005                rdamage = battle_calc_return_damage(target, damage, wd.flag);
3006                if (rdamage > 0) {
3007                        rdelay = clif_damage(src, src, tick, wd.amotion, sstatus->dmotion, rdamage, 1, 4, 0);
3008                        //Use Reflect Shield to signal this kind of skill trigger. [Skotlex]
3009                        skill_additional_effect(target,src,CR_REFLECTSHIELD,1,BF_WEAPON|BF_SHORT|BF_NORMAL,tick);
3010                }
3011        }
3012
3013        wd.dmotion = clif_damage(src, target, tick, wd.amotion, wd.dmotion, wd.damage, wd.div_ , wd.type, wd.damage2);
3014
3015        if (sd && sd->splash_range > 0 && damage > 0)
3016                skill_castend_damage_id(src, target, 0, 1, tick, 0);
3017
3018        map_freeblock_lock();
3019
3020        battle_delay_damage(tick, wd.amotion, src, target, wd.flag, 0, 0, damage, wd.dmg_lv, wd.dmotion);
3021
3022        if (sc && sc->data[SC_AUTOSPELL] && rand()%100 < sc->data[SC_AUTOSPELL]->val4) {
3023                int sp = 0;
3024                int skillid = sc->data[SC_AUTOSPELL]->val2;
3025                int skilllv = sc->data[SC_AUTOSPELL]->val3;
3026                int i = rand()%100;
3027                if (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_SAGE)
3028                        i = 0; //Max chance, no skilllv reduction. [Skotlex]
3029                if (i >= 50) skilllv -= 2;
3030                else if (i >= 15) skilllv--;
3031                if (skilllv < 1) skilllv = 1;
3032                sp = skill_get_sp(skillid,skilllv) * 2 / 3;
3033
3034                if (status_charge(src, 0, sp)) {
3035                        switch (skill_get_casttype(skillid)) {
3036                                case CAST_GROUND:
3037                                        skill_castend_pos2(src, target->x, target->y, skillid, skilllv, tick, flag);
3038                                        break;
3039                                case CAST_NODAMAGE:
3040                                        skill_castend_nodamage_id(src, target, skillid, skilllv, tick, flag);
3041                                        break;
3042                                case CAST_DAMAGE:
3043                                        skill_castend_damage_id(src, target, skillid, skilllv, tick, flag);
3044                                        break;
3045                        }
3046                }
3047        }
3048        if (sd) {
3049                if (wd.flag & BF_WEAPON && src != target && damage > 0) {
3050                        if (battle_config.left_cardfix_to_right)
3051                                battle_drain(sd, target, wd.damage, wd.damage, tstatus->race, is_boss(target));
3052                        else
3053                                battle_drain(sd, target, wd.damage, wd.damage2, tstatus->race, is_boss(target));
3054                }
3055        }
3056        if (rdamage > 0) { //By sending attack type "none" skill_additional_effect won't be invoked. [Skotlex]
3057                if(tsd && src != target)
3058                        battle_drain(tsd, src, rdamage, rdamage, sstatus->race, is_boss(src));
3059                battle_delay_damage(tick, wd.amotion, target, src, 0, 0, 0, rdamage, ATK_DEF, rdelay);
3060        }
3061
3062        if (tsc) {
3063                if (tsc->data[SC_POISONREACT] && 
3064                        (rand()%100 < tsc->data[SC_POISONREACT]->val3
3065                        || sstatus->def_ele == ELE_POISON) &&
3066//                      check_distance_bl(src, target, tstatus->rhw.range+1) && Doesn't checks range! o.O;
3067                        status_check_skilluse(target, src, TF_POISON, 0)
3068                ) {     //Poison React
3069                        struct status_change_entry *sce = tsc->data[SC_POISONREACT];
3070                        if (sstatus->def_ele == ELE_POISON) {
3071                                sce->val2 = 0;
3072                                skill_attack(BF_WEAPON,target,target,src,AS_POISONREACT,sce->val1,tick,0);
3073                        } else {
3074                                skill_attack(BF_WEAPON,target,target,src,TF_POISON, 5, tick, 0);
3075                                --sce->val2;
3076                        }
3077                        if (sce->val2 <= 0)
3078                                status_change_end(target, SC_POISONREACT, -1);
3079                }
3080        }
3081        map_freeblock_unlock();
3082        return wd.dmg_lv;
3083}
3084//new battle check code, i speculate it. But it looks like it just calls other races and elements into one big one.
3085int battle_check_living(int race,int element)// Living creature check [Brain]
3086{
3087        if(element == ELE_UNDEAD || race == RC_UNDEAD // Undead element and race check
3088                || race == RC_DEMON                     // Demon race check
3089                || race == RC_FORMLESS                  // Formless race check
3090                || element == ELE_GHOST){               // Ghost element check
3091                return 0;
3092        }
3093        else {
3094        return 1;
3095        }
3096}
3097int battle_check_undead(int race,int element)
3098{
3099        if(battle_config.undead_detect_type == 0) {
3100                if(element == ELE_UNDEAD)
3101                        return 1;
3102        }
3103        else if(battle_config.undead_detect_type == 1) {
3104                if(race == RC_UNDEAD)
3105                        return 1;
3106        }
3107        else {
3108                if(element == ELE_UNDEAD || race == RC_UNDEAD)
3109                        return 1;
3110        }
3111        return 0;
3112}
3113
3114//Returns the upmost level master starting with the given object
3115struct block_list* battle_get_master(struct block_list *src)
3116{
3117        struct block_list *prev; //Used for infinite loop check (master of yourself?)
3118        do {
3119                prev = src;
3120                switch (src->type) {
3121                        case BL_PET:
3122                                if (((TBL_PET*)src)->msd)
3123                                        src = (struct block_list*)((TBL_PET*)src)->msd;
3124                                break;
3125                        case BL_MOB:
3126                                if (((TBL_MOB*)src)->master_id)
3127                                        src = map_id2bl(((TBL_MOB*)src)->master_id);
3128                                break;
3129                        case BL_HOM:
3130                                if (((TBL_HOM*)src)->master)
3131                                        src = (struct block_list*)((TBL_HOM*)src)->master;
3132                                break;
3133                        case BL_SKILL:
3134                                if (((TBL_SKILL*)src)->group && ((TBL_SKILL*)src)->group->src_id)
3135                                        src = map_id2bl(((TBL_SKILL*)src)->group->src_id);
3136                                break;
3137                }
3138        } while (src && src != prev);
3139        return prev;
3140}
3141
3142/*==========================================
3143 * Checks the state between two targets (rewritten by Skotlex)
3144 * (enemy, friend, party, guild, etc)
3145 * See battle.h for possible values/combinations
3146 * to be used here (BCT_* constants)
3147 * Return value is:
3148 * 1: flag holds true (is enemy, party, etc)
3149 * -1: flag fails
3150 * 0: Invalid target (non-targetable ever)
3151 *------------------------------------------*/
3152int battle_check_target( struct block_list *src, struct block_list *target,int flag)
3153{
3154        int m,state = 0; //Initial state none
3155        int strip_enemy = 1; //Flag which marks whether to remove the BCT_ENEMY status if it's also friend/ally.
3156        struct block_list *s_bl= src, *t_bl= target;
3157
3158        nullpo_retr(0, src);
3159        nullpo_retr(0, target);
3160
3161        m = target->m;
3162        if (flag&BCT_ENEMY && !map_flag_gvg(m) && !(status_get_mode(src)&MD_BOSS))
3163        {       //No offensive stuff while in Basilica.
3164                if (map_getcell(m,src->x,src->y,CELL_CHKBASILICA) ||
3165                        map_getcell(m,target->x,target->y,CELL_CHKBASILICA))
3166                        return -1;
3167        }
3168
3169        //t_bl/s_bl hold the 'master' of the attack, while src/target are the actual
3170        //objects involved.
3171        if ((t_bl = battle_get_master(target)) == NULL)
3172                t_bl = target;
3173
3174        if ((s_bl = battle_get_master(src)) == NULL)
3175                s_bl = src;
3176
3177        switch (target->type)
3178        {       //Checks on actual target
3179                case BL_PC:
3180                        if (((TBL_PC*)target)->invincible_timer != -1 || pc_isinvisible((TBL_PC*)target))
3181                                return -1; //Cannot be targeted yet.
3182                        break;
3183                case BL_MOB:
3184                        if((((TBL_MOB*)target)->special_state.ai == 2 || //Marine Spheres
3185                                (((TBL_MOB*)target)->special_state.ai == 3 && battle_config.summon_flora&1)) && //Floras
3186                                s_bl->type == BL_PC && src->type != BL_MOB)
3187                        {       //Targettable by players
3188                                state |= BCT_ENEMY;
3189                                strip_enemy = 0;
3190                        }
3191                        break;
3192                case BL_SKILL:
3193                {
3194                        TBL_SKILL *su = (TBL_SKILL*)target;
3195                        if (!su->group)
3196                                return 0;
3197                        if (skill_get_inf2(su->group->skill_id)&INF2_TRAP)
3198                        {       //Only a few skills can target traps...
3199                                switch (battle_getcurrentskill(src))
3200                                {
3201                                        case HT_REMOVETRAP:
3202                                        case AC_SHOWER:
3203                                        case WZ_SIGHTRASHER:
3204                                        case WZ_SIGHTBLASTER:
3205                                        case SM_MAGNUM:
3206                                                state |= BCT_ENEMY;
3207                                                strip_enemy = 0;
3208                                                break;
3209                                        default:
3210                                                return 0;
3211                                }
3212                        } else if (su->group->skill_id==WZ_ICEWALL)
3213                        {
3214                                state |= BCT_ENEMY;
3215                                strip_enemy = 0;
3216                        } else  //Excepting traps and icewall, you should not be able to target skills.
3217                                return 0;
3218                }
3219                        break;
3220                //Valid targets with no special checks here.
3221                case BL_HOM:
3222                        break;
3223                //All else not specified is an invalid target.
3224                default:       
3225                        return 0;
3226        }
3227
3228        switch (t_bl->type)
3229        {       //Checks on target master
3230                case BL_PC:
3231                {
3232                        TBL_PC *sd = (TBL_PC*)t_bl;
3233                        if (sd->status.karma && t_bl != s_bl && s_bl->type == BL_PC &&
3234                                ((TBL_PC*)s_bl)->status.karma)
3235                                state |= BCT_ENEMY; //Characters with bad karma may fight amongst them.
3236                        if (sd->state.monster_ignore && t_bl != s_bl && flag&BCT_ENEMY)
3237                                return 0; //Global inmunity to attacks.
3238                        if (sd->state.killable && t_bl != s_bl)
3239                        {
3240                                state |= BCT_ENEMY; //Universal Victim
3241                                strip_enemy = 0;
3242                        }
3243                        break;
3244                }
3245                case BL_MOB:
3246                {
3247                        TBL_MOB *md = (TBL_MOB*)t_bl;
3248
3249                        if (!(agit_flag && map[m].flag.gvg_castle) && md->guardian_data && md->guardian_data->guild_id)
3250                                return 0; //Disable guardians/emperiums owned by Guilds on non-woe times.
3251
3252                        if( md->barricade && !md->barricade->killable )
3253                                return 0;
3254                        break;
3255                }
3256        }
3257
3258        switch(src->type)
3259        {       //Checks on actual src type
3260                case BL_PET:
3261                        if (t_bl->type != BL_MOB && flag&BCT_ENEMY)
3262                                return 0; //Pet may not attack non-mobs.
3263                        if (t_bl->type == BL_MOB && ((TBL_MOB*)t_bl)->guardian_data && flag&BCT_ENEMY)
3264                                return 0; //pet may not attack Guardians/Emperium
3265                        break;
3266                case BL_SKILL:
3267                {
3268                        struct skill_unit *su = (struct skill_unit *)src;
3269                        if (!su->group)
3270                                return 0;
3271
3272                        if (su->group->src_id == target->id)
3273                        {
3274                                int inf2;
3275                                inf2 = skill_get_inf2(su->group->skill_id);
3276                                if (inf2&INF2_NO_TARGET_SELF)
3277                                        return -1;
3278                                if (inf2&INF2_TARGET_SELF)
3279                                        return 1;
3280                        }
3281                        break;
3282                }
3283        }
3284
3285        switch (s_bl->type)
3286        {       //Checks on source master
3287                case BL_PC:
3288                {
3289                        TBL_PC *sd = (TBL_PC*) s_bl;
3290                        if( s_bl != t_bl )
3291                        {
3292                                if( sd->state.killer )
3293                                {
3294                                        state |= BCT_ENEMY; //Is on a killing rampage :O
3295                                        strip_enemy = 0;
3296                                }
3297                                else if( sd->duel_group && !((!battle_config.duel_allow_pvp && map[m].flag.pvp) || (!battle_config.duel_allow_gvg && map_flag_gvg(m))) )
3298                                {
3299                                        if (t_bl->type == BL_PC &&
3300                                                (sd->duel_group == ((TBL_PC*)t_bl)->duel_group))
3301                                                //Duel targets can ONLY be your enemy, nothing else.
3302                                                return (BCT_ENEMY&flag)?1:-1;
3303                                        else // You can't target anything out of your duel
3304                                                return 0;
3305                                }
3306                        }
3307                        if (map_flag_gvg(m) && !sd->status.guild_id &&
3308                                t_bl->type == BL_MOB && ((TBL_MOB*)t_bl)->guardian_data)
3309                                return 0; //If you don't belong to a guild, can't target guardians/emperium.
3310                        if (t_bl->type != BL_PC)
3311                                state |= BCT_ENEMY; //Natural enemy.
3312                        break;
3313                }
3314                case BL_MOB:
3315                {
3316                        TBL_MOB*md = (TBL_MOB*)s_bl;
3317                        if (!(agit_flag && map[m].flag.gvg_castle) && md->guardian_data && md->guardian_data->guild_id)
3318                                return 0; //Disable guardians/emperium owned by Guilds on non-woe times.
3319                        if(md->state.killer/* || !(battle_config.mob_ai&0x400)*/)
3320                                state |= BCT_ENEMY; //By default everyone hates mobs.
3321                        else
3322                        {       //Smart enemy criteria.
3323                                if (!md->special_state.ai) { //Normal mobs.
3324                                        if (t_bl->type == BL_MOB && !((TBL_MOB*)t_bl)->special_state.ai)
3325                                                state |= BCT_PARTY; //Normal mobs with no ai are friends.
3326                                        else
3327                                                state |= BCT_ENEMY; //However, all else are enemies.
3328                                } else {
3329                                        if (t_bl->type == BL_MOB && !((TBL_MOB*)t_bl)->special_state.ai)
3330                                                state |= BCT_ENEMY; //Natural enemy for AI mobs are normal mobs.
3331                                }
3332                        }
3333                        break;
3334                }
3335                default:
3336                //Need some sort of default behaviour for unhandled types.
3337                        if (t_bl->type != s_bl->type)
3338                                state |= BCT_ENEMY;
3339                        break;
3340        }
3341       
3342        if ((flag&BCT_ALL) == BCT_ALL) { //All actually stands for all attackable chars
3343                if (target->type&BL_CHAR)
3344                        return 1;
3345                else
3346                        return -1;
3347        } else
3348        if (flag == BCT_NOONE) //Why would someone use this? no clue.
3349                return -1;
3350       
3351        if (t_bl == s_bl)
3352        {       //No need for further testing.
3353                state |= BCT_SELF|BCT_PARTY|BCT_GUILD;
3354                if (state&BCT_ENEMY && strip_enemy)
3355                        state&=~BCT_ENEMY;
3356                return (flag&state)?1:-1;
3357        }
3358       
3359        if (map_flag_vs(m)) { //Check rivalry settings.
3360                if (flag&(BCT_PARTY|BCT_ENEMY)) {
3361                        int s_party = status_get_party_id(s_bl);
3362                        if (
3363                                !(map[m].flag.pvp && map[m].flag.pvp_noparty) &&
3364                                !(map_flag_gvg(m) && map[m].flag.gvg_noparty) &&
3365                                s_party && s_party == status_get_party_id(t_bl)
3366                        )
3367                                state |= BCT_PARTY;
3368                        else
3369                                state |= BCT_ENEMY;
3370                }
3371                if (flag&(BCT_GUILD|BCT_ENEMY)) {
3372                        int s_guild = status_get_guild_id(s_bl);
3373                        int t_guild = status_get_guild_id(t_bl);
3374                        if (
3375                                !(map[m].flag.pvp && map[m].flag.pvp_noguild) &&
3376                                s_guild && t_guild && (s_guild == t_guild || guild_isallied(s_guild, t_guild))
3377                        )
3378                                state |= BCT_GUILD;
3379                        else
3380                                state |= BCT_ENEMY;
3381                }
3382                if (state&BCT_ENEMY && battle_config.pk_mode && !map_flag_gvg(m) &&
3383                        s_bl->type == BL_PC && t_bl->type == BL_PC)
3384                {       //Prevent novice engagement on pk_mode (feature by Valaris)
3385                        TBL_PC *sd = (TBL_PC*)s_bl, *sd2 = (TBL_PC*)t_bl;
3386                        if (
3387                                (sd->class_&MAPID_UPPERMASK) == MAPID_NOVICE ||
3388                                (sd2->class_&MAPID_UPPERMASK) == MAPID_NOVICE ||
3389                                (int)sd->status.base_level < battle_config.pk_min_level ||
3390                                (int)sd2->status.base_level < battle_config.pk_min_level ||
3391                                (battle_config.pk_level_range && abs((int)sd->status.base_level - (int)sd2->status.base_level) > battle_config.pk_level_range)
3392                        )
3393                                state&=~BCT_ENEMY;
3394                }
3395        } else { //Non pvp/gvg, check party/guild settings.
3396                if (flag&BCT_PARTY || state&BCT_ENEMY) {
3397                        int s_party = status_get_party_id(s_bl);
3398                        if(s_party && s_party == status_get_party_id(t_bl))
3399                                state |= BCT_PARTY;
3400                }
3401                if (flag&BCT_GUILD || state&BCT_ENEMY) {
3402                        int s_guild = status_get_guild_id(s_bl);
3403                        int t_guild = status_get_guild_id(t_bl);
3404                        if(s_guild && t_guild && (s_guild == t_guild || guild_isallied(s_guild, t_guild)))
3405                                state |= BCT_GUILD;
3406                }
3407        }
3408       
3409        if (!state) //If not an enemy, nor a guild, nor party, nor yourself, it's neutral.
3410                state = BCT_NEUTRAL;
3411        //Alliance state takes precedence over enemy one.
3412        else if (state&BCT_ENEMY && strip_enemy && state&(BCT_SELF|BCT_PARTY|BCT_GUILD))
3413                state&=~BCT_ENEMY;
3414
3415        return (flag&state)?1:-1;
3416}
3417/*==========================================
3418 * ŽË’ö”»’è
3419 *------------------------------------------*/
3420bool battle_check_range(struct block_list *src,struct block_list *bl,int range)
3421{
3422        int d;
3423        nullpo_retr(false, src);
3424        nullpo_retr(false, bl);
3425
3426        if(src->m != bl->m)     // ˆá‚€ƒ}ƒbƒv
3427                return false;
3428
3429        if (!check_distance_bl(src, bl, range))
3430                return false;
3431
3432        if((d=distance_bl(src, bl)) < 2) //No need for path checking.
3433                return true;
3434
3435        if (d> AREA_SIZE)
3436                return false; //Avoid targetting objects beyond your range of sight.
3437
3438        // ?áŠQ•š”»’è
3439        return path_search_long(NULL,src->m,src->x,src->y,bl->x,bl->y,CELL_CHKWALL);
3440}
3441
3442static const struct _battle_data {
3443        const char* str;
3444        int* val;
3445        int defval;
3446        int min;
3447        int max;
3448} battle_data[] = {
3449        { "warp_point_debug",                   &battle_config.warp_point_debug,                0,      0,      1,              },
3450        { "enable_critical",                    &battle_config.enable_critical,                 BL_PC,  BL_NUL, BL_ALL,         },
3451        { "mob_critical_rate",                  &battle_config.mob_critical_rate,               100,    0,      INT_MAX,        },
3452        { "critical_rate",                      &battle_config.critical_rate,                   100,    0,      INT_MAX,        },
3453        { "enable_baseatk",                     &battle_config.enable_baseatk,                  BL_PC|BL_HOM, BL_NUL, BL_ALL,   },
3454        { "enable_perfect_flee",                &battle_config.enable_perfect_flee,             BL_PC|BL_PET, BL_NUL, BL_ALL,   },
3455        { "casting_rate",                       &battle_config.cast_rate,                       100,    0,      INT_MAX,        },
3456        { "delay_rate",                         &battle_config.delay_rate,                      100,    0,      INT_MAX,        },
3457        { "delay_dependon_dex",                 &battle_config.delay_dependon_dex,              0,      0,      1,              },
3458        { "delay_dependon_agi",                 &battle_config.delay_dependon_agi,              0,      0,      1,              },
3459        { "skill_delay_attack_enable",          &battle_config.sdelay_attack_enable,            0,      0,      1,              },
3460        { "left_cardfix_to_right",              &battle_config.left_cardfix_to_right,           0,      0,      1,              },
3461        { "skill_add_range",                    &battle_config.skill_add_range,                 0,      0,      INT_MAX,        },
3462        { "skill_out_range_consume",            &battle_config.skill_out_range_consume,         1,      0,      1,              },
3463        { "skillrange_by_distance",             &battle_config.skillrange_by_distance,          ~BL_PC, BL_NUL, BL_ALL,         },
3464        { "skillrange_from_weapon",             &battle_config.use_weapon_skill_range,          ~BL_PC, BL_NUL, BL_ALL,         },
3465        { "player_damage_delay_rate",           &battle_config.pc_damage_delay_rate,            100,    0,      INT_MAX,        },
3466        { "defunit_not_enemy",                  &battle_config.defnotenemy,                     0,      0,      1,              },
3467        { "gvg_traps_target_all",               &battle_config.vs_traps_bctall,                 BL_PC,  BL_NUL, BL_ALL,         },
3468        { "traps_setting",                      &battle_config.traps_setting,                   0,      0,      1,              },
3469        { "summon_flora_setting",               &battle_config.summon_flora,                    1|2,    0,      1|2,            },
3470        { "clear_skills_on_death",              &battle_config.clear_unit_ondeath,              BL_NUL, BL_NUL, BL_ALL,         },
3471        { "clear_skills_on_warp",               &battle_config.clear_unit_onwarp,               BL_ALL, BL_NUL, BL_ALL,         },
3472        { "random_monster_checklv",             &battle_config.random_monster_checklv,          1,      0,      1,              },
3473        { "attribute_recover",                  &battle_config.attr_recover,                    1,      0,      1,              },
3474        { "flooritem_lifetime",                 &battle_config.flooritem_lifetime,              60000,  1000,   INT_MAX,        },
3475        { "item_auto_get",                      &battle_config.item_auto_get,                   0,      0,      1,              },
3476        { "item_first_get_time",                &battle_config.item_first_get_time,             3000,   0,      INT_MAX,        },
3477        { "item_second_get_time",               &battle_config.item_second_get_time,            1000,   0,      INT_MAX,        },
3478        { "item_third_get_time",                &battle_config.item_third_get_time,             1000,   0,      INT_MAX,        },
3479        { "mvp_item_first_get_time",            &battle_config.mvp_item_first_get_time,         10000,  0,      INT_MAX,        },
3480        { "mvp_item_second_get_time",           &battle_config.mvp_item_second_get_time,        10000,  0,      INT_MAX,        },
3481        { "mvp_item_third_get_time",            &battle_config.mvp_item_third_get_time,         2000,   0,      INT_MAX,        },
3482        { "drop_rate0item",                     &battle_config.drop_rate0item,                  0,      0,      1,              },
3483        { "base_exp_rate",                      &battle_config.base_exp_rate,                   100,    0,      INT_MAX,        },
3484        { "job_exp_rate",                       &battle_config.job_exp_rate,                    100,    0,      INT_MAX,        },
3485        { "pvp_exp",                            &battle_config.pvp_exp,                         1,      0,      1,              },
3486        { "death_penalty_type",                 &battle_config.death_penalty_type,              0,      0,      2,              },
3487        { "death_penalty_base",                 &battle_config.death_penalty_base,              0,      0,      INT_MAX,        },
3488        { "death_penalty_job",                  &battle_config.death_penalty_job,               0,      0,      INT_MAX,        },
3489        { "zeny_penalty",                       &battle_config.zeny_penalty,                    0,      0,      INT_MAX,        },
3490        { "hp_rate",                            &battle_config.hp_rate,                         100,    1,      INT_MAX,        },
3491        { "sp_rate",                            &battle_config.sp_rate,                         100,    1,      INT_MAX,        },
3492        { "restart_hp_rate",                    &battle_config.restart_hp_rate,                 0,      0,      100,            },
3493        { "restart_sp_rate",                    &battle_config.restart_sp_rate,                 0,      0,      100,            },
3494        { "guild_aura",                         &battle_config.guild_aura,                      31,     0,      31,             },
3495        { "mvp_hp_rate",                        &battle_config.mvp_hp_rate,                     100,    1,      INT_MAX,        },
3496        { "mvp_exp_rate",                       &battle_config.mvp_exp_rate,                    100,    0,      INT_MAX,        },
3497        { "monster_hp_rate",                    &battle_config.monster_hp_rate,                 100,    1,      INT_MAX,        },
3498        { "monster_max_aspd",                   &battle_config.monster_max_aspd,                199,    100,    199,            },
3499        { "view_range_rate",                    &battle_config.view_range_rate,                 100,    0,      INT_MAX,        },
3500        { "chase_range_rate",                   &battle_config.chase_range_rate,                100,    0,      INT_MAX,        },
3501        { "gtb_sc_immunity",                    &battle_config.gtb_sc_immunity,                 50,     0,      INT_MAX,        },
3502        { "guild_max_castles",                  &battle_config.guild_max_castles,               0,      0,      INT_MAX,        },
3503        { "guild_skill_relog_delay",            &battle_config.guild_skill_relog_delay,         0,      0,      1,              },
3504        { "emergency_call",                     &battle_config.emergency_call,                  11,     0,      31,             },
3505        { "atcommand_gm_only",                  &battle_config.atc_gmonly,                      0,      0,      1,              },
3506        { "atcommand_spawn_quantity_limit",     &battle_config.atc_spawn_quantity_limit,        100,    0,      INT_MAX,        },
3507        { "atcommand_slave_clone_limit",        &battle_config.atc_slave_clone_limit,           25,     0,      INT_MAX,        },
3508        { "partial_name_scan",                  &battle_config.partial_name_scan,               0,      0,      1,              },
3509        { "gm_all_skill",                       &battle_config.gm_allskill,                     0,      0,      100,            },
3510        { "gm_all_equipment",                   &battle_config.gm_allequip,                     0,      0,      100,            },
3511        { "gm_skill_unconditional",             &battle_config.gm_skilluncond,                  0,      0,      100,            },
3512        { "gm_join_chat",                       &battle_config.gm_join_chat,                    0,      0,      100,            },
3513        { "gm_kick_chat",                       &battle_config.gm_kick_chat,                    0,      0,      100,            },
3514        { "player_skillfree",                   &battle_config.skillfree,                       0,      0,      1,              },
3515        { "player_skillup_limit",               &battle_config.skillup_limit,                   1,      0,      1,              },
3516        { "weapon_produce_rate",                &battle_config.wp_rate,                         100,    0,      INT_MAX,        },
3517        { "potion_produce_rate",                &battle_config.pp_rate,                         100,    0,      INT_MAX,        },
3518        { "monster_active_enable",              &battle_config.monster_active_enable,           1,      0,      1,              },
3519        { "monster_damage_delay_rate",          &battle_config.monster_damage_delay_rate,       100,    0,      INT_MAX,        },
3520        { "monster_loot_type",                  &battle_config.monster_loot_type,               0,      0,      1,              },
3521//      { "mob_skill_use",                      &battle_config.mob_skill_use,                   1,      0,      1,              }, //Deprecated
3522        { "mob_skill_rate",                     &battle_config.mob_skill_rate,                  100,    0,      INT_MAX,        },
3523        { "mob_skill_delay",                    &battle_config.mob_skill_delay,                 100,    0,      INT_MAX,        },
3524        { "mob_count_rate",                     &battle_config.mob_count_rate,                  100,    0,      INT_MAX,        },
3525        { "mob_spawn_delay",                    &battle_config.mob_spawn_delay,                 100,    0,      INT_MAX,        },
3526        { "plant_spawn_delay",                  &battle_config.plant_spawn_delay,               100,    0,      INT_MAX,        },
3527        { "boss_spawn_delay",                   &battle_config.boss_spawn_delay,                100,    0,      INT_MAX,        },
3528        { "no_spawn_on_player",                 &battle_config.no_spawn_on_player,              0,      0,      100,            },
3529        { "force_random_spawn",                 &battle_config.force_random_spawn,              0,      0,      1,              },
3530        { "slaves_inherit_mode",                &battle_config.slaves_inherit_mode,             2,      0,      3,              },
3531        { "slaves_inherit_speed",               &battle_config.slaves_inherit_speed,            3,      0,      3,              },
3532        { "summons_trigger_autospells",         &battle_config.summons_trigger_autospells,      1,      0,      1,              },
3533        { "pc_damage_walk_delay_rate",          &battle_config.pc_walk_delay_rate,              20,     0,      INT_MAX,        },
3534        { "damage_walk_delay_rate",             &battle_config.walk_delay_rate,                 100,    0,      INT_MAX,        },
3535        { "multihit_delay",                     &battle_config.multihit_delay,                  80,     0,      INT_MAX,        },
3536        { "quest_skill_learn",                  &battle_config.quest_skill_learn,               0,      0,      1,              },
3537        { "quest_skill_reset",                  &battle_config.quest_skill_reset,               0,      0,      1,              },
3538        { "basic_skill_check",                  &battle_config.basic_skill_check,               1,      0,      1,              },
3539        { "guild_emperium_check",               &battle_config.guild_emperium_check,            1,      0,      1,              },
3540        { "guild_exp_limit",                    &battle_config.guild_exp_limit,                 50,     0,      99,             },
3541        { "player_invincible_time",             &battle_config.pc_invincible_time,              5000,   0,      INT_MAX,        },
3542        { "pet_catch_rate",                     &battle_config.pet_catch_rate,                  100,    0,      INT_MAX,        },
3543        { "pet_rename",                         &battle_config.pet_rename,                      0,      0,      1,              },
3544        { "pet_friendly_rate",                  &battle_config.pet_friendly_rate,               100,    0,      INT_MAX,        },
3545        { "pet_hungry_delay_rate",              &battle_config.pet_hungry_delay_rate,           100,    10,     INT_MAX,        },
3546        { "pet_hungry_friendly_decrease",       &battle_config.pet_hungry_friendly_decrease,    5,      0,      INT_MAX,        },
3547        { "pet_status_support",                 &battle_config.pet_status_support,              0,      0,      1,              },
3548        { "pet_attack_support",                 &battle_config.pet_attack_support,              0,      0,      1,              },
3549        { "pet_damage_support",                 &battle_config.pet_damage_support,              0,      0,      1,              },
3550        { "pet_support_min_friendly",           &battle_config.pet_support_min_friendly,        900,    0,      950,            },
3551        { "pet_support_rate",                   &battle_config.pet_support_rate,                100,    0,      INT_MAX,        },
3552        { "pet_attack_exp_to_master",           &battle_config.pet_attack_exp_to_master,        0,      0,      1,              },
3553        { "pet_attack_exp_rate",                &battle_config.pet_attack_exp_rate,             100,    0,      INT_MAX,        },
3554        { "pet_lv_rate",                        &battle_config.pet_lv_rate,                     0,      0,      INT_MAX,        },
3555        { "pet_max_stats",                      &battle_config.pet_max_stats,                   99,     0,      INT_MAX,        },
3556        { "pet_max_atk1",                       &battle_config.pet_max_atk1,                    750,    0,      INT_MAX,        },
3557        { "pet_max_atk2",                       &battle_config.pet_max_atk2,                    1000,   0,      INT_MAX,        },
3558        { "pet_disable_in_gvg",                 &battle_config.pet_no_gvg,                      0,      0,      1,              },
3559        { "skill_min_damage",                   &battle_config.skill_min_damage,                2|4,    0,      1|2|4,          },
3560        { "finger_offensive_type",              &battle_config.finger_offensive_type,           0,      0,      1,              },
3561        { "heal_exp",                           &battle_config.heal_exp,                        0,      0,      INT_MAX,        },
3562        { "resurrection_exp",                   &battle_config.resurrection_exp,                0,      0,      INT_MAX,        },
3563        { "shop_exp",                           &battle_config.shop_exp,                        0,      0,      INT_MAX,        },
3564        { "max_heal_lv",                        &battle_config.max_heal_lv,                     11,     1,      INT_MAX,        },
3565        { "max_heal",                           &battle_config.max_heal,                        9999,   0,      INT_MAX,        },
3566        { "combo_delay_rate",                   &battle_config.combo_delay_rate,                100,    0,      INT_MAX,        },
3567        { "item_check",                         &battle_config.item_check,                      0,      0,      1,              },
3568        { "item_use_interval",                  &battle_config.item_use_interval,               100,    0,      INT_MAX,        },
3569        { "wedding_modifydisplay",              &battle_config.wedding_modifydisplay,           0,      0,      1,              },
3570        { "wedding_ignorepalette",              &battle_config.wedding_ignorepalette,           0,      0,      1,              },
3571        { "xmas_ignorepalette",                 &battle_config.xmas_ignorepalette,              0,      0,      1,              },
3572        { "summer_ignorepalette",               &battle_config.summer_ignorepalette,            0,      0,      1,              },
3573        { "natural_healhp_interval",            &battle_config.natural_healhp_interval,         6000,   NATURAL_HEAL_INTERVAL, INT_MAX, },
3574        { "natural_healsp_interval",            &battle_config.natural_healsp_interval,         8000,   NATURAL_HEAL_INTERVAL, INT_MAX, },
3575        { "natural_heal_skill_interval",        &battle_config.natural_heal_skill_interval,     10000,  NATURAL_HEAL_INTERVAL, INT_MAX, },
3576        { "natural_heal_weight_rate",           &battle_config.natural_heal_weight_rate,        50,     50,     101             },
3577        { "arrow_decrement",                    &battle_config.arrow_decrement,                 1,      0,      2,              },
3578        { "max_aspd",                           &battle_config.max_aspd,                        199,    100,    199,            },
3579        { "max_walk_speed",                     &battle_config.max_walk_speed,                  300,    100,    100*DEFAULT_WALK_SPEED, },
3580        { "max_lv",                             &battle_config.max_lv,                          99,     0,      127,            },
3581        { "aura_lv",                            &battle_config.aura_lv,                         99,     0,      INT_MAX,        },
3582        { "max_hp",                             &battle_config.max_hp,                          32500,  100,    1000000000,     },
3583        { "max_sp",                             &battle_config.max_sp,                          32500,  100,    1000000000,     },
3584        { "max_cart_weight",                    &battle_config.max_cart_weight,                 8000,   100,    1000000,        },
3585        { "max_parameter",                      &battle_config.max_parameter,                   99,     10,     10000,          },
3586        { "max_baby_parameter",                 &battle_config.max_baby_parameter,              80,     10,     10000,          },
3587        { "max_def",                            &battle_config.max_def,                         99,     0,      INT_MAX,        },
3588        { "over_def_bonus",                     &battle_config.over_def_bonus,                  0,      0,      1000,           },
3589        { "skill_log",                          &battle_config.skill_log,                       BL_NUL, BL_NUL, BL_ALL,         },
3590        { "battle_log",                         &battle_config.battle_log,                      0,      0,      1,              },
3591        { "save_log",                           &battle_config.save_log,                        0,      0,      1,              },
3592        { "etc_log",                            &battle_config.etc_log,                         1,      0,      1,              },
3593        { "save_clothcolor",                    &battle_config.save_clothcolor,                 1,      0,      1,              },
3594        { "undead_detect_type",                 &battle_config.undead_detect_type,              0,      0,      2,              },
3595        { "auto_counter_type",                  &battle_config.auto_counter_type,               BL_ALL, BL_NUL, BL_ALL,         },
3596        { "min_hitrate",                        &battle_config.min_hitrate,                     5,      0,      100,            },
3597        { "max_hitrate",                        &battle_config.max_hitrate,                     100,    0,      100,            },
3598        { "agi_penalty_target",                 &battle_config.agi_penalty_target,              BL_PC,  BL_NUL, BL_ALL,         },
3599        { "agi_penalty_type",                   &battle_config.agi_penalty_type,                1,      0,      2,              },
3600        { "agi_penalty_count",                  &battle_config.agi_penalty_count,               3,      2,      INT_MAX,        },
3601        { "agi_penalty_num",                    &battle_config.agi_penalty_num,                 10,     0,      INT_MAX,        },
3602        { "agi_penalty_count_lv",               &battle_config.agi_penalty_count_lv,            ATK_FLEE, 0,    INT_MAX,        },
3603        { "vit_penalty_target",                 &battle_config.vit_penalty_target,              BL_PC,  BL_NUL, BL_ALL,         },
3604        { "vit_penalty_type",                   &battle_config.vit_penalty_type,                1,      0,      2,              },
3605        { "vit_penalty_count",                  &battle_config.vit_penalty_count,               3,      2,      INT_MAX,        },
3606        { "vit_penalty_num",                    &battle_config.vit_penalty_num,                 5,      0,      INT_MAX,        },
3607        { "vit_penalty_count_lv",               &battle_config.vit_penalty_count_lv,            ATK_DEF, 0,     INT_MAX,        },
3608        { "weapon_defense_type",                &battle_config.weapon_defense_type,             0,      0,      INT_MAX,        },
3609        { "magic_defense_type",                 &battle_config.magic_defense_type,              0,      0,      INT_MAX,        },
3610        { "skill_reiteration",                  &battle_config.skill_reiteration,               BL_NUL, BL_NUL, BL_ALL,         },
3611        { "skill_nofootset",                    &battle_config.skill_nofootset,                 BL_PC,  BL_NUL, BL_ALL,         },
3612        { "player_cloak_check_type",            &battle_config.pc_cloak_check_type,             1,      0,      1|2|4,          },
3613        { "monster_cloak_check_type",           &battle_config.monster_cloak_check_type,        4,      0,      1|2|4,          },
3614        { "sense_type",                         &battle_config.estimation_type,                 1|2,    0,      1|2,            },
3615        { "gvg_eliminate_time",                 &battle_config.gvg_eliminate_time,              7000,   0,      INT_MAX,        },
3616        { "gvg_short_attack_damage_rate",       &battle_config.gvg_short_damage_rate,           80,     0,      INT_MAX,        },
3617        { "gvg_long_attack_damage_rate",        &battle_config.gvg_long_damage_rate,            80,     0,      INT_MAX,        },
3618        { "gvg_weapon_attack_damage_rate",      &battle_config.gvg_weapon_damage_rate,          60,     0,      INT_MAX,        },
3619        { "gvg_magic_attack_damage_rate",       &battle_config.gvg_magic_damage_rate,           60,     0,      INT_MAX,        },
3620        { "gvg_misc_attack_damage_rate",        &battle_config.gvg_misc_damage_rate,            60,     0,      INT_MAX,        },
3621        { "gvg_flee_penalty",                   &battle_config.gvg_flee_penalty,                20,     0,      INT_MAX,        },
3622        { "pk_short_attack_damage_rate",        &battle_config.pk_short_damage_rate,            80,     0,      INT_MAX,        },
3623        { "pk_long_attack_damage_rate",         &battle_config.pk_long_damage_rate,             70,     0,      INT_MAX,        },
3624        { "pk_weapon_attack_damage_rate",       &battle_config.pk_weapon_damage_rate,           60,     0,      INT_MAX,        },
3625        { "pk_magic_attack_damage_rate",        &battle_config.pk_magic_damage_rate,            60,     0,      INT_MAX,        },
3626        { "pk_misc_attack_damage_rate",         &battle_config.pk_misc_damage_rate,             60,     0,      INT_MAX,        },
3627        { "mob_changetarget_byskill",           &battle_config.mob_changetarget_byskill,        0,      0,      1,              },
3628        { "attack_direction_change",            &battle_config.attack_direction_change,         BL_ALL, BL_NUL, BL_ALL,         },
3629        { "land_skill_limit",                   &battle_config.land_skill_limit,                BL_ALL, BL_NUL, BL_ALL,         },
3630        { "monster_class_change_full_recover",  &battle_config.monster_class_change_recover,    1,      0,      1,              },
3631        { "produce_item_name_input",            &battle_config.produce_item_name_input,         0x1|0x2, 0,     0x9F,           },
3632        { "display_skill_fail",                 &battle_config.display_skill_fail,              2,      0,      1|2|4|8,        },
3633        { "chat_warpportal",                    &battle_config.chat_warpportal,                 0,      0,      1,              },
3634        { "mob_warp",                           &battle_config.mob_warp,                        0,      0,      1|2|4,          },
3635        { "dead_branch_active",                 &battle_config.dead_branch_active,              1,      0,      1,              },
3636        { "vending_max_value",                  &battle_config.vending_max_value,               10000000, 1,    MAX_ZENY,       },
3637        { "vending_over_max",                   &battle_config.vending_over_max,                1,      0,      1,              },
3638        { "show_steal_in_same_party",           &battle_config.show_steal_in_same_party,        0,      0,      1,              },
3639        { "party_hp_mode",                      &battle_config.party_hp_mode,                   0,      0,      1,              },
3640        { "show_party_share_picker",            &battle_config.party_show_share_picker,         0,      0,      1,              },
3641        { "party_update_interval",              &battle_config.party_update_interval,           1000,   100,    INT_MAX,        },
3642        { "party_item_share_type",              &battle_config.party_share_type,                0,      0,      1|2|3,          },
3643        { "attack_attr_none",                   &battle_config.attack_attr_none,                ~BL_PC, BL_NUL, BL_ALL,         },
3644        { "gx_allhit",                          &battle_config.gx_allhit,                       0,      0,      1,              },
3645        { "gx_disptype",                        &battle_config.gx_disptype,                     1,      0,      1,              },
3646        { "devotion_level_difference",          &battle_config.devotion_level_difference,       10,     0,      INT_MAX,        },
3647        { "player_skill_partner_check",         &battle_config.player_skill_partner_check,      1,      0,      1,              },
3648        { "hide_GM_session",                    &battle_config.hide_GM_session,                 0,      0,      1,              },
3649        { "invite_request_check",               &battle_config.invite_request_check,            1,      0,      1,              },
3650        { "skill_removetrap_type",              &battle_config.skill_removetrap_type,           0,      0,      1,              },
3651        { "disp_experience",                    &battle_config.disp_experience,                 0,      0,      1,              },
3652        { "disp_zeny",                          &battle_config.disp_zeny,                       0,      0,      1,              },
3653        { "castle_defense_rate",                &battle_config.castle_defense_rate,             100,    0,      100,            },
3654        { "gm_cant_drop_min_lv",                &battle_config.gm_cant_drop_min_lv,             1,      0,      100,            },
3655        { "gm_cant_drop_max_lv",                &battle_config.gm_cant_drop_max_lv,             0,      0,      100,            },
3656        { "disp_hpmeter",                       &battle_config.disp_hpmeter,                    0,      0,      100,            },
3657        { "bone_drop",                          &battle_config.bone_drop,                       0,      0,      2,              },
3658        { "buyer_name",                         &battle_config.buyer_name,                      1,      0,      1,              },
3659        { "skill_wall_check",                   &battle_config.skill_wall_check,                1,      0,      1,              },
3660        { "cell_stack_limit",                   &battle_config.cell_stack_limit,                1,      1,      255,            },
3661// eAthena additions
3662        { "item_logarithmic_drops",             &battle_config.logarithmic_drops,               0,      0,      1,              },
3663        { "item_drop_common_min",               &battle_config.item_drop_common_min,            1,      1,      10000,          },
3664        { "item_drop_common_max",               &battle_config.item_drop_common_max,            10000,  1,      10000,          },
3665        { "item_drop_equip_min",                &battle_config.item_drop_equip_min,             1,      1,      10000,          },
3666        { "item_drop_equip_max",                &battle_config.item_drop_equip_max,             10000,  1,      10000,          },
3667        { "item_drop_card_min",                 &battle_config.item_drop_card_min,              1,      1,      10000,          },
3668        { "item_drop_card_max",                 &battle_config.item_drop_card_max,              10000,  1,      10000,          },
3669        { "item_drop_mvp_min",                  &battle_config.item_drop_mvp_min,               1,      1,      10000,          },
3670        { "item_drop_mvp_max",                  &battle_config.item_drop_mvp_max,               10000,  1,      10000,          },
3671        { "item_drop_heal_min",                 &battle_config.item_drop_heal_min,              1,      1,      10000,          },
3672        { "item_drop_heal_max",                 &battle_config.item_drop_heal_max,              10000,  1,      10000,          },
3673        { "item_drop_use_min",                  &battle_config.item_drop_use_min,               1,      1,      10000,          },
3674        { "item_drop_use_max",                  &battle_config.item_drop_use_max,               10000,  1,      10000,          },
3675        { "item_drop_add_min",                  &battle_config.item_drop_adddrop_min,           1,      1,      10000,          },
3676        { "item_drop_add_max",                  &battle_config.item_drop_adddrop_max,           10000,  1,      10000,          },
3677        { "item_drop_treasure_min",             &battle_config.item_drop_treasure_min,          1,      1,      10000,          },
3678        { "item_drop_treasure_max",             &battle_config.item_drop_treasure_max,          10000,  1,      10000,          },
3679        { "item_rate_mvp",                      &battle_config.item_rate_mvp,                   100,    0,      1000000,        },
3680        { "item_rate_common",                   &battle_config.item_rate_common,                100,    0,      1000000,        },
3681        { "item_rate_common_boss",              &battle_config.item_rate_common_boss,           100,    0,      1000000,        },
3682        { "item_rate_equip",                    &battle_config.item_rate_equip,                 100,    0,      1000000,        },
3683        { "item_rate_equip_boss",               &battle_config.item_rate_equip_boss,            100,    0,      1000000,        },
3684        { "item_rate_card",                     &battle_config.item_rate_card,                  100,    0,      1000000,        },
3685        { "item_rate_card_boss",                &battle_config.item_rate_card_boss,             100,    0,      1000000,        },
3686        { "item_rate_heal",                     &battle_config.item_rate_heal,                  100,    0,      1000000,        },
3687        { "item_rate_heal_boss",                &battle_config.item_rate_heal_boss,             100,    0,      1000000,        },
3688        { "item_rate_use",                      &battle_config.item_rate_use,                   100,    0,      1000000,        },
3689        { "item_rate_use_boss",                 &battle_config.item_rate_use_boss,              100,    0,      1000000,        },
3690        { "item_rate_adddrop",                  &battle_config.item_rate_adddrop,               100,    0,      1000000,        },
3691        { "item_rate_treasure",                 &battle_config.item_rate_treasure,              100,    0,      1000000,        },
3692        { "prevent_logout",                     &battle_config.prevent_logout,                  10000,  0,      60000,          },
3693        { "alchemist_summon_reward",            &battle_config.alchemist_summon_reward,         1,      0,      2,              },
3694        { "drops_by_luk",                       &battle_config.drops_by_luk,                    0,      0,      INT_MAX,        },
3695        { "drops_by_luk2",                      &battle_config.drops_by_luk2,                   0,      0,      INT_MAX,        },
3696        { "equip_natural_break_rate",           &battle_config.equip_natural_break_rate,        0,      0,      INT_MAX,        },
3697        { "equip_self_break_rate",              &battle_config.equip_self_break_rate,           100,    0,      INT_MAX,        },
3698        { "equip_skill_break_rate",             &battle_config.equip_skill_break_rate,          100,    0,      INT_MAX,        },
3699        { "pk_mode",                            &battle_config.pk_mode,                         0,      0,      1,              },
3700        { "pk_level_range",                     &battle_config.pk_level_range,                  0,      0,      INT_MAX,        },
3701        { "manner_system",                      &battle_config.manner_system,                   0xFFF,  0,      0xFFF,          },
3702        { "pet_equip_required",                 &battle_config.pet_equip_required,              0,      0,      1,              },
3703        { "multi_level_up",                     &battle_config.multi_level_up,                  0,      0,      1,              },
3704        { "max_exp_gain_rate",                  &battle_config.max_exp_gain_rate,               0,      0,      INT_MAX,        },
3705        { "backstab_bow_penalty",               &battle_config.backstab_bow_penalty,            0,      0,      1,              },
3706        { "night_at_start",                     &battle_config.night_at_start,                  0,      0,      1,              },
3707        { "show_mob_info",                      &battle_config.show_mob_info,                   0,      0,      1|2|4,          },
3708        { "ban_hack_trade",                     &battle_config.ban_hack_trade,                  0,      0,      INT_MAX,        },
3709        { "hack_info_GM_level",                 &battle_config.hack_info_GM_level,              60,     0,      100,            },
3710        { "any_warp_GM_min_level",              &battle_config.any_warp_GM_min_level,           20,     0,      100,            },
3711        { "who_display_aid",                    &battle_config.who_display_aid,                 40,     0,      100,            },
3712        { "packet_ver_flag",                    &battle_config.packet_ver_flag,                 0xFFFF, 0x0000, 0xFFFF,         },
3713        { "min_hair_style",                     &battle_config.min_hair_style,                  0,      0,      INT_MAX,        },
3714        { "max_hair_style",                     &battle_config.max_hair_style,                  23,     0,      INT_MAX,        },
3715        { "min_hair_color",                     &battle_config.min_hair_color,                  0,      0,      INT_MAX,        },
3716        { "max_hair_color",                     &battle_config.max_hair_color,                  9,      0,      INT_MAX,        },
3717        { "min_cloth_color",                    &battle_config.min_cloth_color,                 0,      0,      INT_MAX,        },
3718        { "max_cloth_color",                    &battle_config.max_cloth_color,                 4,      0,      INT_MAX,        },
3719        { "pet_hair_style",                     &battle_config.pet_hair_style,                  100,    0,      INT_MAX,        },
3720        { "castrate_dex_scale",                 &battle_config.castrate_dex_scale,              150,    1,      INT_MAX,        },
3721        { "area_size",                          &battle_config.area_size,                       14,     0,      INT_MAX,        },
3722        { "zeny_from_mobs",                     &battle_config.zeny_from_mobs,                  0,      0,      1,              },
3723        { "mobs_level_up",                      &battle_config.mobs_level_up,                   0,      0,      1,              },
3724        { "mobs_level_up_exp_rate",             &battle_config.mobs_level_up_exp_rate,          1,      1,      INT_MAX,        },
3725        { "pk_min_level",                       &battle_config.pk_min_level,                    55,     1,      INT_MAX,        },
3726        { "skill_steal_max_tries",              &battle_config.skill_steal_max_tries,           0,      0,      UCHAR_MAX,      },
3727        { "motd_type",                          &battle_config.motd_type,                       0,      0,      1,              },
3728        { "finding_ore_rate",                   &battle_config.finding_ore_rate,                100,    0,      INT_MAX,        },
3729        { "exp_calc_type",                      &battle_config.exp_calc_type,                   0,      0,      1,              },
3730        { "exp_bonus_attacker",                 &battle_config.exp_bonus_attacker,              25,     0,      INT_MAX,        },
3731        { "exp_bonus_max_attacker",             &battle_config.exp_bonus_max_attacker,          12,     2,      INT_MAX,        },
3732        { "min_skill_delay_limit",              &battle_config.min_skill_delay_limit,           100,    10,     INT_MAX,        },
3733        { "default_walk_delay",                 &battle_config.default_walk_delay,              300,    0,      INT_MAX,        },
3734        { "no_skill_delay",                     &battle_config.no_skill_delay,                  BL_MOB, BL_NUL, BL_ALL,         },
3735        { "attack_walk_delay",                  &battle_config.attack_walk_delay,               BL_ALL, BL_NUL, BL_ALL,         },
3736        { "require_glory_guild",                &battle_config.require_glory_guild,             0,      0,      1,              },
3737        { "idle_no_share",                      &battle_config.idle_no_share,                   0,      0,      INT_MAX,        },
3738        { "party_even_share_bonus",             &battle_config.party_even_share_bonus,          0,      0,      INT_MAX,        }, 
3739        { "delay_battle_damage",                &battle_config.delay_battle_damage,             1,      0,      1,              },
3740        { "hide_woe_damage",                    &battle_config.hide_woe_damage,                 0,      0,      1,              },
3741        { "display_version",                    &battle_config.display_version,                 1,      0,      1,              },
3742        { "display_hallucination",              &battle_config.display_hallucination,           1,      0,      1,              },
3743        { "use_statpoint_table",                &battle_config.use_statpoint_table,             1,      0,      1,              },
3744        { "ignore_items_gender",                &battle_config.ignore_items_gender,             1,      0,      1,              },
3745        { "copyskill_restrict",                 &battle_config.copyskill_restrict,              2,      0,      2,              },
3746        { "berserk_cancels_buffs",              &battle_config.berserk_cancels_buffs,           0,      0,      1,              },
3747        { "debuff_on_logout",                   &battle_config.debuff_on_logout,                1|2,    0,      1|2,            },
3748        { "monster_ai",                         &battle_config.mob_ai,                          0x000,  0x000,  0x77F,          },
3749        { "hom_setting",                        &battle_config.hom_setting,                     0xFFFF, 0x0000, 0xFFFF,         },
3750        { "dynamic_mobs",                       &battle_config.dynamic_mobs,                    1,      0,      1,              },
3751        { "mob_remove_damaged",                 &battle_config.mob_remove_damaged,              1,      0,      1,              },
3752        { "show_hp_sp_drain",                   &battle_config.show_hp_sp_drain,                0,      0,      1,              },
3753        { "show_hp_sp_gain",                    &battle_config.show_hp_sp_gain,                 1,      0,      1,              },
3754        { "mob_npc_event_type",                 &battle_config.mob_npc_event_type,              1,      0,      1,              },
3755        { "mob_clear_delay",                    &battle_config.mob_clear_delay,                 0,      0,      INT_MAX,        },
3756        { "character_size",                     &battle_config.character_size,                  1|2,    0,      1|2,            },
3757        { "mob_max_skilllvl",                   &battle_config.mob_max_skilllvl,                MAX_SKILL_LEVEL, 1, MAX_SKILL_LEVEL, },
3758        { "retaliate_to_master",                &battle_config.retaliate_to_master,             1,      0,      1,              },
3759        { "rare_drop_announce",                 &battle_config.rare_drop_announce,              0,      0,      10000,          },
3760        { "title_lvl1",                         &battle_config.title_lvl1,                      1,      0,      100,            },
3761        { "title_lvl2",                         &battle_config.title_lvl2,                      10,     0,      100,            },
3762        { "title_lvl3",                         &battle_config.title_lvl3,                      20,     0,      100,            },
3763        { "title_lvl4",                         &battle_config.title_lvl4,                      40,     0,      100,            },
3764        { "title_lvl5",                         &battle_config.title_lvl5,                      50,     0,      100,            },
3765        { "title_lvl6",                         &battle_config.title_lvl6,                      60,     0,      100,            },
3766        { "title_lvl7",                         &battle_config.title_lvl7,                      80,     0,      100,            },
3767        { "title_lvl8",                         &battle_config.title_lvl8,                      99,     0,      100,            },
3768        { "duel_allow_pvp",                     &battle_config.duel_allow_pvp,                  0,      0,      1,              },
3769        { "duel_allow_gvg",                     &battle_config.duel_allow_gvg,                  0,      0,      1,              },
3770        { "duel_allow_teleport",                &battle_config.duel_allow_teleport,             0,      0,      1,              },
3771        { "duel_autoleave_when_die",            &battle_config.duel_autoleave_when_die,         1,      0,      1,              },
3772        { "duel_time_interval",                 &battle_config.duel_time_interval,              60,     0,      INT_MAX,        },
3773        { "duel_only_on_same_map",              &battle_config.duel_only_on_same_map,           0,      0,      1,              },
3774        { "skip_teleport_lv1_menu",             &battle_config.skip_teleport_lv1_menu,          0,      0,      1,              },
3775        { "allow_skill_without_day",            &battle_config.allow_skill_without_day,         0,      0,      1,              },
3776        { "allow_es_magic_player",              &battle_config.allow_es_magic_pc,               0,      0,      1,              },
3777        { "skill_caster_check",                 &battle_config.skill_caster_check,              1,      0,      1,              },
3778        { "status_cast_cancel",                 &battle_config.sc_castcancel,                   BL_NUL, BL_NUL, BL_ALL,         },
3779        { "pc_status_def_rate",                 &battle_config.pc_sc_def_rate,                  100,    0,      INT_MAX,        },
3780        { "mob_status_def_rate",                &battle_config.mob_sc_def_rate,                 100,    0,      INT_MAX,        },
3781        { "pc_luk_status_def",                  &battle_config.pc_luk_sc_def,                   300,    1,      INT_MAX,        },
3782        { "mob_luk_status_def",                 &battle_config.mob_luk_sc_def,                  300,    1,      INT_MAX,        },
3783        { "pc_max_status_def",                  &battle_config.pc_max_sc_def,                   100,    0,      INT_MAX,        },
3784        { "mob_max_status_def",                 &battle_config.mob_max_sc_def,                  100,    0,      INT_MAX,        },
3785        { "sg_miracle_skill_ratio",             &battle_config.sg_miracle_skill_ratio,          1,      0,      10000,          },
3786        { "sg_angel_skill_ratio",               &battle_config.sg_angel_skill_ratio,            10,     0,      10000,          },
3787        { "autospell_stacking",                 &battle_config.autospell_stacking,              0,      0,      1,              },
3788        { "override_mob_names",                 &battle_config.override_mob_names,              0,      0,      2,              },
3789        { "min_chat_delay",                     &battle_config.min_chat_delay,                  0,      0,      INT_MAX,        },
3790        { "friend_auto_add",                    &battle_config.friend_auto_add,                 1,      0,      1,              },
3791        { "hom_rename",                         &battle_config.hom_rename,                      0,      0,      1,              },
3792        { "homunculus_show_growth",             &battle_config.homunculus_show_growth,          0,      0,      1,              },
3793        { "homunculus_friendly_rate",           &battle_config.homunculus_friendly_rate,        100,    0,      INT_MAX,        },
3794        { "vending_tax",                        &battle_config.vending_tax,                     0,      0,      10000,          },
3795        { "day_duration",                       &battle_config.day_duration,                    0,      0,      INT_MAX,        },
3796        { "night_duration",                     &battle_config.night_duration,                  0,      0,      INT_MAX,        },
3797        { "mob_remove_delay",                   &battle_config.mob_remove_delay,                60000,  1000,   INT_MAX,        },
3798        { "mob_active_time",                    &battle_config.mob_active_time,                 0,      0,      INT_MAX,        },
3799        { "boss_active_time",                   &battle_config.boss_active_time,                0,      0,      INT_MAX,        },
3800        { "sg_miracle_skill_duration",          &battle_config.sg_miracle_skill_duration,       3600000, 0,     INT_MAX,        },
3801        { "hvan_explosion_intimate",            &battle_config.hvan_explosion_intimate,         45000,  0,      100000,         },
3802        { "quest_exp_rate",                     &battle_config.quest_exp_rate,                  100,    0,      INT_MAX,        },
3803        { "at_mapflag",                         &battle_config.autotrade_mapflag,               0,      0,      1,              },
3804        { "at_timeout",                         &battle_config.at_timeout,                      0,      0,      INT_MAX,        },
3805        { "homunculus_autoloot",                &battle_config.homunculus_autoloot,             0,      0,      1,              },
3806        { "idle_no_autoloot",                   &battle_config.idle_no_autoloot,                0,      0,      INT_MAX,        },
3807        { "max_guild_alliance",                 &battle_config.max_guild_alliance,              3,      1,      3,              },
3808        { "ksprotection",                       &battle_config.ksprotection,                    5000,   0,      INT_MAX,        },
3809        { "auction_feeperhour",                 &battle_config.auction_feeperhour,              12000,  0,      INT_MAX,        },
3810        { "auction_maximumprice",               &battle_config.auction_maximumprice,            500000000, 0,   MAX_ZENY,       },
3811//battle conf declarations, does this mean we add new lines to battle.conf?
3812        //Vanaheim battle settings [Brainstorm]
3813        { "necro_retaliation",                  &battle_config.necro_retaliation,               1,      0,      1,              },
3814        { "disp_summon_stats",                  &battle_config.disp_summon_stats,               0,      0,      1,              },
3815        { "gm_viewequip_min_lv",                &battle_config.gm_viewequip_min_lv,             0,      0,      99,             },
3816        { "homunculus_auto_vapor",              &battle_config.homunculus_auto_vapor,           0,      0,      1,              },
3817};
3818
3819
3820int battle_set_value(const char* w1, const char* w2)
3821{
3822        int val = config_switch(w2);
3823
3824        int i;
3825        ARR_FIND(0, ARRAYLENGTH(battle_data), i, strcmpi(w1, battle_data[i].str) == 0);
3826        if (i == ARRAYLENGTH(battle_data))
3827                return 0; // not found
3828
3829        if (val < battle_data[i].min || val > battle_data[i].max)
3830        {
3831                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);
3832                val = battle_data[i].defval;
3833        }
3834
3835        *battle_data[i].val = val;
3836        return 1;
3837}
3838
3839int battle_get_value(const char* w1)
3840{
3841        int i;
3842        ARR_FIND(0, ARRAYLENGTH(battle_data), i, strcmpi(w1, battle_data[i].str) == 0);
3843        if (i == ARRAYLENGTH(battle_data))
3844                return 0; // not found
3845        else
3846                return *battle_data[i].val;
3847}
3848
3849void battle_set_defaults()
3850{
3851        int i;
3852        for (i = 0; i < ARRAYLENGTH(battle_data); i++)
3853                *battle_data[i].val = battle_data[i].defval;
3854}
3855
3856void battle_adjust_conf()
3857{
3858        battle_config.monster_max_aspd = 2000 - battle_config.monster_max_aspd*10;
3859        battle_config.max_aspd = 2000 - battle_config.max_aspd*10;
3860        battle_config.max_walk_speed = 100*DEFAULT_WALK_SPEED/battle_config.max_walk_speed;     
3861        battle_config.max_cart_weight *= 10;
3862       
3863        if(battle_config.max_def > 100 && !battle_config.weapon_defense_type)    // added by [Skotlex]
3864                battle_config.max_def = 100;
3865
3866        if(battle_config.min_hitrate > battle_config.max_hitrate)
3867                battle_config.min_hitrate = battle_config.max_hitrate;
3868               
3869        if(battle_config.pet_max_atk1 > battle_config.pet_max_atk2)     //Skotlex
3870                battle_config.pet_max_atk1 = battle_config.pet_max_atk2;
3871       
3872        if (battle_config.day_duration && battle_config.day_duration < 60000) // added by [Yor]
3873                battle_config.day_duration = 60000;
3874        if (battle_config.night_duration && battle_config.night_duration < 60000) // added by [Yor]
3875                battle_config.night_duration = 60000;
3876       
3877#ifndef CELL_NOSTACK
3878        if (battle_config.cell_stack_limit != 1)
3879                ShowWarning("Battle setting 'cell_stack_limit' takes no effect as this server was compiled without Cell Stack Limit support.\n");
3880#endif
3881}
3882
3883int battle_config_read(const char* cfgName)
3884{
3885        char line[1024], w1[1024], w2[1024];
3886        FILE* fp;
3887        static int count = 0;
3888
3889        if (count == 0)
3890                battle_set_defaults();
3891
3892        count++;
3893
3894        fp = fopen(cfgName,"r");
3895        if (fp == NULL)
3896                ShowError("File not found: %s\n", cfgName);
3897        else
3898        {
3899                while(fgets(line, sizeof(line), fp))
3900                {
3901                        if (line[0] == '/' && line[1] == '/')
3902                                continue;
3903                        if (sscanf(line, "%1023[^:]:%1023s", w1, w2) != 2)
3904                                continue;
3905                        if (strcmpi(w1, "import") == 0)
3906                                battle_config_read(w2);
3907                        else
3908                        if (battle_set_value(w1, w2) == 0)
3909                                ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName);
3910                }
3911
3912                fclose(fp);
3913        }
3914
3915        count--;
3916
3917        if (count == 0)
3918                battle_adjust_conf();
3919
3920        return 0;
3921}
3922
3923void do_init_battle(void)
3924{
3925        delay_damage_ers = ers_new(sizeof(struct delay_damage));
3926        add_timer_func_list(battle_delay_damage_sub, "battle_delay_damage_sub");
3927}
3928
3929void do_final_battle(void)
3930{
3931        ers_destroy(delay_damage_ers);
3932}
Note: See TracBrowser for help on using the browser.