summaryrefslogblamecommitdiff
path: root/src/map/battle.c
blob: 579ea5535aa10ead11743dadf4e2672f34aa658b (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315











                                                          


                   
                
                

                  
                             
                    




                     
                               



                                            

                     

                                            
                                                    
 
                
 


                             


                                            

                                           

                                            

                                                                        
 






                                                                          
 
 
                                            

                          

                                            
                                            
 






                                                                 
 
 
                                            

                         

                                            
                                          
 






                                                                 
 
 
                                            

                           

                                            
                                         
 






                                                                   
 
 
                                            

                         

                                            
                                            
 






                                                                 
 
 
                                            

                       

                                            
                                         
 






                                                                 
 
 
                                            

                        

                                            
                                             
 

































                                                                            
 
 
                                            

                        

                                            
                                          
 





























                                                                                     
 
 
                                            

                        


                                            
                                          
 





























                                                                                                                                                                           
 
 
                                            

                        

                                            
                                          
 



















                                                                                     
 
 
                                            

                        

                                            
                                          
 




























                                                                                     
 
 
                                            

                        

                                            
                                          
 

































                                                                                     
 
 
                                            

                        

                                            
                                          
 





















                                                                                           


                                            

                         

                                            
                                           
 





























                                                                                       
 
 
                                            

                        

                                            
                                          
 





























                                                                                              
 
 
                                            

                             

                                            
                                            
 



























                                                                              
 
 
                                            

                                 

                                            
                                               
 




























                                                                                    
 
 
                                            

                    

                                            
                                              
 

























                                                                                                    
 
 
                                            

                        

                                            
                                          
 





















                                                                                              
 
 
                                            

                            

                                            
                                           
 










                                                                            
 
 
                                            

                         

                                            
                                           
 
































                                                                              
 
 
                                            

                             

                                            
                                            
 




                                                        
 
 
                                            

                          

                                            
                                            
 
















                                                                             
 
 
                                            

                          

                                            
                                            
 















                                                                             
 
 
                                            

                        

                                            
                                          
 































































                                                                              
 
 
                                            

                         

                                            
                                           
 


































                                                                         
 
 
                                            

                         

                                            
                                           
 
























                                                                            
 
 
                                            

                          

                                            
                                            
 



















                                                                      
 
 
                                            


                                    

                                            
                                            
 

















































                                                                              
 
 
                                            

                                           

                                            
                                             
 





































































                                                                                                                                                                                                                                       
 

                                              
 


























































                                                                                                                                                                                                                                       
 

                                              
 

























                                                                             
 

                                              
 




















                                                                                     
 

                                                     
 

























                                                                               
 

                                                      
 
























                                                                                   
 

                                               
 













                                                                 
 

                                               
 








                                                                 
 

                                           
 






                                                                 
 

                                           
 






                                                                 
 

                                           
 




                                                              

 
                                           
 












                                                                             

 

                                                          
 













                                       
                

                     

 
                       
                                                                
 





                                                                 
 

                                                  
 





                                                                 
 

                                              
 







                                                                 
 

                                              
 







                                                                 
 

                                              
 







                                                                 
 

                                                
 







                                                                 



                                                                     
                 




                                    
  
                                                                          
 




                                                                            
 
 
















                                                                                

 
                 

                                                                    
 












































































                                                                                   
 
                                           
 





                                                                              
 


















                                                                              

 
           
                                             
 





                                                              
 
 
           
                                                        
 





                                                                      

 
                                            
                     

                                            
                                                            
 












                                                                                      

 
                                            
                   

                                            


                                                                          
 











































































































































                                                                             

                                                                            






























































































                                                                                                               


                                            
               

                                            

                                                                              
 



















































































































































                                                                          

 



                                                                              
 






























































































































































































                                                                                                                                                                 
 


























































































































































































































                                                                                                  
 

























































































































































































































                                                                                                                                                         

 













                                                                     
 

                                                                            
                     

                                                                           



                                                                             
 




















































                                                                           

                              





























                                                                                                                                                                          
                              
 























                                                                                                                
         

















































































































































                                                                                                  

         



















                                                                                                                                                        






























                                                                                                          

















                                                                 
 



























































































































































































































































































































































































































































































































































































































































































































































































                                                                                                                                                         
 
                                  
 
                                      

























































                                                                                                                                              
                                      
 
                                            





















                                                                                                      
                                            

                                                                

                                          
 
                                      
























                                                                                                                   
                                      
 
                                                          























                                                                                                      
                                                          
 



























































































































































                                                                                  

                                                                      


















                                             


                                            
                   

                                            



                                                                     
 



































































                                                                                                                    


                                            
                   

                                            






























                                                                              


                                                                     
















































































                                                                                    
  
                                                                                                                                                    



                                                     
































































































                                                                                           

         












































































































                                                                                                   


                                            
                     

                                            


                                                                             
 
















































































































































                                                                                                   

 
 
                                            
                         

                                            



                                                                           
 




















                                                                              
 
 
                                            
                     

                                            

                                                                            
 








































































                                                                           
 





                                                                              
 


























                                                                           
                 















                                                                          
 


                                                                              
 

















































                                                                                                          
 












                                                                              
 
































                                                                             
                 

























































































































































































                                                                                       
                 












                                                                          
 



























                                                                                                                

 
                                               
 















                                                   


                                            





                                                                                        

                                            

                                                                           
 





























































































                                                                                                                                                          
 

                                                       
 


                                                               
 


                                                                            
 


                                                        
 

                                   
 

                                       
 






                                                                                 
 

                                                                                                       



                                                                                                          



















































                                                                                 
 
                                                                                     
 
 
                                            
           

                                            

                                                                      

 


                             
 

                         
 


                                   
 

                                             
 

                                                   
 

                                                 
 

                                                                                 
 






                                                                            
 



                                                                         



                                                                       
                                              

                                            









                                                                   
 
 
                                            
                         

                                            
                                            
 
































































































































































































































































































































































































































































































































































































































































































































































































































































































                                                                                                   
 
// $Id: battle.c,v 1.10 2004/09/29 21:08:17 Akitasha Exp $
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

#include "battle.h"

#include "timer.h"
#include "nullpo.h"
#include "malloc.h"

#include "clif.h"
#include "guild.h"
#include "itemdb.h"
#include "map.h"
#include "mob.h"
#include "pc.h"
#include "skill.h"
#include "../common/socket.h"
#include "mt_rand.h"

#ifdef MEMWATCH
#include "memwatch.h"
#endif

int  attr_fix_table[4][10][10];

struct Battle_Config battle_config;

/*==========================================
 * ��_�Ԃ̋�����Ԃ�
 * �߂�͐�����0�ȏ�
 *------------------------------------------
 */
static int distance (int x0, int y0, int x1, int y1)
{
    int  dx, dy;

    dx = abs (x0 - x1);
    dy = abs (y0 - y1);
    return dx > dy ? dx : dy;
}

/*==========================================
 * ���������b�N���Ă���Ώۂ̐���Ԃ�(�ėp)
 * �߂�͐�����0�ȏ�
 *------------------------------------------
 */
int battle_counttargeted (struct block_list *bl, struct block_list *src,
                          int target_lv)
{
    nullpo_retr (0, bl);
    if (bl->type == BL_PC)
        return pc_counttargeted ((struct map_session_data *) bl, src,
                                 target_lv);
    else if (bl->type == BL_MOB)
        return mob_counttargeted ((struct mob_data *) bl, src, target_lv);
    return 0;
}

/*==========================================
 * �Ώۂ�Class��Ԃ�(�ėp)
 * �߂�͐�����0�ȏ�
 *------------------------------------------
 */
int battle_get_class (struct block_list *bl)
{
    nullpo_retr (0, bl);
    if (bl->type == BL_MOB && (struct mob_data *) bl)
        return ((struct mob_data *) bl)->class;
    else if (bl->type == BL_PC && (struct map_session_data *) bl)
        return ((struct map_session_data *) bl)->status.class;
    else
        return 0;
}

/*==========================================
 * �Ώۂ̕�����Ԃ�(�ėp)
 * �߂�͐�����0�ȏ�
 *------------------------------------------
 */
int battle_get_dir (struct block_list *bl)
{
    nullpo_retr (0, bl);
    if (bl->type == BL_MOB && (struct mob_data *) bl)
        return ((struct mob_data *) bl)->dir;
    else if (bl->type == BL_PC && (struct map_session_data *) bl)
        return ((struct map_session_data *) bl)->dir;
    else
        return 0;
}

/*==========================================
 * �Ώۂ̃��x����Ԃ�(�ėp)
 * �߂�͐�����0�ȏ�
 *------------------------------------------
 */
int battle_get_lv (struct block_list *bl)
{
    nullpo_retr (0, bl);
    if (bl->type == BL_MOB && (struct mob_data *) bl)
        return ((struct mob_data *) bl)->stats[MOB_LV];
    else if (bl->type == BL_PC && (struct map_session_data *) bl)
        return ((struct map_session_data *) bl)->status.base_level;
    else
        return 0;
}

/*==========================================
 * �Ώۂ̎˒���Ԃ�(�ėp)
 * �߂�͐�����0�ȏ�
 *------------------------------------------
 */
int battle_get_range (struct block_list *bl)
{
    nullpo_retr (0, bl);
    if (bl->type == BL_MOB && (struct mob_data *) bl)
        return mob_db[((struct mob_data *) bl)->class].range;
    else if (bl->type == BL_PC && (struct map_session_data *) bl)
        return ((struct map_session_data *) bl)->attackrange;
    else
        return 0;
}

/*==========================================
 * �Ώۂ�HP��Ԃ�(�ėp)
 * �߂�͐�����0�ȏ�
 *------------------------------------------
 */
int battle_get_hp (struct block_list *bl)
{
    nullpo_retr (1, bl);
    if (bl->type == BL_MOB && (struct mob_data *) bl)
        return ((struct mob_data *) bl)->hp;
    else if (bl->type == BL_PC && (struct map_session_data *) bl)
        return ((struct map_session_data *) bl)->status.hp;
    else
        return 1;
}

/*==========================================
 * �Ώۂ�MHP��Ԃ�(�ėp)
 * �߂�͐�����0�ȏ�
 *------------------------------------------
 */
int battle_get_max_hp (struct block_list *bl)
{
    nullpo_retr (1, bl);
    if (bl->type == BL_PC && ((struct map_session_data *) bl))
        return ((struct map_session_data *) bl)->status.max_hp;
    else
    {
        struct status_change *sc_data = battle_get_sc_data (bl);
        int  max_hp = 1;
        if (bl->type == BL_MOB && ((struct mob_data *) bl))
        {
            max_hp = ((struct mob_data *) bl)->stats[MOB_MAX_HP];
            if (mob_db[((struct mob_data *) bl)->class].mexp > 0)
            {
                if (battle_config.mvp_hp_rate != 100)
                    max_hp = (max_hp * battle_config.mvp_hp_rate) / 100;
            }
            else
            {
                if (battle_config.monster_hp_rate != 100)
                    max_hp = (max_hp * battle_config.monster_hp_rate) / 100;
            }
        }
        if (sc_data)
        {
            if (sc_data[SC_APPLEIDUN].timer != -1)
                max_hp +=
                    ((5 + sc_data[SC_APPLEIDUN].val1 * 2 +
                      ((sc_data[SC_APPLEIDUN].val2 + 1) >> 1) +
                      sc_data[SC_APPLEIDUN].val3 / 10) * max_hp) / 100;
        }
        if (max_hp < 1)
            max_hp = 1;
        return max_hp;
    }
    return 1;
}

/*==========================================
 * �Ώۂ�Str��Ԃ�(�ėp)
 * �߂�͐�����0�ȏ�
 *------------------------------------------
 */
int battle_get_str (struct block_list *bl)
{
    int  str = 0;
    struct status_change *sc_data;

    nullpo_retr (0, bl);
    sc_data = battle_get_sc_data (bl);
    if (bl->type == BL_MOB && ((struct mob_data *) bl))
        str = ((struct mob_data *) bl)->stats[MOB_STR];
    else if (bl->type == BL_PC && ((struct map_session_data *) bl))
        return ((struct map_session_data *) bl)->paramc[0];

    if (sc_data)
    {
        if (sc_data[SC_LOUD].timer != -1 && sc_data[SC_QUAGMIRE].timer == -1
            && bl->type != BL_PC)
            str += 4;
        if (sc_data[SC_BLESSING].timer != -1 && bl->type != BL_PC)
        {                       // �u���b�V���O
            int  race = battle_get_race (bl);
            if (battle_check_undead (race, battle_get_elem_type (bl))
                || race == 6)
                str >>= 1;      // �� ��/�s��
            else
                str += sc_data[SC_BLESSING].val1;   // ���̑�
        }
        if (sc_data[SC_TRUESIGHT].timer != -1 && bl->type != BL_PC) // �g�D���[�T�C�g
            str += 5;
    }
    if (str < 0)
        str = 0;
    return str;
}

/*==========================================
 * �Ώۂ�Agi��Ԃ�(�ėp)
 * �߂�͐�����0�ȏ�
 *------------------------------------------
 */

int battle_get_agi (struct block_list *bl)
{
    int  agi = 0;
    struct status_change *sc_data;

    nullpo_retr (0, bl);
    sc_data = battle_get_sc_data (bl);
    if (bl->type == BL_MOB && (struct mob_data *) bl)
        agi = ((struct mob_data *) bl)->stats[MOB_AGI];
    else if (bl->type == BL_PC && (struct map_session_data *) bl)
        agi = ((struct map_session_data *) bl)->paramc[1];

    if (sc_data)
    {
        if (sc_data[SC_INCREASEAGI].timer != -1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1 && bl->type != BL_PC)   // ���x����(PC��pc.c��)
            agi += 2 + sc_data[SC_INCREASEAGI].val1;

        if (sc_data[SC_CONCENTRATE].timer != -1
            && sc_data[SC_QUAGMIRE].timer == -1 && bl->type != BL_PC)
            agi += agi * (2 + sc_data[SC_CONCENTRATE].val1) / 100;

        if (sc_data[SC_DECREASEAGI].timer != -1)    // ���x����
            agi -= 2 + sc_data[SC_DECREASEAGI].val1;

        if (sc_data[SC_QUAGMIRE].timer != -1)   // �N�@�O�}�C�A
            agi >>= 1;
        if (sc_data[SC_TRUESIGHT].timer != -1 && bl->type != BL_PC) // �g�D���[�T�C�g
            agi += 5;
    }
    if (agi < 0)
        agi = 0;
    return agi;
}

/*==========================================
 * �Ώۂ�Vit��Ԃ�(�ėp)
 * �߂�͐�����0�ȏ�
 *------------------------------------------
 */
int battle_get_vit (struct block_list *bl)
{
    int  vit = 0;
    struct status_change *sc_data;

    nullpo_retr (0, bl);
    sc_data = battle_get_sc_data (bl);
    if (bl->type == BL_MOB && (struct mob_data *) bl)
        vit = ((struct mob_data *) bl)->stats[MOB_VIT];
    else if (bl->type == BL_PC && (struct map_session_data *) bl)
        vit = ((struct map_session_data *) bl)->paramc[2];
    if (sc_data)
    {
        if (sc_data[SC_STRIPARMOR].timer != -1 && bl->type != BL_PC)
            vit = vit * 60 / 100;
        if (sc_data[SC_TRUESIGHT].timer != -1 && bl->type != BL_PC) // �g�D���[�T�C�g
            vit += 5;
    }

    if (vit < 0)
        vit = 0;
    return vit;
}

/*==========================================
 * �Ώۂ�Int��Ԃ�(�ėp)
 * �߂�͐�����0�ȏ�
 *------------------------------------------
 */
int battle_get_int (struct block_list *bl)
{
    int  int_ = 0;
    struct status_change *sc_data;

    nullpo_retr (0, bl);
    sc_data = battle_get_sc_data (bl);
    if (bl->type == BL_MOB && (struct mob_data *) bl)
        int_ = ((struct mob_data *) bl)->stats[MOB_INT];
    else if (bl->type == BL_PC && (struct map_session_data *) bl)
        int_ = ((struct map_session_data *) bl)->paramc[3];

    if (sc_data)
    {
        if (sc_data[SC_BLESSING].timer != -1 && bl->type != BL_PC)
        {                       // �u���b�V���O
            int  race = battle_get_race (bl);
            if (battle_check_undead (race, battle_get_elem_type (bl))
                || race == 6)
                int_ >>= 1;     // �� ��/�s��
            else
                int_ += sc_data[SC_BLESSING].val1;  // ���̑�
        }
        if (sc_data[SC_STRIPHELM].timer != -1 && bl->type != BL_PC)
            int_ = int_ * 60 / 100;
        if (sc_data[SC_TRUESIGHT].timer != -1 && bl->type != BL_PC) // �g�D���[�T�C�g
            int_ += 5;
    }
    if (int_ < 0)
        int_ = 0;
    return int_;
}

/*==========================================
 * �Ώۂ�Dex��Ԃ�(�ėp)
 * �߂�͐�����0�ȏ�
 *------------------------------------------
 */
int battle_get_dex (struct block_list *bl)
{
    int  dex = 0;
    struct status_change *sc_data;

    nullpo_retr (0, bl);
    sc_data = battle_get_sc_data (bl);
    if (bl->type == BL_MOB && (struct mob_data *) bl)
        dex = ((struct mob_data *) bl)->stats[MOB_DEX];
    else if (bl->type == BL_PC && (struct map_session_data *) bl)
        dex = ((struct map_session_data *) bl)->paramc[4];

    if (sc_data)
    {
        if (sc_data[SC_CONCENTRATE].timer != -1
            && sc_data[SC_QUAGMIRE].timer == -1 && bl->type != BL_PC)
            dex += dex * (2 + sc_data[SC_CONCENTRATE].val1) / 100;

        if (sc_data[SC_BLESSING].timer != -1 && bl->type != BL_PC)
        {                       // �u���b�V���O
            int  race = battle_get_race (bl);
            if (battle_check_undead (race, battle_get_elem_type (bl))
                || race == 6)
                dex >>= 1;      // �� ��/�s��
            else
                dex += sc_data[SC_BLESSING].val1;   // ���̑�
        }

        if (sc_data[SC_QUAGMIRE].timer != -1)   // �N�@�O�}�C�A
            dex >>= 1;
        if (sc_data[SC_TRUESIGHT].timer != -1 && bl->type != BL_PC) // �g�D���[�T�C�g
            dex += 5;
    }
    if (dex < 0)
        dex = 0;
    return dex;
}

/*==========================================
 * �Ώۂ�Luk��Ԃ�(�ėp)
 * �߂�͐�����0�ȏ�
 *------------------------------------------
 */
int battle_get_luk (struct block_list *bl)
{
    int  luk = 0;
    struct status_change *sc_data;

    nullpo_retr (0, bl);
    sc_data = battle_get_sc_data (bl);
    if (bl->type == BL_MOB && (struct mob_data *) bl)
        luk = ((struct mob_data *) bl)->stats[MOB_LUK];
    else if (bl->type == BL_PC && (struct map_session_data *) bl)
        luk = ((struct map_session_data *) bl)->paramc[5];

    if (sc_data)
    {
        if (sc_data[SC_GLORIA].timer != -1 && bl->type != BL_PC)    // �O�����A(PC��pc.c��)
            luk += 30;
        if (sc_data[SC_CURSE].timer != -1)  // ��
            luk = 0;
        if (sc_data[SC_TRUESIGHT].timer != -1 && bl->type != BL_PC) // �g�D���[�T�C�g
            luk += 5;
    }
    if (luk < 0)
        luk = 0;
    return luk;
}

/*==========================================
 * �Ώۂ�Flee��Ԃ�(�ėp)
 * �߂�͐�����1�ȏ�
 *------------------------------------------
 */
int battle_get_flee (struct block_list *bl)
{
    int  flee = 1;
    struct status_change *sc_data;

    nullpo_retr (1, bl);
    sc_data = battle_get_sc_data (bl);
    if (bl->type == BL_PC && (struct map_session_data *) bl)
        flee = ((struct map_session_data *) bl)->flee;
    else
        flee = battle_get_agi (bl) + battle_get_lv (bl);

    if (sc_data)
    {
        if (sc_data[SC_WHISTLE].timer != -1 && bl->type != BL_PC)
            flee +=
                flee * (sc_data[SC_WHISTLE].val1 + sc_data[SC_WHISTLE].val2 +
                        (sc_data[SC_WHISTLE].val3 >> 16)) / 100;
        if (sc_data[SC_BLIND].timer != -1 && bl->type != BL_PC)
            flee -= flee * 25 / 100;
        if (sc_data[SC_WINDWALK].timer != -1 && bl->type != BL_PC)  // �E�B���h�E�H�[�N
            flee += flee * (sc_data[SC_WINDWALK].val2) / 100;
        if (sc_data[SC_SPIDERWEB].timer != -1 && bl->type != BL_PC) //�X�p�C�_�[�E�F�u
            flee -= flee * 50 / 100;

        if (battle_is_unarmed (bl))
            flee += (skill_power_bl (bl, TMW_BRAWLING) >> 3);   // +25 for 200
        flee += skill_power_bl (bl, TMW_SPEED) >> 3;
    }
    if (flee < 1)
        flee = 1;
    return flee;
}

/*==========================================
 * �Ώۂ�Hit��Ԃ�(�ėp)
 * �߂�͐�����1�ȏ�
 *------------------------------------------
 */
int battle_get_hit (struct block_list *bl)
{
    int  hit = 1;
    struct status_change *sc_data;

    nullpo_retr (1, bl);
    sc_data = battle_get_sc_data (bl);
    if (bl->type == BL_PC && (struct map_session_data *) bl)
        hit = ((struct map_session_data *) bl)->hit;
    else
        hit = battle_get_dex (bl) + battle_get_lv (bl);

    if (sc_data)
    {
        if (sc_data[SC_HUMMING].timer != -1 && bl->type != BL_PC)   //
            hit +=
                hit * (sc_data[SC_HUMMING].val1 * 2 +
                       sc_data[SC_HUMMING].val2 +
                       sc_data[SC_HUMMING].val3) / 100;
        if (sc_data[SC_BLIND].timer != -1 && bl->type != BL_PC) // ��
            hit -= hit * 25 / 100;
        if (sc_data[SC_TRUESIGHT].timer != -1 && bl->type != BL_PC) // �g�D���[�T�C�g
            hit += 3 * (sc_data[SC_TRUESIGHT].val1);
        if (sc_data[SC_CONCENTRATION].timer != -1 && bl->type != BL_PC) //�R���Z���g���[�V����
            hit += (hit * (10 * (sc_data[SC_CONCENTRATION].val1))) / 100;

        if (battle_is_unarmed (bl))
            hit += (skill_power_bl (bl, TMW_BRAWLING) >> 4);    // +12 for 200
    }
    if (hit < 1)
        hit = 1;
    return hit;
}

/*==========================================
 * �Ώۂ̊��S�����Ԃ�(�ėp)
 * �߂�͐�����1�ȏ�
 *------------------------------------------
 */
int battle_get_flee2 (struct block_list *bl)
{
    int  flee2 = 1;
    struct status_change *sc_data;

    nullpo_retr (1, bl);
    sc_data = battle_get_sc_data (bl);
    if (bl->type == BL_PC && (struct map_session_data *) bl)
    {
        flee2 = battle_get_luk (bl) + 10;
        flee2 +=
            ((struct map_session_data *) bl)->flee2 -
            (((struct map_session_data *) bl)->paramc[5] + 10);
    }
    else
        flee2 = battle_get_luk (bl) + 1;

    if (sc_data)
    {
        if (sc_data[SC_WHISTLE].timer != -1 && bl->type != BL_PC)
            flee2 += (sc_data[SC_WHISTLE].val1 + sc_data[SC_WHISTLE].val2
                      + (sc_data[SC_WHISTLE].val3 & 0xffff)) * 10;

        if (battle_is_unarmed (bl))
            flee2 += (skill_power_bl (bl, TMW_BRAWLING) >> 3);  // +25 for 200
        flee2 += skill_power_bl (bl, TMW_SPEED) >> 3;
    }
    if (flee2 < 1)
        flee2 = 1;
    return flee2;
}

/*==========================================
 * �Ώۂ̃N���e�B�J����Ԃ�(�ėp)
 * �߂�͐�����1�ȏ�
 *------------------------------------------
 */
int battle_get_critical (struct block_list *bl)
{
    int  critical = 1;
    struct status_change *sc_data;

    nullpo_retr (1, bl);
    sc_data = battle_get_sc_data (bl);
    if (bl->type == BL_PC && (struct map_session_data *) bl)
    {
        critical = battle_get_luk (bl) * 2 + 10;
        critical +=
            ((struct map_session_data *) bl)->critical -
            ((((struct map_session_data *) bl)->paramc[5] * 3) + 10);
    }
    else
        critical = battle_get_luk (bl) * 3 + 1;

    if (sc_data)
    {
        if (sc_data[SC_FORTUNE].timer != -1 && bl->type != BL_PC)
            critical +=
                (10 + sc_data[SC_FORTUNE].val1 + sc_data[SC_FORTUNE].val2 +
                 sc_data[SC_FORTUNE].val3) * 10;
        if (sc_data[SC_EXPLOSIONSPIRITS].timer != -1 && bl->type != BL_PC)
            critical += sc_data[SC_EXPLOSIONSPIRITS].val2;
        if (sc_data[SC_TRUESIGHT].timer != -1 && bl->type != BL_PC) //�g�D���[�T�C�g
            critical += critical * sc_data[SC_TRUESIGHT].val1 / 100;
    }
    if (critical < 1)
        critical = 1;
    return critical;
}

/*==========================================
 * base_atk�̎擾
 * �߂�͐�����1�ȏ�
 *------------------------------------------
 */
int battle_get_baseatk (struct block_list *bl)
{
    struct status_change *sc_data;
    int  batk = 1;

    nullpo_retr (1, bl);
    sc_data = battle_get_sc_data (bl);
    if (bl->type == BL_PC && (struct map_session_data *) bl)
        batk = ((struct map_session_data *) bl)->base_atk;  //�ݒ肳��Ă���base_atk
    else
    {                           //����ȊO�Ȃ�
        int  str, dstr;
        str = battle_get_str (bl);  //STR
        dstr = str / 10;
        batk = dstr * dstr + str;   //base_atk���v�Z����
    }
    if (sc_data)
    {                           //��Ԉُ킠��
        if (sc_data[SC_PROVOKE].timer != -1 && bl->type != BL_PC)   //PC�Ńv���{�b�N(SM_PROVOKE)���
            batk = batk * (100 + 2 * sc_data[SC_PROVOKE].val1) / 100;   //base_atk����
        if (sc_data[SC_CURSE].timer != -1)  //���������
            batk -= batk * 25 / 100;    //base_atk��25%����
        if (sc_data[SC_CONCENTRATION].timer != -1 && bl->type != BL_PC) //�R���Z���g���[�V����
            batk += batk * (5 * sc_data[SC_CONCENTRATION].val1) / 100;
    }
    if (batk < 1)
        batk = 1;               //base_atk�͍Œ�ł�1
    return batk;
}

/*==========================================
 * �Ώۂ�Atk��Ԃ�(�ėp)
 * �߂�͐�����0�ȏ�
 *------------------------------------------
 */
int battle_get_atk (struct block_list *bl)
{
    struct status_change *sc_data;
    int  atk = 0;

    nullpo_retr (0, bl);
    sc_data = battle_get_sc_data (bl);
    if (bl->type == BL_PC && (struct map_session_data *) bl)
        atk = ((struct map_session_data *) bl)->watk;
    else if (bl->type == BL_MOB && (struct mob_data *) bl)
        atk = ((struct mob_data *) bl)->stats[MOB_ATK1];

    if (sc_data)
    {
        if (sc_data[SC_PROVOKE].timer != -1 && bl->type != BL_PC)
            atk = atk * (100 + 2 * sc_data[SC_PROVOKE].val1) / 100;
        if (sc_data[SC_CURSE].timer != -1)
            atk -= atk * 25 / 100;
        if (sc_data[SC_CONCENTRATION].timer != -1 && bl->type != BL_PC) //�R���Z���g���[�V����
            atk += atk * (5 * sc_data[SC_CONCENTRATION].val1) / 100;
    }
    if (atk < 0)
        atk = 0;
    return atk;
}

/*==========================================
 * �Ώۂ̍���Atk��Ԃ�(�ėp)
 * �߂�͐�����0�ȏ�
 *------------------------------------------
 */
int battle_get_atk_ (struct block_list *bl)
{
    nullpo_retr (0, bl);
    if (bl->type == BL_PC && (struct map_session_data *) bl)
    {
        int  atk = ((struct map_session_data *) bl)->watk_;

        if (((struct map_session_data *) bl)->sc_data[SC_CURSE].timer != -1)
            atk -= atk * 25 / 100;
        return atk;
    }
    else
        return 0;
}

/*==========================================
 * �Ώۂ�Atk2��Ԃ�(�ėp)
 * �߂�͐�����0�ȏ�
 *------------------------------------------
 */
int battle_get_atk2 (struct block_list *bl)
{
    nullpo_retr (0, bl);
    if (bl->type == BL_PC && (struct map_session_data *) bl)
        return ((struct map_session_data *) bl)->watk2;
    else
    {
        struct status_change *sc_data = battle_get_sc_data (bl);
        int  atk2 = 0;
        if (bl->type == BL_MOB && (struct mob_data *) bl)
            atk2 = ((struct mob_data *) bl)->stats[MOB_ATK2];
        if (sc_data)
        {
            if (sc_data[SC_IMPOSITIO].timer != -1)
                atk2 += sc_data[SC_IMPOSITIO].val1 * 5;
            if (sc_data[SC_PROVOKE].timer != -1)
                atk2 = atk2 * (100 + 2 * sc_data[SC_PROVOKE].val1) / 100;
            if (sc_data[SC_CURSE].timer != -1)
                atk2 -= atk2 * 25 / 100;
            if (sc_data[SC_DRUMBATTLE].timer != -1)
                atk2 += sc_data[SC_DRUMBATTLE].val2;
            if (sc_data[SC_NIBELUNGEN].timer != -1
                && (battle_get_element (bl) / 10) >= 8)
                atk2 += sc_data[SC_NIBELUNGEN].val2;
            if (sc_data[SC_STRIPWEAPON].timer != -1)
                atk2 = atk2 * 90 / 100;
            if (sc_data[SC_CONCENTRATION].timer != -1)  //�R���Z���g���[�V����
                atk2 += atk2 * (5 * sc_data[SC_CONCENTRATION].val1) / 100;
        }

        if (atk2 < 0)
            atk2 = 0;
        return atk2;
    }
    return 0;
}

/*==========================================
 * �Ώۂ̍���Atk2��Ԃ�(�ėp)
 * �߂�͐�����0�ȏ�
 *------------------------------------------
 */
int battle_get_atk_2 (struct block_list *bl)
{
    nullpo_retr (0, bl);
    if (bl->type == BL_PC)
        return ((struct map_session_data *) bl)->watk_2;
    else
        return 0;
}

/*==========================================
 * �Ώۂ�MAtk1��Ԃ�(�ėp)
 * �߂�͐�����0�ȏ�
 *------------------------------------------
 */
int battle_get_matk1 (struct block_list *bl)
{
    struct status_change *sc_data;
    nullpo_retr (0, bl);
    sc_data = battle_get_sc_data (bl);
    if (bl->type == BL_MOB)
    {
        int  matk, int_ = battle_get_int (bl);
        matk = int_ + (int_ / 5) * (int_ / 5);

        if (sc_data)
            if (sc_data[SC_MINDBREAKER].timer != -1 && bl->type != BL_PC)
                matk = matk * (100 + 2 * sc_data[SC_MINDBREAKER].val1) / 100;
        return matk;
    }
    else if (bl->type == BL_PC && (struct map_session_data *) bl)
        return ((struct map_session_data *) bl)->matk1;
    else
        return 0;
}

/*==========================================
 * �Ώۂ�MAtk2��Ԃ�(�ėp)
 * �߂�͐�����0�ȏ�
 *------------------------------------------
 */
int battle_get_matk2 (struct block_list *bl)
{
    struct status_change *sc_data = battle_get_sc_data (bl);
    nullpo_retr (0, bl);
    if (bl->type == BL_MOB)
    {
        int  matk, int_ = battle_get_int (bl);
        matk = int_ + (int_ / 7) * (int_ / 7);

        if (sc_data)
            if (sc_data[SC_MINDBREAKER].timer != -1 && bl->type != BL_PC)
                matk = matk * (100 + 2 * sc_data[SC_MINDBREAKER].val1) / 100;
        return matk;
    }
    else if (bl->type == BL_PC && (struct map_session_data *) bl)
        return ((struct map_session_data *) bl)->matk2;
    else
        return 0;
}

/*==========================================
 * �Ώۂ�Def��Ԃ�(�ėp)
 * �߂�͐�����0�ȏ�
 *------------------------------------------
 */
int battle_get_def (struct block_list *bl)
{
    struct status_change *sc_data;
    int  def = 0, skilltimer = -1, skillid = 0;

    nullpo_retr (0, bl);
    sc_data = battle_get_sc_data (bl);
    if (bl->type == BL_PC && (struct map_session_data *) bl)
    {
        def = ((struct map_session_data *) bl)->def;
        skilltimer = ((struct map_session_data *) bl)->skilltimer;
        skillid = ((struct map_session_data *) bl)->skillid;
    }
    else if (bl->type == BL_MOB && (struct mob_data *) bl)
    {
        def = ((struct mob_data *) bl)->stats[MOB_DEF];
        skilltimer = ((struct mob_data *) bl)->skilltimer;
        skillid = ((struct mob_data *) bl)->skillid;
    }

    if (def < 1000000)
    {
        if (sc_data)
        {
            //�L�[�s���O����DEF100
            if (sc_data[SC_KEEPING].timer != -1)
                def = 100;
            //�v���{�b�N���͌��Z
            if (sc_data[SC_PROVOKE].timer != -1 && bl->type != BL_PC)
                def = (def * (100 - 6 * sc_data[SC_PROVOKE].val1) + 50) / 100;
            //�푾�ۂ̋������͉��Z
            if (sc_data[SC_DRUMBATTLE].timer != -1 && bl->type != BL_PC)
                def += sc_data[SC_DRUMBATTLE].val3;
            //�łɂ������Ă��鎞�͌��Z
            if (sc_data[SC_POISON].timer != -1 && bl->type != BL_PC)
                def = def * 75 / 100;
            //�X�g���b�v�V�[���h���͌��Z
            if (sc_data[SC_STRIPSHIELD].timer != -1 && bl->type != BL_PC)
                def = def * 85 / 100;
            //�V�O�i���N���V�X���͌��Z
            if (sc_data[SC_SIGNUMCRUCIS].timer != -1 && bl->type != BL_PC)
                def = def * (100 - sc_data[SC_SIGNUMCRUCIS].val2) / 100;
            //�i���̍��׎���DEF0�ɂȂ�
            if (sc_data[SC_ETERNALCHAOS].timer != -1 && bl->type != BL_PC)
                def = 0;
            //�����A�Ή����͉E�V�t�g
            if (sc_data[SC_FREEZE].timer != -1
                || (sc_data[SC_STONE].timer != -1
                    && sc_data[SC_STONE].val2 == 0))
                def >>= 1;
            //�R���Z���g���[�V�������͌��Z
            if (sc_data[SC_CONCENTRATION].timer != -1 && bl->type != BL_PC)
                def =
                    (def * (100 - 5 * sc_data[SC_CONCENTRATION].val1)) / 100;
        }
        //�r�����͉r�������Z���Ɋ�Â��Č��Z
        if (skilltimer != -1)
        {
            int  def_rate = skill_get_castdef (skillid);
            if (def_rate != 0)
                def = (def * (100 - def_rate)) / 100;
        }
    }
    if (def < 0)
        def = 0;
    return def;
}

/*==========================================
 * �Ώۂ�MDef��Ԃ�(�ėp)
 * �߂�͐�����0�ȏ�
 *------------------------------------------
 */
int battle_get_mdef (struct block_list *bl)
{
    struct status_change *sc_data;
    int  mdef = 0;

    nullpo_retr (0, bl);
    sc_data = battle_get_sc_data (bl);
    if (bl->type == BL_PC && (struct map_session_data *) bl)
        mdef = ((struct map_session_data *) bl)->mdef;
    else if (bl->type == BL_MOB && (struct mob_data *) bl)
        mdef = ((struct mob_data *) bl)->stats[MOB_MDEF];

    if (mdef < 1000000)
    {
        if (sc_data)
        {
            //�o���A�[��Ԏ���MDEF100
            if (mdef < 90 && sc_data[SC_MBARRIER].timer != -1)
            {
                mdef += sc_data[SC_MBARRIER].val1;
                if (mdef > 90)
                    mdef = 90;
            }
            if (sc_data[SC_BARRIER].timer != -1)
                mdef = 100;
            //�����A�Ή�����1.25�{
            if (sc_data[SC_FREEZE].timer != -1
                || (sc_data[SC_STONE].timer != -1
                    && sc_data[SC_STONE].val2 == 0))
                mdef = mdef * 125 / 100;
            if (sc_data[SC_MINDBREAKER].timer != -1 && bl->type != BL_PC)
                mdef -= (mdef * 6 * sc_data[SC_MINDBREAKER].val1) / 100;
        }
    }
    if (mdef < 0)
        mdef = 0;
    return mdef;
}

/*==========================================
 * �Ώۂ�Def2��Ԃ�(�ėp)
 * �߂�͐�����1�ȏ�
 *------------------------------------------
 */
int battle_get_def2 (struct block_list *bl)
{
    struct status_change *sc_data;
    int  def2 = 1;

    nullpo_retr (1, bl);
    sc_data = battle_get_sc_data (bl);
    if (bl->type == BL_PC)
        def2 = ((struct map_session_data *) bl)->def2;
    else if (bl->type == BL_MOB)
        def2 = ((struct mob_data *) bl)->stats[MOB_VIT];

    if (sc_data)
    {
        if (sc_data[SC_ANGELUS].timer != -1 && bl->type != BL_PC)
            def2 = def2 * (110 + 5 * sc_data[SC_ANGELUS].val1) / 100;
        if (sc_data[SC_PROVOKE].timer != -1 && bl->type != BL_PC)
            def2 = (def2 * (100 - 6 * sc_data[SC_PROVOKE].val1) + 50) / 100;
        if (sc_data[SC_POISON].timer != -1 && bl->type != BL_PC)
            def2 = def2 * 75 / 100;
        //�R���Z���g���[�V�������͌��Z
        if (sc_data[SC_CONCENTRATION].timer != -1 && bl->type != BL_PC)
            def2 = def2 * (100 - 5 * sc_data[SC_CONCENTRATION].val1) / 100;
    }
    if (def2 < 1)
        def2 = 1;
    return def2;
}

/*==========================================
 * �Ώۂ�MDef2��Ԃ�(�ėp)
 * �߂�͐�����0�ȏ�
 *------------------------------------------
 */
int battle_get_mdef2 (struct block_list *bl)
{
    int  mdef2 = 0;
    struct status_change *sc_data = battle_get_sc_data (bl);

    nullpo_retr (0, bl);
    if (bl->type == BL_MOB)
        mdef2 =
            ((struct mob_data *) bl)->stats[MOB_INT] +
            (((struct mob_data *) bl)->stats[MOB_VIT] >> 1);
    else if (bl->type == BL_PC)
        mdef2 =
            ((struct map_session_data *) bl)->mdef2 +
            (((struct map_session_data *) bl)->paramc[2] >> 1);
    if (sc_data)
    {
        if (sc_data[SC_MINDBREAKER].timer != -1 && bl->type != BL_PC)
            mdef2 -= (mdef2 * 6 * sc_data[SC_MINDBREAKER].val1) / 100;
    }
    if (mdef2 < 0)
        mdef2 = 0;
    return mdef2;
}

/*==========================================
 * �Ώۂ�Speed(�ړ����x)��Ԃ�(�ėp)
 * �߂�͐�����1�ȏ�
 * Speed�͏������ق����ړ����x������
 *------------------------------------------
 */
int battle_get_speed (struct block_list *bl)
{
    nullpo_retr (1000, bl);
    if (bl->type == BL_PC && (struct map_session_data *) bl)
        return ((struct map_session_data *) bl)->speed;
    else
    {
        struct status_change *sc_data = battle_get_sc_data (bl);
        int  speed = 1000;
        if (bl->type == BL_MOB && (struct mob_data *) bl)
            speed = ((struct mob_data *) bl)->stats[MOB_SPEED];

        if (sc_data)
        {
            //���x��������25%���Z
            if (sc_data[SC_INCREASEAGI].timer != -1
                && sc_data[SC_DONTFORGETME].timer == -1)
                speed -= speed * 25 / 100;
            //���x��������25%���Z
            if (sc_data[SC_DECREASEAGI].timer != -1)
                speed = speed * 125 / 100;
            //�N�@�O�}�C�A����50%���Z
            if (sc_data[SC_QUAGMIRE].timer != -1)
                speed = speed * 3 / 2;
            //����Y��Ȃ��Łc���͉��Z
            if (sc_data[SC_DONTFORGETME].timer != -1)
                speed =
                    speed * (100 + sc_data[SC_DONTFORGETME].val1 * 2 +
                             sc_data[SC_DONTFORGETME].val2 +
                             (sc_data[SC_DONTFORGETME].val3 & 0xffff)) / 100;
            //��������25%���Z
            if (sc_data[SC_STEELBODY].timer != -1)
                speed = speed * 125 / 100;
            //�f�B�t�F���_�[���͉��Z
            if (sc_data[SC_DEFENDER].timer != -1)
                speed = (speed * (155 - sc_data[SC_DEFENDER].val1 * 5)) / 100;
            //�x���Ԃ�4�{�x��
            if (sc_data[SC_DANCING].timer != -1)
                speed *= 4;
            //�􂢎���450���Z
            if (sc_data[SC_CURSE].timer != -1)
                speed = speed + 450;
            //�E�B���h�E�H�[�N����Lv*2%���Z
            if (sc_data[SC_WINDWALK].timer != -1)
                speed -= (speed * (sc_data[SC_WINDWALK].val1 * 2)) / 100;
        }
        if (speed < 1)
            speed = 1;
        return speed;
    }

    return 1000;
}

/*==========================================
 * �Ώۂ�aDelay(�U�����f�B���C)��Ԃ�(�ėp)
 * aDelay�͏������ق����U�����x������
 *------------------------------------------
 */
int battle_get_adelay (struct block_list *bl)
{
    nullpo_retr (4000, bl);
    if (bl->type == BL_PC && (struct map_session_data *) bl)
        return (((struct map_session_data *) bl)->aspd << 1);
    else
    {
        struct status_change *sc_data = battle_get_sc_data (bl);
        int  adelay = 4000, aspd_rate = 100, i;
        if (bl->type == BL_MOB && (struct mob_data *) bl)
            adelay = ((struct mob_data *) bl)->stats[MOB_ADELAY];

        if (sc_data)
        {
            //�c�[�n���h�N�C�b�P���g�p���ŃN�@�O�}�C�A�ł�����Y��Ȃ��Łc�ł��Ȃ�����3�����Z
            if (sc_data[SC_TWOHANDQUICKEN].timer != -1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1) // 2HQ
                aspd_rate -= 30;
            //�A�h���i�������b�V���g�p���Ńc�[�n���h�N�C�b�P���ł��N�@�O�}�C�A�ł�����Y��Ȃ��Łc�ł��Ȃ�����
            if (sc_data[SC_ADRENALINE].timer != -1
                && sc_data[SC_TWOHANDQUICKEN].timer == -1
                && sc_data[SC_QUAGMIRE].timer == -1
                && sc_data[SC_DONTFORGETME].timer == -1)
            {                   // �A�h���i�������b�V��
                //�g�p�҂ƃp�[�e�B�����o�[�Ŋi�����o��ݒ�łȂ����3�����Z
                if (sc_data[SC_ADRENALINE].val2
                    || !battle_config.party_skill_penaly)
                    aspd_rate -= 30;
                //�����łȂ����2.5�����Z
                else
                    aspd_rate -= 25;
            }
            //�X�s�A�N�B�b�P�����͌��Z
            if (sc_data[SC_SPEARSQUICKEN].timer != -1 && sc_data[SC_ADRENALINE].timer == -1 && sc_data[SC_TWOHANDQUICKEN].timer == -1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1)  // �X�s�A�N�B�b�P��
                aspd_rate -= sc_data[SC_SPEARSQUICKEN].val2;
            //�[���̃A�T�V���N���X���͌��Z
            if (sc_data[SC_ASSNCROS].timer != -1 && // �[�z�̃A�T�V���N���X
                sc_data[SC_TWOHANDQUICKEN].timer == -1
                && sc_data[SC_ADRENALINE].timer == -1
                && sc_data[SC_SPEARSQUICKEN].timer == -1
                && sc_data[SC_DONTFORGETME].timer == -1)
                aspd_rate -=
                    5 + sc_data[SC_ASSNCROS].val1 +
                    sc_data[SC_ASSNCROS].val2 + sc_data[SC_ASSNCROS].val3;
            //����Y��Ȃ��Łc���͉��Z
            if (sc_data[SC_DONTFORGETME].timer != -1)   // ����Y��Ȃ���
                aspd_rate +=
                    sc_data[SC_DONTFORGETME].val1 * 3 +
                    sc_data[SC_DONTFORGETME].val2 +
                    (sc_data[SC_DONTFORGETME].val3 >> 16);
            //������25%���Z
            if (sc_data[SC_STEELBODY].timer != -1)  // ����
                aspd_rate += 25;
            //�����|�[�V�����g�p���͌��Z
            if (sc_data[i = SC_SPEEDPOTION2].timer != -1
                || sc_data[i = SC_SPEEDPOTION1].timer != -1
                || sc_data[i = SC_SPEEDPOTION0].timer != -1)
                aspd_rate -= sc_data[i].val1;
            // Fate's `haste' spell works the same as the above
            if (sc_data[SC_HASTE].timer != -1)
                aspd_rate -= sc_data[SC_HASTE].val1;
            //�f�B�t�F���_�[���͉��Z
            if (sc_data[SC_DEFENDER].timer != -1)
                adelay += (1100 - sc_data[SC_DEFENDER].val1 * 100);
        }

        if (aspd_rate != 100)
            adelay = adelay * aspd_rate / 100;
        if (adelay < battle_config.monster_max_aspd << 1)
            adelay = battle_config.monster_max_aspd << 1;
        return adelay;
    }
    return 4000;
}

int battle_get_amotion (struct block_list *bl)
{
    nullpo_retr (2000, bl);
    if (bl->type == BL_PC && (struct map_session_data *) bl)
        return ((struct map_session_data *) bl)->amotion;
    else
    {
        struct status_change *sc_data = battle_get_sc_data (bl);
        int  amotion = 2000, aspd_rate = 100, i;
        if (bl->type == BL_MOB && (struct mob_data *) bl)
            amotion = mob_db[((struct mob_data *) bl)->class].amotion;

        if (sc_data)
        {
            if (sc_data[SC_TWOHANDQUICKEN].timer != -1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1) // 2HQ
                aspd_rate -= 30;
            if (sc_data[SC_ADRENALINE].timer != -1
                && sc_data[SC_TWOHANDQUICKEN].timer == -1
                && sc_data[SC_QUAGMIRE].timer == -1
                && sc_data[SC_DONTFORGETME].timer == -1)
            {                   // �A�h���i�������b�V��
                if (sc_data[SC_ADRENALINE].val2
                    || !battle_config.party_skill_penaly)
                    aspd_rate -= 30;
                else
                    aspd_rate -= 25;
            }
            if (sc_data[SC_SPEARSQUICKEN].timer != -1 && sc_data[SC_ADRENALINE].timer == -1 && sc_data[SC_TWOHANDQUICKEN].timer == -1 && sc_data[SC_QUAGMIRE].timer == -1 && sc_data[SC_DONTFORGETME].timer == -1)  // �X�s�A�N�B�b�P��
                aspd_rate -= sc_data[SC_SPEARSQUICKEN].val2;
            if (sc_data[SC_ASSNCROS].timer != -1 && // �[�z�̃A�T�V���N���X
                sc_data[SC_TWOHANDQUICKEN].timer == -1
                && sc_data[SC_ADRENALINE].timer == -1
                && sc_data[SC_SPEARSQUICKEN].timer == -1
                && sc_data[SC_DONTFORGETME].timer == -1)
                aspd_rate -=
                    5 + sc_data[SC_ASSNCROS].val1 +
                    sc_data[SC_ASSNCROS].val2 + sc_data[SC_ASSNCROS].val3;
            if (sc_data[SC_DONTFORGETME].timer != -1)   // ����Y��Ȃ���
                aspd_rate +=
                    sc_data[SC_DONTFORGETME].val1 * 3 +
                    sc_data[SC_DONTFORGETME].val2 +
                    (sc_data[SC_DONTFORGETME].val3 >> 16);
            if (sc_data[SC_STEELBODY].timer != -1)  // ����
                aspd_rate += 25;
            if (sc_data[i = SC_SPEEDPOTION2].timer != -1
                || sc_data[i = SC_SPEEDPOTION1].timer != -1
                || sc_data[i = SC_SPEEDPOTION0].timer != -1)
                aspd_rate -= sc_data[i].val1;
            if (sc_data[SC_HASTE].timer != -1)
                aspd_rate -= sc_data[SC_HASTE].val1;
            if (sc_data[SC_DEFENDER].timer != -1)
                amotion += (550 - sc_data[SC_DEFENDER].val1 * 50);
        }

        if (aspd_rate != 100)
            amotion = amotion * aspd_rate / 100;
        if (amotion < battle_config.monster_max_aspd)
            amotion = battle_config.monster_max_aspd;
        return amotion;
    }
    return 2000;
}

int battle_get_dmotion (struct block_list *bl)
{
    int  ret;
    struct status_change *sc_data;

    nullpo_retr (0, bl);
    sc_data = battle_get_sc_data (bl);
    if (bl->type == BL_MOB && (struct mob_data *) bl)
    {
        ret = mob_db[((struct mob_data *) bl)->class].dmotion;
        if (battle_config.monster_damage_delay_rate != 100)
            ret = ret * battle_config.monster_damage_delay_rate / 400;
    }
    else if (bl->type == BL_PC && (struct map_session_data *) bl)
    {
        ret = ((struct map_session_data *) bl)->dmotion;
        if (battle_config.pc_damage_delay_rate != 100)
            ret = ret * battle_config.pc_damage_delay_rate / 400;
    }
    else
        return 2000;

    if ((sc_data && sc_data[SC_ENDURE].timer != -1) ||
        (bl->type == BL_PC
         && ((struct map_session_data *) bl)->special_state.infinite_endure))
        ret = 0;

    return ret;
}

int battle_get_element (struct block_list *bl)
{
    int  ret = 20;
    struct status_change *sc_data;

    nullpo_retr (ret, bl);
    sc_data = battle_get_sc_data (bl);
    if (bl->type == BL_MOB && (struct mob_data *) bl)   // 10�̈ʁ�Lv*2�A�P�̈ʁ�����
        ret = ((struct mob_data *) bl)->def_ele;
    else if (bl->type == BL_PC && (struct map_session_data *) bl)
        ret = 20 + ((struct map_session_data *) bl)->def_ele;   // �h�䑮��Lv1

    if (sc_data)
    {
        if (sc_data[SC_BENEDICTIO].timer != -1) // ���̍~��
            ret = 26;
        if (sc_data[SC_FREEZE].timer != -1) // ����
            ret = 21;
        if (sc_data[SC_STONE].timer != -1 && sc_data[SC_STONE].val2 == 0)
            ret = 22;
    }

    return ret;
}

int battle_get_attack_element (struct block_list *bl)
{
    int  ret = 0;
    struct status_change *sc_data = battle_get_sc_data (bl);

    nullpo_retr (0, bl);
    if (bl->type == BL_MOB && (struct mob_data *) bl)
        ret = 0;
    else if (bl->type == BL_PC && (struct map_session_data *) bl)
        ret = ((struct map_session_data *) bl)->atk_ele;

    if (sc_data)
    {
        if (sc_data[SC_FROSTWEAPON].timer != -1)    // �t���X�g�E�F�|��
            ret = 1;
        if (sc_data[SC_SEISMICWEAPON].timer != -1)  // �T�C�Y�~�b�N�E�F�|��
            ret = 2;
        if (sc_data[SC_FLAMELAUNCHER].timer != -1)  // �t���[�������`���[
            ret = 3;
        if (sc_data[SC_LIGHTNINGLOADER].timer != -1)    // ���C�g�j���O���[�_�[
            ret = 4;
        if (sc_data[SC_ENCPOISON].timer != -1)  // �G���`�����g�|�C�Y��
            ret = 5;
        if (sc_data[SC_ASPERSIO].timer != -1)   // �A�X�y���V�I
            ret = 6;
    }

    return ret;
}

int battle_get_attack_element2 (struct block_list *bl)
{
    nullpo_retr (0, bl);
    if (bl->type == BL_PC && (struct map_session_data *) bl)
    {
        int  ret = ((struct map_session_data *) bl)->atk_ele_;
        struct status_change *sc_data =
            ((struct map_session_data *) bl)->sc_data;

        if (sc_data)
        {
            if (sc_data[SC_FROSTWEAPON].timer != -1)    // �t���X�g�E�F�|��
                ret = 1;
            if (sc_data[SC_SEISMICWEAPON].timer != -1)  // �T�C�Y�~�b�N�E�F�|��
                ret = 2;
            if (sc_data[SC_FLAMELAUNCHER].timer != -1)  // �t���[�������`���[
                ret = 3;
            if (sc_data[SC_LIGHTNINGLOADER].timer != -1)    // ���C�g�j���O���[�_�[
                ret = 4;
            if (sc_data[SC_ENCPOISON].timer != -1)  // �G���`�����g�|�C�Y��
                ret = 5;
            if (sc_data[SC_ASPERSIO].timer != -1)   // �A�X�y���V�I
                ret = 6;
        }
        return ret;
    }
    return 0;
}

int battle_get_party_id (struct block_list *bl)
{
    nullpo_retr (0, bl);
    if (bl->type == BL_PC && (struct map_session_data *) bl)
        return ((struct map_session_data *) bl)->status.party_id;
    else if (bl->type == BL_MOB && (struct mob_data *) bl)
    {
        struct mob_data *md = (struct mob_data *) bl;
        if (md->master_id > 0)
            return -md->master_id;
        return -md->bl.id;
    }
    else if (bl->type == BL_SKILL && (struct skill_unit *) bl)
        return ((struct skill_unit *) bl)->group->party_id;
    else
        return 0;
}

int battle_get_guild_id (struct block_list *bl)
{
    nullpo_retr (0, bl);
    if (bl->type == BL_PC && (struct map_session_data *) bl)
        return ((struct map_session_data *) bl)->status.guild_id;
    else if (bl->type == BL_MOB && (struct mob_data *) bl)
        return ((struct mob_data *) bl)->class;
    else if (bl->type == BL_SKILL && (struct skill_unit *) bl)
        return ((struct skill_unit *) bl)->group->guild_id;
    else
        return 0;
}

int battle_get_race (struct block_list *bl)
{
    nullpo_retr (0, bl);
    if (bl->type == BL_MOB && (struct mob_data *) bl)
        return mob_db[((struct mob_data *) bl)->class].race;
    else if (bl->type == BL_PC && (struct map_session_data *) bl)
        return 7;
    else
        return 0;
}

int battle_get_size (struct block_list *bl)
{
    nullpo_retr (1, bl);
    if (bl->type == BL_MOB && (struct mob_data *) bl)
        return mob_db[((struct mob_data *) bl)->class].size;
    else if (bl->type == BL_PC && (struct map_session_data *) bl)
        return 1;
    else
        return 1;
}

int battle_get_mode (struct block_list *bl)
{
    nullpo_retr (0x01, bl);
    if (bl->type == BL_MOB && (struct mob_data *) bl)
        return mob_db[((struct mob_data *) bl)->class].mode;
    else
        return 0x01;            // �Ƃ肠���������Ƃ������Ƃ�1
}

int battle_get_mexp (struct block_list *bl)
{
    nullpo_retr (0, bl);
    if (bl->type == BL_MOB && (struct mob_data *) bl)
    {
        const struct mob_data *mob = (struct mob_data *) bl;
        const int retval =
            (mob_db[mob->class].mexp *
             (int) (mob->stats[MOB_XP_BONUS])) >> MOB_XP_BONUS_SHIFT;
        fprintf (stderr, "Modifier of %x: -> %d\n", mob->stats[MOB_XP_BONUS],
                 retval);
        return retval;
    }
    else
        return 0;
}

int battle_get_stat (int stat_id /* SP_VIT or similar */ ,
                     struct block_list *bl)
{
    switch (stat_id)
    {
        case SP_STR:
            return battle_get_str (bl);
        case SP_AGI:
            return battle_get_agi (bl);
        case SP_DEX:
            return battle_get_dex (bl);
        case SP_VIT:
            return battle_get_vit (bl);
        case SP_INT:
            return battle_get_int (bl);
        case SP_LUK:
            return battle_get_luk (bl);
        default:
            return 0;
    }
}

// StatusChange�n�̏���
struct status_change *battle_get_sc_data (struct block_list *bl)
{
    nullpo_retr (NULL, bl);
    if (bl->type == BL_MOB && (struct mob_data *) bl)
        return ((struct mob_data *) bl)->sc_data;
    else if (bl->type == BL_PC && (struct map_session_data *) bl)
        return ((struct map_session_data *) bl)->sc_data;
    return NULL;
}

short *battle_get_sc_count (struct block_list *bl)
{
    nullpo_retr (NULL, bl);
    if (bl->type == BL_MOB && (struct mob_data *) bl)
        return &((struct mob_data *) bl)->sc_count;
    else if (bl->type == BL_PC && (struct map_session_data *) bl)
        return &((struct map_session_data *) bl)->sc_count;
    return NULL;
}

short *battle_get_opt1 (struct block_list *bl)
{
    nullpo_retr (0, bl);
    if (bl->type == BL_MOB && (struct mob_data *) bl)
        return &((struct mob_data *) bl)->opt1;
    else if (bl->type == BL_PC && (struct map_session_data *) bl)
        return &((struct map_session_data *) bl)->opt1;
    else if (bl->type == BL_NPC && (struct npc_data *) bl)
        return &((struct npc_data *) bl)->opt1;
    return 0;
}

short *battle_get_opt2 (struct block_list *bl)
{
    nullpo_retr (0, bl);
    if (bl->type == BL_MOB && (struct mob_data *) bl)
        return &((struct mob_data *) bl)->opt2;
    else if (bl->type == BL_PC && (struct map_session_data *) bl)
        return &((struct map_session_data *) bl)->opt2;
    else if (bl->type == BL_NPC && (struct npc_data *) bl)
        return &((struct npc_data *) bl)->opt2;
    return 0;
}

short *battle_get_opt3 (struct block_list *bl)
{
    nullpo_retr (0, bl);
    if (bl->type == BL_MOB && (struct mob_data *) bl)
        return &((struct mob_data *) bl)->opt3;
    else if (bl->type == BL_PC && (struct map_session_data *) bl)
        return &((struct map_session_data *) bl)->opt3;
    else if (bl->type == BL_NPC && (struct npc_data *) bl)
        return &((struct npc_data *) bl)->opt3;
    return 0;
}

short *battle_get_option (struct block_list *bl)
{
    nullpo_retr (0, bl);
    if (bl->type == BL_MOB && (struct mob_data *) bl)
        return &((struct mob_data *) bl)->option;
    else if (bl->type == BL_PC && (struct map_session_data *) bl)
        return &((struct map_session_data *) bl)->status.option;
    else if (bl->type == BL_NPC && (struct npc_data *) bl)
        return &((struct npc_data *) bl)->option;
    return 0;
}

//-------------------------------------------------------------------

// �_���[�W�̒x��
struct battle_delay_damage_
{
    struct block_list *src, *target;
    int  damage;
    int  flag;
};
int battle_delay_damage_sub (int tid, unsigned int tick, int id, int data)
{
    struct battle_delay_damage_ *dat = (struct battle_delay_damage_ *) data;
    if (dat && map_id2bl (id) == dat->src && dat->target->prev != NULL)
        battle_damage (dat->src, dat->target, dat->damage, dat->flag);
    free (dat);
    return 0;
}

int battle_delay_damage (unsigned int tick, struct block_list *src,
                         struct block_list *target, int damage, int flag)
{
    struct battle_delay_damage_ *dat =
        (struct battle_delay_damage_ *) aCalloc (1,
                                                 sizeof (struct
                                                         battle_delay_damage_));

    nullpo_retr (0, src);
    nullpo_retr (0, target);

    dat->src = src;
    dat->target = target;
    dat->damage = damage;
    dat->flag = flag;
    add_timer (tick, battle_delay_damage_sub, src->id, (int) dat);
    return 0;
}

// ���ۂ�HP�𑀍�
int battle_damage (struct block_list *bl, struct block_list *target,
                   int damage, int flag)
{
    struct map_session_data *sd = NULL;
    struct status_change *sc_data = battle_get_sc_data (target);
    short *sc_count;
    int  i;

    nullpo_retr (0, target);    //bl��NULL�ŌĂ΂�邱�Ƃ�����̂ő��Ń`�F�b�N

    if (damage == 0)
        return 0;

    if (target->prev == NULL)
        return 0;

    if (bl)
    {
        if (bl->prev == NULL)
            return 0;

        if (bl->type == BL_PC)
            sd = (struct map_session_data *) bl;
    }

    if (damage < 0)
        return battle_heal (bl, target, -damage, 0, flag);

    if (!flag && (sc_count = battle_get_sc_count (target)) != NULL
        && *sc_count > 0)
    {
        // �����A�Ή��A����������
        if (sc_data[SC_FREEZE].timer != -1)
            skill_status_change_end (target, SC_FREEZE, -1);
        if (sc_data[SC_STONE].timer != -1 && sc_data[SC_STONE].val2 == 0)
            skill_status_change_end (target, SC_STONE, -1);
        if (sc_data[SC_SLEEP].timer != -1)
            skill_status_change_end (target, SC_SLEEP, -1);
    }

    if (target->type == BL_MOB)
    {                           // MOB
        struct mob_data *md = (struct mob_data *) target;
        if (md && md->skilltimer != -1 && md->state.skillcastcancel)    // �r���W�Q
            skill_castcancel (target, 0);
        return mob_damage (bl, md, damage, 0);
    }
    else if (target->type == BL_PC)
    {                           // PC

        struct map_session_data *tsd = (struct map_session_data *) target;

        if (tsd && tsd->sc_data && tsd->sc_data[SC_DEVOTION].val1)
        {                       // �f�B�{�[�V����������������
            struct map_session_data *md =
                map_id2sd (tsd->sc_data[SC_DEVOTION].val1);
            if (md && skill_devotion3 (&md->bl, target->id))
            {
                skill_devotion (md, target->id);
            }
            else if (md && bl)
                for (i = 0; i < 5; i++)
                    if (md->dev.val1[i] == target->id)
                    {
                        clif_damage (bl, &md->bl, gettick (), 0, 0,
                                     damage, 0, 0, 0);
                        pc_damage (&md->bl, md, damage);

                        return 0;
                    }
        }

        if (tsd && tsd->skilltimer != -1)
        {                       // �r���W�Q
            // �t�F���J�[�h��W�Q����Ȃ��X�L�����̌���
            if ((!tsd->special_state.no_castcancel || map[bl->m].flag.gvg)
                && tsd->state.skillcastcancel
                && !tsd->special_state.no_castcancel2)
                skill_castcancel (target, 0);
        }

        return pc_damage (bl, tsd, damage);

    }
    else if (target->type == BL_SKILL)
        return skill_unit_ondamaged ((struct skill_unit *) target, bl, damage,
                                     gettick ());
    return 0;
}

int battle_heal (struct block_list *bl, struct block_list *target, int hp,
                 int sp, int flag)
{
    nullpo_retr (0, target);    //bl��NULL�ŌĂ΂�邱�Ƃ�����̂ő��Ń`�F�b�N

    if (target->type == BL_PC
        && pc_isdead ((struct map_session_data *) target))
        return 0;
    if (hp == 0 && sp == 0)
        return 0;

    if (hp < 0)
        return battle_damage (bl, target, -hp, flag);

    if (target->type == BL_MOB)
        return mob_heal ((struct mob_data *) target, hp);
    else if (target->type == BL_PC)
        return pc_heal ((struct map_session_data *) target, hp, sp);
    return 0;
}

// �U����~
int battle_stopattack (struct block_list *bl)
{
    nullpo_retr (0, bl);
    if (bl->type == BL_MOB)
        return mob_stopattack ((struct mob_data *) bl);
    else if (bl->type == BL_PC)
        return pc_stopattack ((struct map_session_data *) bl);
    return 0;
}

// �ړ���~
int battle_stopwalking (struct block_list *bl, int type)
{
    nullpo_retr (0, bl);
    if (bl->type == BL_MOB)
        return mob_stop_walking ((struct mob_data *) bl, type);
    else if (bl->type == BL_PC)
        return pc_stop_walking ((struct map_session_data *) bl, type);
    return 0;
}

/*==========================================
 * �_���[�W�̑����C��
 *------------------------------------------
 */
int battle_attr_fix (int damage, int atk_elem, int def_elem)
{
    int  def_type = def_elem % 10, def_lv = def_elem / 10 / 2;

    if (atk_elem < 0 || atk_elem > 9 || def_type < 0 || def_type > 9 ||
        def_lv < 1 || def_lv > 4)
    {                           // �� ���l�����������̂łƂ肠�������̂܂ܕԂ�
        if (battle_config.error_log)
            printf
                ("battle_attr_fix: unknown attr type: atk=%d def_type=%d def_lv=%d\n",
                 atk_elem, def_type, def_lv);
        return damage;
    }

    return damage * attr_fix_table[def_lv - 1][atk_elem][def_type] / 100;
}

/*==========================================
 * �_���[�W�ŏI�v�Z
 *------------------------------------------
 */
int battle_calc_damage (struct block_list *src, struct block_list *bl,
                        int damage, int div_, int skill_num, int skill_lv,
                        int flag)
{
    struct map_session_data *sd = NULL;
    struct mob_data *md = NULL;
    struct status_change *sc_data, *sc;
    short *sc_count;
    int  class;

    nullpo_retr (0, bl);

    class = battle_get_class (bl);
    if (bl->type == BL_MOB)
        md = (struct mob_data *) bl;
    else
        sd = (struct map_session_data *) bl;

    sc_data = battle_get_sc_data (bl);
    sc_count = battle_get_sc_count (bl);

    if (sc_count != NULL && *sc_count > 0)
    {

        if (sc_data[SC_SAFETYWALL].timer != -1 && damage > 0
            && flag & BF_WEAPON && flag & BF_SHORT
            && skill_num != NPC_GUIDEDATTACK)
        {
            // �Z�[�t�e�B�E�H�[��
            struct skill_unit *unit =
                (struct skill_unit *) sc_data[SC_SAFETYWALL].val2;
            if (unit && unit->alive && (--unit->group->val2) <= 0)
                skill_delunit (unit);
            skill_unit_move (bl, gettick (), 1);    // �d�ˊ|���`�F�b�N
            damage = 0;
        }
        if (sc_data[SC_PNEUMA].timer != -1 && damage > 0 && flag & BF_WEAPON
            && flag & BF_LONG && skill_num != NPC_GUIDEDATTACK)
        {
            // �j���[�}
            damage = 0;
        }

        if (sc_data[SC_ROKISWEIL].timer != -1 && damage > 0 &&
            flag & BF_MAGIC)
        {
            // �j���[�}
            damage = 0;
        }

        if (sc_data[SC_AETERNA].timer != -1 && damage > 0)
        {                       // ���b�N�X�G�[�e���i
            damage <<= 1;
            skill_status_change_end (bl, SC_AETERNA, -1);
        }

        //������̃_���[�W����
        if (sc_data[SC_VOLCANO].timer != -1)
        {                       // �{���P�[�m
            if (flag & BF_SKILL && skill_get_pl (skill_num) == 3)
                damage += damage * sc_data[SC_VOLCANO].val4 / 100;
            else if (!flag & BF_SKILL && battle_get_attack_element (bl) == 3)
                damage += damage * sc_data[SC_VOLCANO].val4 / 100;
        }

        if (sc_data[SC_VIOLENTGALE].timer != -1)
        {                       // �o�C�I�����g�Q�C��
            if (flag & BF_SKILL && skill_get_pl (skill_num) == 4)
                damage += damage * sc_data[SC_VIOLENTGALE].val4 / 100;
            else if (!flag & BF_SKILL && battle_get_attack_element (bl) == 4)
                damage += damage * sc_data[SC_VIOLENTGALE].val4 / 100;
        }

        if (sc_data[SC_DELUGE].timer != -1)
        {                       // �f�����[�W
            if (flag & BF_SKILL && skill_get_pl (skill_num) == 1)
                damage += damage * sc_data[SC_DELUGE].val4 / 100;
            else if (!flag & BF_SKILL && battle_get_attack_element (bl) == 1)
                damage += damage * sc_data[SC_DELUGE].val4 / 100;
        }

        if (sc_data[SC_ENERGYCOAT].timer != -1 && damage > 0
            && flag & BF_WEAPON)
        {                       // �G�i�W�[�R�[�g
            if (sd)
            {
                if (sd->status.sp > 0)
                {
                    int  per = sd->status.sp * 5 / (sd->status.max_sp + 1);
                    sd->status.sp -= sd->status.sp * (per * 5 + 10) / 1000;
                    if (sd->status.sp < 0)
                        sd->status.sp = 0;
                    damage -= damage * ((per + 1) * 6) / 100;
                    clif_updatestatus (sd, SP_SP);
                }
                if (sd->status.sp <= 0)
                    skill_status_change_end (bl, SC_ENERGYCOAT, -1);
            }
            else
                damage -= damage * (sc_data[SC_ENERGYCOAT].val1 * 6) / 100;
        }

        if (sc_data[SC_KYRIE].timer != -1 && damage > 0)
        {                       // �L���G�G���C�\��
            sc = &sc_data[SC_KYRIE];
            sc->val2 -= damage;
            if (flag & BF_WEAPON)
            {
                if (sc->val2 >= 0)
                    damage = 0;
                else
                    damage = -sc->val2;
            }
            if ((--sc->val3) <= 0 || (sc->val2 <= 0)
                || skill_num == AL_HOLYLIGHT)
                skill_status_change_end (bl, SC_KYRIE, -1);
        }

        if (sc_data[SC_BASILICA].timer != -1 && damage > 0)
        {
            // �j���[�}
            damage = 0;
        }
        if (sc_data[SC_LANDPROTECTOR].timer != -1 && damage > 0
            && flag & BF_MAGIC)
        {
            // �j���[�}
            damage = 0;
        }

        if (sc_data[SC_AUTOGUARD].timer != -1 && damage > 0
            && flag & BF_WEAPON)
        {
            if (MRAND (100) < sc_data[SC_AUTOGUARD].val2)
            {
                damage = 0;
                clif_skill_nodamage (bl, bl, CR_AUTOGUARD,
                                     sc_data[SC_AUTOGUARD].val1, 1);
                if (sd)
                    sd->canmove_tick = gettick () + 300;
                else if (md)
                    md->canmove_tick = gettick () + 300;
            }
        }
// -- moonsoul (chance to block attacks with new Lord Knight skill parrying)
//
        if (sc_data[SC_PARRYING].timer != -1 && damage > 0
            && flag & BF_WEAPON)
        {
            if (MRAND (100) < sc_data[SC_PARRYING].val2)
            {
                damage = 0;
                clif_skill_nodamage (bl, bl, LK_PARRYING,
                                     sc_data[SC_PARRYING].val1, 1);
            }
        }
        // ���W�F�N�g�\�[�h
        if (sc_data[SC_REJECTSWORD].timer != -1 && damage > 0
            && flag & BF_WEAPON
            &&
            ((src->type == BL_PC
              && ((struct map_session_data *) src)->status.weapon == (1 || 2
                                                                      || 3))
             || src->type == BL_MOB))
        {
            if (MRAND (100) < (10 + 5 * sc_data[SC_REJECTSWORD].val1))
            {                   //���ˊm����10+5*Lv
                damage = damage * 50 / 100;
                battle_damage (bl, src, damage, 0);
                //�_���[�W��^�����̂͗ǂ��񂾂��A��������ǂ����ĕ\������񂾂��킩��˂�
                //�G�t�F�N�g������ł����̂��킩��˂�
                clif_skill_nodamage (bl, bl, ST_REJECTSWORD,
                                     sc_data[SC_REJECTSWORD].val1, 1);
                if ((--sc_data[SC_REJECTSWORD].val2) <= 0)
                    skill_status_change_end (bl, SC_REJECTSWORD, -1);
            }
        }
    }

    if (class == 1288 || class == 1287 || class == 1286 || class == 1285)
    {
//  if(class == 1288) {
        if (class == 1288 && flag & BF_SKILL)
            damage = 0;
        if (src->type == BL_PC)
        {
            struct guild *g =
                guild_search (((struct map_session_data *) src)->
                              status.guild_id);
            struct guild_castle *gc = guild_mapname2gc (map[bl->m].name);
            if (!((struct map_session_data *) src)->status.guild_id)
                damage = 0;
            if (gc && agit_flag == 0 && class != 1288)  // guardians cannot be damaged during non-woe [Valaris]
                damage = 0;     // end woe check [Valaris]
            if (g == NULL)
                damage = 0;     //�M���h�������Ȃ�_���[�W����
            else if ((gc != NULL) && guild_isallied (g, gc))
                damage = 0;     //����̃M���h�̃G���y�Ȃ�_���[�W����
            else if (g && guild_checkskill (g, GD_APPROVAL) <= 0)
                damage = 0;     //���K�M���h���F���Ȃ��ƃ_���[�W����
            else if (battle_config.guild_max_castles != 0
                     && guild_checkcastles (g) >=
                     battle_config.guild_max_castles)
                damage = 0;     // [MouseJstr]
        }
        else
            damage = 0;
    }

    if (map[bl->m].flag.gvg && damage > 0)
    {                           //GvG
        if (flag & BF_WEAPON)
        {
            if (flag & BF_SHORT)
                damage = damage * battle_config.gvg_short_damage_rate / 100;
            if (flag & BF_LONG)
                damage = damage * battle_config.gvg_long_damage_rate / 100;
        }
        if (flag & BF_MAGIC)
            damage = damage * battle_config.gvg_magic_damage_rate / 100;
        if (flag & BF_MISC)
            damage = damage * battle_config.gvg_misc_damage_rate / 100;
        if (damage < 1)
            damage = 1;
    }

    if (battle_config.skill_min_damage || flag & BF_MISC)
    {
        if (div_ < 255)
        {
            if (damage > 0 && damage < div_)
                damage = div_;
        }
        else if (damage > 0 && damage < 3)
            damage = 3;
    }

    if (md != NULL && md->hp > 0 && damage > 0) // �����Ȃǂ�MOB�X�L������
        mobskill_event (md, flag);

    return damage;
}

/*==========================================
 * �C���_���[�W
 *------------------------------------------
 */
int battle_addmastery (struct map_session_data *sd, struct block_list *target,
                       int dmg, int type)
{
    int  damage, skill;
    int  race = battle_get_race (target);
    int  weapon;
    damage = 0;

    nullpo_retr (0, sd);

    // �f�[�����x�C��(+3 �` +30) vs �s�� or ���� (���l�͊܂߂Ȃ��H)
    if ((skill = pc_checkskill (sd, AL_DEMONBANE)) > 0
        && (battle_check_undead (race, battle_get_elem_type (target))
            || race == 6))
        damage += (skill * 3);

    // �r�[�X�g�x�C��(+4 �` +40) vs ���� or ����
    if ((skill = pc_checkskill (sd, HT_BEASTBANE)) > 0
        && (race == 2 || race == 4))
        damage += (skill * 4);

    if (type == 0)
        weapon = sd->weapontype1;
    else
        weapon = sd->weapontype2;
    switch (weapon)
    {
        case 0x01:             // �Z�� (Updated By AppleGirl)
        case 0x02:             // 1HS
        {
            // ���C��(+4 �` +40) �Ў茕 �Z���܂�
            if ((skill = pc_checkskill (sd, SM_SWORD)) > 0)
            {
                damage += (skill * 4);
            }
            break;
        }
        case 0x03:             // 2HS
        {
            // ���茕�C��(+4 �` +40) ���茕
            if ((skill = pc_checkskill (sd, SM_TWOHAND)) > 0)
            {
                damage += (skill * 4);
            }
            break;
        }
        case 0x04:             // 1HL
        {
            // ���C��(+4 �` +40,+5 �` +50) ��
            if ((skill = pc_checkskill (sd, KN_SPEARMASTERY)) > 0)
            {
                if (!pc_isriding (sd))
                    damage += (skill * 4);  // �y�R�ɏ���ĂȂ�
                else
                    damage += (skill * 5);  // �y�R�ɏ���Ă�
            }
            break;
        }
        case 0x05:             // 2HL
        {
            // ���C��(+4 �` +40,+5 �` +50) ��
            if ((skill = pc_checkskill (sd, KN_SPEARMASTERY)) > 0)
            {
                if (!pc_isriding (sd))
                    damage += (skill * 4);  // �y�R�ɏ���ĂȂ�
                else
                    damage += (skill * 5);  // �y�R�ɏ���Ă�
            }
            break;
        }
        case 0x06:             // �Ў蕀
        {
            if ((skill = pc_checkskill (sd, AM_AXEMASTERY)) > 0)
            {
                damage += (skill * 3);
            }
            break;
        }
        case 0x07:             // Axe by Tato
        {
            if ((skill = pc_checkskill (sd, AM_AXEMASTERY)) > 0)
            {
                damage += (skill * 3);
            }
            break;
        }
        case 0x08:             // ���C�X
        {
            // ���C�X�C��(+3 �` +30) ���C�X
            if ((skill = pc_checkskill (sd, PR_MACEMASTERY)) > 0)
            {
                damage += (skill * 3);
            }
            break;
        }
        case 0x09:             // �Ȃ�?
            break;
        case 0x0a:             // ��
            break;
        case 0x0b:             // �|
            break;
        case 0x00:             // �f��
        case 0x0c:             // Knuckles
        {
            // �S��(+3 �` +30) �f��,�i�b�N��
            if ((skill = pc_checkskill (sd, MO_IRONHAND)) > 0)
            {
                damage += (skill * 3);
            }
            break;
        }
        case 0x0d:             // Musical Instrument
        {
            // �y��̗��K(+3 �` +30) �y��
            if ((skill = pc_checkskill (sd, BA_MUSICALLESSON)) > 0)
            {
                damage += (skill * 3);
            }
            break;
        }
        case 0x0e:             // Dance Mastery
        {
            // Dance Lesson Skill Effect(+3 damage for every lvl = +30) ��
            if ((skill = pc_checkskill (sd, DC_DANCINGLESSON)) > 0)
            {
                damage += (skill * 3);
            }
            break;
        }
        case 0x0f:             // Book
        {
            // Advance Book Skill Effect(+3 damage for every lvl = +30) {
            if ((skill = pc_checkskill (sd, SA_ADVANCEDBOOK)) > 0)
            {
                damage += (skill * 3);
            }
            break;
        }
        case 0x10:             // Katars
        {
            // �J�^�[���C��(+3 �` +30) �J�^�[��
            if ((skill = pc_checkskill (sd, AS_KATAR)) > 0)
            {
                //�\�j�b�N�u���[���͕ʏ����i1���ɕt��1/8�K��)
                damage += (skill * 3);
            }
            break;
        }
    }
    damage = dmg + damage;
    return (damage);
}

static struct Damage battle_calc_mob_weapon_attack (struct block_list *src,
                                                    struct block_list *target,
                                                    int skill_num,
                                                    int skill_lv, int wflag)
{
    struct map_session_data *tsd = NULL;
    struct mob_data *md = (struct mob_data *) src, *tmd = NULL;
    int  hitrate, flee, cri = 0, atkmin, atkmax;
    int  luk, target_count = 1;
    int  def1 = battle_get_def (target);
    int  def2 = battle_get_def2 (target);
    int  t_vit = battle_get_vit (target);
    struct Damage wd;
    int  damage, damage2 = 0, type, div_, blewcount =
        skill_get_blewcount (skill_num, skill_lv);
    int  flag, skill, ac_flag = 0, dmg_lv = 0;
    int  t_mode = 0, t_race = 0, t_size = 1, s_race = 0, s_ele = 0;
    struct status_change *sc_data, *t_sc_data;
    short *sc_count;
    short *option, *opt1, *opt2;

    //return�O�̏���������̂ŏ��o�͕��̂ݕύX
    if (src == NULL || target == NULL || md == NULL)
    {
        nullpo_info (NLP_MARK);
        memset (&wd, 0, sizeof (wd));
        return wd;
    }

    s_race = battle_get_race (src);
    s_ele = battle_get_attack_element (src);
    sc_data = battle_get_sc_data (src);
    sc_count = battle_get_sc_count (src);
    option = battle_get_option (src);
    opt1 = battle_get_opt1 (src);
    opt2 = battle_get_opt2 (src);

    // �^�[�Q�b�g
    if (target->type == BL_PC)
        tsd = (struct map_session_data *) target;
    else if (target->type == BL_MOB)
        tmd = (struct mob_data *) target;
    t_race = battle_get_race (target);
    t_size = battle_get_size (target);
    t_mode = battle_get_mode (target);
    t_sc_data = battle_get_sc_data (target);

    if ((skill_num == 0
         || (target->type == BL_PC && battle_config.pc_auto_counter_type & 2)
         || (target->type == BL_MOB
             && battle_config.monster_auto_counter_type & 2))
        && skill_lv >= 0)
    {
        if (skill_num != CR_GRANDCROSS && t_sc_data
            && t_sc_data[SC_AUTOCOUNTER].timer != -1)
        {
            int  dir = map_calc_dir (src, target->x, target->y), t_dir =
                battle_get_dir (target);
            int  dist = distance (src->x, src->y, target->x, target->y);
            if (dist <= 0 || map_check_dir (dir, t_dir))
            {
                memset (&wd, 0, sizeof (wd));
                t_sc_data[SC_AUTOCOUNTER].val3 = 0;
                t_sc_data[SC_AUTOCOUNTER].val4 = 1;
                if (sc_data && sc_data[SC_AUTOCOUNTER].timer == -1)
                {
                    int  range = battle_get_range (target);
                    if ((target->type == BL_PC
                         && ((struct map_session_data *) target)->
                         status.weapon != 11 && dist <= range + 1)
                        || (target->type == BL_MOB && range <= 3
                            && dist <= range + 1))
                        t_sc_data[SC_AUTOCOUNTER].val3 = src->id;
                }
                return wd;
            }
            else
                ac_flag = 1;
        }
    }
    flag = BF_SHORT | BF_WEAPON | BF_NORMAL;    // �U���̎�ނ̐ݒ�

    // ��𗦌v�Z�A��𔻒�͌��
    flee = battle_get_flee (target);
    if (battle_config.agi_penaly_type > 0
        || battle_config.vit_penaly_type > 0)
        target_count +=
            battle_counttargeted (target, src,
                                  battle_config.agi_penaly_count_lv);
    if (battle_config.agi_penaly_type > 0)
    {
        if (target_count >= battle_config.agi_penaly_count)
        {
            if (battle_config.agi_penaly_type == 1)
                flee =
                    (flee *
                     (100 -
                      (target_count -
                       (battle_config.agi_penaly_count -
                        1)) * battle_config.agi_penaly_num)) / 100;
            else if (battle_config.agi_penaly_type == 2)
                flee -=
                    (target_count -
                     (battle_config.agi_penaly_count -
                      1)) * battle_config.agi_penaly_num;
            if (flee < 1)
                flee = 1;
        }
    }
    hitrate = battle_get_hit (src) - flee + 80;

    type = 0;                   // normal
    div_ = 1;                   // single attack

    luk = battle_get_luk (src);

    if (battle_config.enemy_str)
        damage = battle_get_baseatk (src);
    else
        damage = 0;
    if (skill_num == HW_MAGICCRASHER)
    {                           /* �}�W�b�N�N���b�V���[��MATK�ʼn��� */
        atkmin = battle_get_matk1 (src);
        atkmax = battle_get_matk2 (src);
    }
    else
    {
        atkmin = battle_get_atk (src);
        atkmax = battle_get_atk2 (src);
    }
    if (mob_db[md->class].range > 3)
        flag = (flag & ~BF_RANGEMASK) | BF_LONG;

    if (atkmin > atkmax)
        atkmin = atkmax;

    if (sc_data != NULL && sc_data[SC_MAXIMIZEPOWER].timer != -1)
    {                           // �}�L�V�}�C�Y�p���[
        atkmin = atkmax;
    }

    cri = battle_get_critical (src);
    cri -= battle_get_luk (target) * 3;
    if (battle_config.enemy_critical_rate != 100)
    {
        cri = cri * battle_config.enemy_critical_rate / 100;
        if (cri < 1)
            cri = 1;
    }
    if (t_sc_data != NULL && t_sc_data[SC_SLEEP].timer != -1)   // �������̓N���e�B�J�����{��
        cri <<= 1;

    if (ac_flag)
        cri = 1000;

    if (skill_num == KN_AUTOCOUNTER)
    {
        if (!(battle_config.monster_auto_counter_type & 1))
            cri = 1000;
        else
            cri <<= 1;
    }

    if (tsd && tsd->critical_def)
        cri = cri * (100 - tsd->critical_def) / 100;

    if ((skill_num == 0 || skill_num == KN_AUTOCOUNTER) && skill_lv >= 0 && battle_config.enemy_critical && (MRAND (1000)) < cri)   // ����i�X�L���̏ꍇ�͖����j
        // �G�̔���
    {
        damage += atkmax;
        type = 0x0a;
    }
    else
    {
        int  vitbonusmax;

        if (atkmax > atkmin)
            damage += atkmin + MRAND ((atkmax - atkmin + 1));
        else
            damage += atkmin;
        // �X�L���C���P�i�U���͔{���n�j
        // �I�[�o�[�g���X�g(+5% �` +25%),���U���n�X�L���̏ꍇ�����ŕ␳
        // �o�b�V��,�}�O�i���u���C�N,
        // �{�[�����O�o�b�V��,�X�s�A�u�[������,�u�����f�B�b�V���X�s�A,�X�s�A�X�^�b�u,
        // ���}�[�i�C�g,�J�[�g���{�����[�V����
        // �_�u���X�g���C�t�B���O,�A���[�V�����[,�`���[�W�A���[,
        // �\�j�b�N�u���[
        if (sc_data)
        {                       //��Ԉُ풆�̃_���[�W�lj�
            if (sc_data[SC_OVERTHRUST].timer != -1) // �I�[�o�[�g���X�g
                damage += damage * (5 * sc_data[SC_OVERTHRUST].val1) / 100;
            if (sc_data[SC_TRUESIGHT].timer != -1)  // �g�D���[�T�C�g
                damage += damage * (2 * sc_data[SC_TRUESIGHT].val1) / 100;
            if (sc_data[SC_BERSERK].timer != -1)    // �o�[�T�[�N
                damage += damage * 50 / 100;
        }

        if (skill_num > 0)
        {
            int  i;
            if ((i = skill_get_pl (skill_num)) > 0)
                s_ele = i;

            flag = (flag & ~BF_SKILLMASK) | BF_SKILL;
            switch (skill_num)
            {
                case SM_BASH:  // �o�b�V��
                    damage = damage * (100 + 30 * skill_lv) / 100;
                    hitrate = (hitrate * (100 + 5 * skill_lv)) / 100;
                    break;
                case SM_MAGNUM:    // �}�O�i���u���C�N
                    damage =
                        damage * (5 * skill_lv + (wflag) ? 65 : 115) / 100;
                    break;
                case MC_MAMMONITE: // ���}�[�i�C�g
                    damage = damage * (100 + 50 * skill_lv) / 100;
                    break;
                case AC_DOUBLE:    // �_�u���X�g���C�t�B���O
                    damage = damage * (180 + 20 * skill_lv) / 100;
                    div_ = 2;
                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
                    break;
                case AC_SHOWER:    // �A���[�V�����[
                    damage = damage * (75 + 5 * skill_lv) / 100;
                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
                    break;
                case AC_CHARGEARROW:   // �`���[�W�A���[
                    damage = damage * 150 / 100;
                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
                    break;
                case KN_PIERCE:    // �s�A�[�X
                    damage = damage * (100 + 10 * skill_lv) / 100;
                    hitrate = hitrate * (100 + 5 * skill_lv) / 100;
                    div_ = t_size + 1;
                    damage *= div_;
                    break;
                case KN_SPEARSTAB: // �X�s�A�X�^�u
                    damage = damage * (100 + 15 * skill_lv) / 100;
                    break;
                case KN_SPEARBOOMERANG:    // �X�s�A�u�[������
                    damage = damage * (100 + 50 * skill_lv) / 100;
                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
                    break;
                case KN_BRANDISHSPEAR: // �u�����f�B�b�V���X�s�A
                    damage = damage * (100 + 20 * skill_lv) / 100;
                    if (skill_lv > 3 && wflag == 1)
                        damage2 += damage / 2;
                    if (skill_lv > 6 && wflag == 1)
                        damage2 += damage / 4;
                    if (skill_lv > 9 && wflag == 1)
                        damage2 += damage / 8;
                    if (skill_lv > 6 && wflag == 2)
                        damage2 += damage / 2;
                    if (skill_lv > 9 && wflag == 2)
                        damage2 += damage / 4;
                    if (skill_lv > 9 && wflag == 3)
                        damage2 += damage / 2;
                    damage += damage2;
                    blewcount = 0;
                    break;
                case KN_BOWLINGBASH:   // �{�E�����O�o�b�V��
                    damage = damage * (100 + 50 * skill_lv) / 100;
                    blewcount = 0;
                    break;
                case KN_AUTOCOUNTER:
                    if (battle_config.monster_auto_counter_type & 1)
                        hitrate += 20;
                    else
                        hitrate = 1000000;
                    flag = (flag & ~BF_SKILLMASK) | BF_NORMAL;
                    break;
                case AS_SONICBLOW: // �\�j�b�N�u���E
                    damage = damage * (300 + 50 * skill_lv) / 100;
                    div_ = 8;
                    break;
                case TF_SPRINKLESAND:  // ���܂�
                    damage = damage * 125 / 100;
                    break;
                case MC_CARTREVOLUTION:    // �J�[�g���{�����[�V����
                    damage = (damage * 150) / 100;
                    break;
                    // �ȉ�MOB
                case NPC_COMBOATTACK:  // ���i�U��
                    div_ = skill_get_num (skill_num, skill_lv);
                    damage *= div_;
                    break;
                case NPC_RANDOMATTACK: // �����_��ATK�U��
                    damage = damage * (MPRAND (50, 150)) / 100;
                    break;
                    // �����U���i�K���j
                case NPC_WATERATTACK:
                case NPC_GROUNDATTACK:
                case NPC_FIREATTACK:
                case NPC_WINDATTACK:
                case NPC_POISONATTACK:
                case NPC_HOLYATTACK:
                case NPC_DARKNESSATTACK:
                case NPC_TELEKINESISATTACK:
                    damage = damage * (100 + 25 * (skill_lv - 1)) / 100;
                    break;
                case NPC_GUIDEDATTACK:
                    hitrate = 1000000;
                    break;
                case NPC_RANGEATTACK:
                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
                    break;
                case NPC_PIERCINGATT:
                    flag = (flag & ~BF_RANGEMASK) | BF_SHORT;
                    break;
                case RG_BACKSTAP:  // �o�b�N�X�^�u
                    damage = damage * (300 + 40 * skill_lv) / 100;
                    hitrate = 1000000;
                    break;
                case RG_RAID:  // �T�v���C�Y�A�^�b�N
                    damage = damage * (100 + 40 * skill_lv) / 100;
                    break;
                case RG_INTIMIDATE:    // �C���e�B�~�f�C�g
                    damage = damage * (100 + 30 * skill_lv) / 100;
                    break;
                case CR_SHIELDCHARGE:  // �V�[���h�`���[�W
                    damage = damage * (100 + 20 * skill_lv) / 100;
                    flag = (flag & ~BF_RANGEMASK) | BF_SHORT;
                    s_ele = 0;
                    break;
                case CR_SHIELDBOOMERANG:   // �V�[���h�u�[������
                    damage = damage * (100 + 30 * skill_lv) / 100;
                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
                    s_ele = 0;
                    break;
                case CR_HOLYCROSS: // �z�[���[�N���X
                    damage = damage * (100 + 35 * skill_lv) / 100;
                    div_ = 2;
                    break;
                case CR_GRANDCROSS:
                    hitrate = 1000000;
                    break;
                case AM_DEMONSTRATION: // �f�����X�g���[�V����
                    damage = damage * (100 + 20 * skill_lv) / 100;
                    damage2 = damage2 * (100 + 20 * skill_lv) / 100;
                    break;
                case AM_ACIDTERROR:    // �A�V�b�h�e���[
                    damage = damage * (100 + 40 * skill_lv) / 100;
                    damage2 = damage2 * (100 + 40 * skill_lv) / 100;
                    break;
                case MO_FINGEROFFENSIVE:   //�w�e
                    damage = damage * (100 + 50 * skill_lv) / 100;
                    div_ = 1;
                    break;
                case MO_INVESTIGATE:   // �� ��
                    if (def1 < 1000000)
                        damage =
                            damage * (100 + 75 * skill_lv) / 100 * (def1 +
                                                                    def2) /
                            100;
                    hitrate = 1000000;
                    s_ele = 0;
                    break;
                case MO_EXTREMITYFIST: // ���C���e�P��
                    damage = damage * 8 + 250 + (skill_lv * 150);
                    hitrate = 1000000;
                    s_ele = 0;
                    break;
                case MO_CHAINCOMBO:    // �A�ŏ�
                    damage = damage * (150 + 50 * skill_lv) / 100;
                    div_ = 4;
                    break;
                case BA_MUSICALSTRIKE: // �~���[�W�J���X�g���C�N
                    damage = damage * (100 + 50 * skill_lv) / 100;
                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
                    break;
                case DC_THROWARROW:    // ���
                    damage = damage * (100 + 50 * skill_lv) / 100;
                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
                    break;
                case MO_COMBOFINISH:   // �җ���
                    damage = damage * (240 + 60 * skill_lv) / 100;
                    break;
                case CH_TIGERFIST: // ���Ռ�
                    damage = damage * (100 + 20 * skill_lv) / 100;
                    break;
                case CH_CHAINCRUSH:    // �A������
                    damage = damage * (100 + 20 * skill_lv) / 100;
                    div_ = skill_get_num (skill_num, skill_lv);
                    break;
                case CH_PALMSTRIKE:    // �ҌՍd�h�R
                    damage = damage * (50 + 100 * skill_lv) / 100;
                    break;
                case LK_SPIRALPIERCE:  /* �X�p�C�����s�A�[�X */
                    damage = damage * (100 + 50 * skill_lv) / 100;  //�����ʂ�������Ȃ��̂œK����
                    div_ = 5;
                    if (tsd)
                        tsd->canmove_tick = gettick () + 1000;
                    else if (tmd)
                        tmd->canmove_tick = gettick () + 1000;
                    break;
                case LK_HEADCRUSH: /* �w�b�h�N���b�V�� */
                    damage = damage * (100 + 20 * skill_lv) / 100;
                    break;
                case LK_JOINTBEAT: /* �W���C���g�r�[�g */
                    damage = damage * (50 + 10 * skill_lv) / 100;
                    break;
                case ASC_METEORASSAULT:    /* ���e�I�A�T���g */
                    damage = damage * (40 + 40 * skill_lv) / 100;
                    break;
                case SN_SHARPSHOOTING: /* �V���[�v�V���[�e�B���O */
                    damage += damage * (30 * skill_lv) / 100;
                    break;
                case CG_ARROWVULCAN:   /* �A���[�o���J�� */
                    damage = damage * (160 + 40 * skill_lv) / 100;
                    div_ = 9;
                    break;
                case AS_SPLASHER:  /* �x�i���X�v���b�V���[ */
                    damage = damage * (200 + 20 * skill_lv) / 100;
                    break;
            }
        }

        if (skill_num != NPC_CRITICALSLASH)
        {
            // �� �ۂ̖h��͂ɂ��_���[�W�̌���
            // �f�B�o�C���v���e�N�V�����i�����ł����̂��ȁH�j
            if (skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST
                && skill_num != KN_AUTOCOUNTER && def1 < 1000000)
            {                   //DEF, VIT����
                int  t_def;
                target_count =
                    1 + battle_counttargeted (target, src,
                                              battle_config.vit_penaly_count_lv);
                if (battle_config.vit_penaly_type > 0)
                {
                    if (target_count >= battle_config.vit_penaly_count)
                    {
                        if (battle_config.vit_penaly_type == 1)
                        {
                            def1 =
                                (def1 *
                                 (100 -
                                  (target_count -
                                   (battle_config.vit_penaly_count -
                                    1)) * battle_config.vit_penaly_num)) /
                                100;
                            def2 =
                                (def2 *
                                 (100 -
                                  (target_count -
                                   (battle_config.vit_penaly_count -
                                    1)) * battle_config.vit_penaly_num)) /
                                100;
                            t_vit =
                                (t_vit *
                                 (100 -
                                  (target_count -
                                   (battle_config.vit_penaly_count -
                                    1)) * battle_config.vit_penaly_num)) /
                                100;
                        }
                        else if (battle_config.vit_penaly_type == 2)
                        {
                            def1 -=
                                (target_count -
                                 (battle_config.vit_penaly_count -
                                  1)) * battle_config.vit_penaly_num;
                            def2 -=
                                (target_count -
                                 (battle_config.vit_penaly_count -
                                  1)) * battle_config.vit_penaly_num;
                            t_vit -=
                                (target_count -
                                 (battle_config.vit_penaly_count -
                                  1)) * battle_config.vit_penaly_num;
                        }
                        if (def1 < 0)
                            def1 = 0;
                        if (def2 < 1)
                            def2 = 1;
                        if (t_vit < 1)
                            t_vit = 1;
                    }
                }
                t_def = def2 * 8 / 10;
                if (battle_check_undead (s_race, battle_get_elem_type (src))
                    || s_race == 6)
                    if (tsd && (skill = pc_checkskill (tsd, AL_DP)) > 0)
                        t_def += skill * 3;

                vitbonusmax = (t_vit / 20) * (t_vit / 20) - 1;
                if (battle_config.monster_defense_type)
                {
                    damage =
                        damage - (def1 * battle_config.monster_defense_type) -
                        t_def -
                        ((vitbonusmax < 1) ? 0 : MRAND ((vitbonusmax + 1)));
                }
                else
                {
                    damage =
                        damage * (100 - def1) / 100 - t_def -
                        ((vitbonusmax < 1) ? 0 : MRAND ((vitbonusmax + 1)));
                }
            }
        }
    }

    // 0�����������ꍇ1�ɕ␳
    if (damage < 1)
        damage = 1;

    // ����C��
    if (hitrate < 1000000)
        hitrate = ((hitrate > 95) ? 95 : ((hitrate < 5) ? 5 : hitrate));
    if (hitrate < 1000000 &&    // �K���U��
        (t_sc_data != NULL && (t_sc_data[SC_SLEEP].timer != -1 ||   // �����͕K��
                               t_sc_data[SC_STAN].timer != -1 ||    // �X�^���͕K��
                               t_sc_data[SC_FREEZE].timer != -1 || (t_sc_data[SC_STONE].timer != -1 && t_sc_data[SC_STONE].val2 == 0))))    // �����͕K��
        hitrate = 1000000;
    if (type == 0 && MRAND (100) >= hitrate)
    {
        damage = damage2 = 0;
        dmg_lv = ATK_FLEE;
    }
    else
    {
        dmg_lv = ATK_DEF;
    }

    if (tsd)
    {
        int  cardfix = 100, i;
        cardfix = cardfix * (100 - tsd->subele[s_ele]) / 100;   // �� ���ɂ��_���[�W�ϐ�
        cardfix = cardfix * (100 - tsd->subrace[s_race]) / 100; // �푰�ɂ��_���[�W�ϐ�
        if (mob_db[md->class].mode & 0x20)
            cardfix = cardfix * (100 - tsd->subrace[10]) / 100;
        else
            cardfix = cardfix * (100 - tsd->subrace[11]) / 100;
        for (i = 0; i < tsd->add_def_class_count; i++)
        {
            if (tsd->add_def_classid[i] == md->class)
            {
                cardfix = cardfix * (100 - tsd->add_def_classrate[i]) / 100;
                break;
            }
        }
        if (flag & BF_LONG)
            cardfix = cardfix * (100 - tsd->long_attack_def_rate) / 100;
        if (flag & BF_SHORT)
            cardfix = cardfix * (100 - tsd->near_attack_def_rate) / 100;
        damage = damage * cardfix / 100;
    }
    if (t_sc_data)
    {
        int  cardfix = 100;
        if (t_sc_data[SC_DEFENDER].timer != -1 && flag & BF_LONG)
            cardfix = cardfix * (100 - t_sc_data[SC_DEFENDER].val2) / 100;
        if (cardfix != 100)
            damage = damage * cardfix / 100;
    }
    if (t_sc_data && t_sc_data[SC_ASSUMPTIO].timer != -1)
    {                           //�A�V�����v�e�B�I
        if (!map[target->m].flag.pvp)
            damage = damage / 3;
        else
            damage = damage / 2;
    }

    if (damage < 0)
        damage = 0;

    // �� ���̓K�p
    if (!((battle_config.mob_ghostring_fix == 1) && (battle_get_element (target) == 8) && (target->type == BL_PC))) // [MouseJstr]
        if (skill_num != 0 || s_ele != 0
            || !battle_config.mob_attack_attr_none)
            damage =
                battle_attr_fix (damage, s_ele, battle_get_element (target));

    if (sc_data && sc_data[SC_AURABLADE].timer != -1)   /* �I�[���u���[�h �K�� */
        damage += sc_data[SC_AURABLADE].val1 * 10;
    if (skill_num == PA_PRESSURE)   /* �v���b�V���[ �K��? */
        damage = 700 + 100 * skill_lv;

    // �C���x�i���C��
    if (skill_num == TF_POISON)
    {
        damage =
            battle_attr_fix (damage + 15 * skill_lv, s_ele,
                             battle_get_element (target));
    }
    if (skill_num == MC_CARTREVOLUTION)
    {
        damage = battle_attr_fix (damage, 0, battle_get_element (target));
    }

    // ���S����̔���
    if (skill_num == 0 && skill_lv >= 0 && tsd != NULL
        && MRAND (1000) < battle_get_flee2 (target))
    {
        damage = 0;
        type = 0x0b;
        dmg_lv = ATK_LUCKY;
    }

    if (battle_config.enemy_perfect_flee)
    {
        if (skill_num == 0 && skill_lv >= 0 && tmd != NULL
            && MRAND (1000) < battle_get_flee2 (target))
        {
            damage = 0;
            type = 0x0b;
            dmg_lv = ATK_LUCKY;
        }
    }

//  if(def1 >= 1000000 && damage > 0)
    if (t_mode & 0x40 && damage > 0)
        damage = 1;

    if (tsd && tsd->special_state.no_weapon_damage)
        damage = 0;

    if (skill_num != CR_GRANDCROSS)
        damage =
            battle_calc_damage (src, target, damage, div_, skill_num,
                                skill_lv, flag);

    wd.damage = damage;
    wd.damage2 = 0;
    wd.type = type;
    wd.div_ = div_;
    wd.amotion = battle_get_amotion (src);
    if (skill_num == KN_AUTOCOUNTER)
        wd.amotion >>= 1;
    wd.dmotion = battle_get_dmotion (target);
    wd.blewcount = blewcount;
    wd.flag = flag;
    wd.dmg_lv = dmg_lv;
    return wd;
}

int battle_is_unarmed (struct block_list *bl)
{
    if (!bl)
        return 0;
    if (bl->type == BL_PC)
    {
        struct map_session_data *sd = (struct map_session_data *) bl;

        return (sd->equip_index[EQUIP_SHIELD] == -1
                && sd->equip_index[EQUIP_WEAPON] == -1);
    }
    else
        return 0;
}

/*
 * =========================================================================
 * PC�̕���ɂ��U��
 *-------------------------------------------------------------------------
 */
static struct Damage battle_calc_pc_weapon_attack (struct block_list *src,
                                                   struct block_list *target,
                                                   int skill_num,
                                                   int skill_lv, int wflag)
{
    struct map_session_data *sd = (struct map_session_data *) src, *tsd =
        NULL;
    struct mob_data *tmd = NULL;
    int  hitrate, flee, cri = 0, atkmin, atkmax;
    int  dex, luk, target_count = 1;
    int  def1 = battle_get_def (target);
    int  def2 = battle_get_def2 (target);
    int  t_vit = battle_get_vit (target);
    struct Damage wd;
    int  damage, damage2, damage3 = 0, damage4 = 0, type, div_, blewcount =
        skill_get_blewcount (skill_num, skill_lv);
    int  flag, skill, dmg_lv = 0;
    int  t_mode = 0, t_race = 0, t_size = 1, s_race = 7, s_ele = 0;
    struct status_change *sc_data, *t_sc_data;
    short *sc_count;
    short *option, *opt1, *opt2;
    int  atkmax_ = 0, atkmin_ = 0, s_ele_;  //�񓁗��p
    int  watk, watk_, cardfix, t_ele;
    int  da = 0, i, t_class, ac_flag = 0;
    int  idef_flag = 0, idef_flag_ = 0;
    int  target_distance;

    //return�O�̏���������̂ŏ��o�͕��̂ݕύX
    if (src == NULL || target == NULL || sd == NULL)
    {
        nullpo_info (NLP_MARK);
        memset (&wd, 0, sizeof (wd));
        return wd;
    }

    // �A�^�b�J�[
    s_race = battle_get_race (src); //�푰
    s_ele = battle_get_attack_element (src);    //����
    s_ele_ = battle_get_attack_element2 (src);  //���葮��
    sc_data = battle_get_sc_data (src); //�X�e�[�^�X�ُ�
    sc_count = battle_get_sc_count (src);   //�X�e�[�^�X�ُ�̐�
    option = battle_get_option (src);   //��Ƃ��y�R�Ƃ��J�[�g�Ƃ�
    opt1 = battle_get_opt1 (src);   //�Ή��A�����A�X�^���A�����A�È�
    opt2 = battle_get_opt2 (src);   //�ŁA�􂢁A���فA�ÈŁH

    if (skill_num != CR_GRANDCROSS) //�O�����h�N���X�łȂ��Ȃ�
        sd->state.attack_type = BF_WEAPON;  //�U���^�C�v�͕���U��

    // �^�[�Q�b�g
    if (target->type == BL_PC)  //�Ώۂ�PC�Ȃ�
        tsd = (struct map_session_data *) target;   //tsd�ɑ��(tmd��NULL)
    else if (target->type == BL_MOB)    //�Ώۂ�Mob�Ȃ�
        tmd = (struct mob_data *) target;   //tmd�ɑ��(tsd��NULL)
    t_race = battle_get_race (target);  //�Ώۂ̎푰
    t_ele = battle_get_elem_type (target);  //�Ώۂ̑���
    t_size = battle_get_size (target);  //�Ώۂ̃T�C�Y
    t_mode = battle_get_mode (target);  //�Ώۂ�Mode
    t_sc_data = battle_get_sc_data (target);    //�Ώۂ̃X�e�[�^�X�ُ�

//�I�[�g�J�E���^�[������������
    if ((skill_num == 0
         || (target->type == BL_PC && battle_config.pc_auto_counter_type & 2)
         || (target->type == BL_MOB
             && battle_config.monster_auto_counter_type & 2))
        && skill_lv >= 0)
    {
        if (skill_num != CR_GRANDCROSS && t_sc_data
            && t_sc_data[SC_AUTOCOUNTER].timer != -1)
        {                       //�O�����h�N���X�łȂ��A�Ώۂ��I�[�g�J�E���^�[��Ԃ̏ꍇ
            int  dir = map_calc_dir (src, target->x, target->y), t_dir =
                battle_get_dir (target);
            int  dist = distance (src->x, src->y, target->x, target->y);
            if (dist <= 0 || map_check_dir (dir, t_dir))
            {                   //�ΏۂƂ̋�����0�ȉ��A�܂��͑Ώۂ̐��ʁH
                memset (&wd, 0, sizeof (wd));
                t_sc_data[SC_AUTOCOUNTER].val3 = 0;
                t_sc_data[SC_AUTOCOUNTER].val4 = 1;
                if (sc_data && sc_data[SC_AUTOCOUNTER].timer == -1)
                {               //�������I�[�g�J�E���^�[���
                    int  range = battle_get_range (target);
                    if ((target->type == BL_PC && ((struct map_session_data *) target)->status.weapon != 11 && dist <= range + 1) ||    //�Ώۂ�PC�ŕ��킪�|��łȂ��˒���
                        (target->type == BL_MOB && range <= 3 && dist <= range + 1))    //�܂��͑Ώۂ�Mob�Ŏ˒���3�ȉ��Ŏ˒���
                        t_sc_data[SC_AUTOCOUNTER].val3 = src->id;
                }
                return wd;      //�_���[�W�\���̂�Ԃ��ďI��
            }
            else
                ac_flag = 1;
        }
    }
//�I�[�g�J�E���^�[���������܂�

    flag = BF_SHORT | BF_WEAPON | BF_NORMAL;    // �U���̎�ނ̐ݒ�

    // ��𗦌v�Z�A��𔻒�͌��
    flee = battle_get_flee (target);
    if (battle_config.agi_penaly_type > 0 || battle_config.vit_penaly_type > 0) //AGI�AVIT�y�i���e�B�ݒ肪�L��
        target_count += battle_counttargeted (target, src, battle_config.agi_penaly_count_lv);  //�Ώۂ̐����Z�o
    if (battle_config.agi_penaly_type > 0)
    {
        if (target_count >= battle_config.agi_penaly_count)
        {                       //�y�i���e�B�ݒ���Ώۂ�����
            if (battle_config.agi_penaly_type == 1) //��𗦂�agi_penaly_num%���Œ���
                flee =
                    (flee *
                     (100 -
                      (target_count -
                       (battle_config.agi_penaly_count -
                        1)) * battle_config.agi_penaly_num)) / 100;
            else if (battle_config.agi_penaly_type == 2)    //��𗦂�agi_penaly_num������
                flee -=
                    (target_count -
                     (battle_config.agi_penaly_count -
                      1)) * battle_config.agi_penaly_num;
            if (flee < 1)
                flee = 1;       //��𗦂͍Œ�ł�1
        }
    }
    hitrate = battle_get_hit (src) - flee + 80; //�������v�Z

    {                           // [fate] Reduce hit chance by distance
        int  dx = abs (src->x - target->x);
        int  dy = abs (src->y - target->y);
        int  malus_dist;

        target_distance = MAX (dx, dy);
        malus_dist =
            MAX (0, target_distance - (skill_power (sd, AC_OWL) / 75));
        hitrate -= (malus_dist * (malus_dist + 1));
    }

    dex = battle_get_dex (src); //DEX
    luk = battle_get_luk (src); //LUK
    watk = battle_get_atk (src);    //ATK
    watk_ = battle_get_atk_ (src);  //ATK����

    type = 0;                   // normal
    div_ = 1;                   // single attack

    if (skill_num == HW_MAGICCRASHER)
    {                           /* �}�W�b�N�N���b�V���[��MATK�ʼn��� */
        damage = damage2 = battle_get_matk1 (src);  //damega,damega2���o��Abase_atk�̎擾
    }
    else
    {
        damage = damage2 = battle_get_baseatk (&sd->bl);    //damega,damega2���o��Abase_atk�̎擾
    }
    if (sd->attackrange > 2)
    {                           // [fate] ranged weapon?
        const int range_damage_bonus = 80;  // up to 31.25% bonus for long-range hit
        damage =
            damage * (256 +
                      ((range_damage_bonus * target_distance) /
                       sd->attackrange)) >> 8;
        damage2 =
            damage2 * (256 +
                       ((range_damage_bonus * target_distance) /
                        sd->attackrange)) >> 8;
    }

    atkmin = atkmin_ = dex;     //�Œ�ATK��DEX�ŏ������H
    sd->state.arrow_atk = 0;    //arrow_atk������
    if (sd->equip_index[9] >= 0 && sd->inventory_data[sd->equip_index[9]])
        atkmin =
            atkmin * (80 +
                      sd->inventory_data[sd->equip_index[9]]->wlv * 20) / 100;
    if (sd->equip_index[8] >= 0 && sd->inventory_data[sd->equip_index[8]])
        atkmin_ =
            atkmin_ * (80 +
                       sd->inventory_data[sd->equip_index[8]]->wlv * 20) /
            100;
    if (sd->status.weapon == 11)
    {                           //���킪�|��̏ꍇ
        atkmin = watk * ((atkmin < watk) ? atkmin : watk) / 100;    //�|�p�Œ�ATK�v�Z
        flag = (flag & ~BF_RANGEMASK) | BF_LONG;    //�������U���t���O��L��
        if (sd->arrow_ele > 0)  //������Ȃ瑮�����̑����ɕύX
            s_ele = sd->arrow_ele;
        sd->state.arrow_atk = 1;    //arrow_atk�L����
    }

    // �T�C�Y�C��
    // �y�R�R�悵�Ă��āA���ōU�������ꍇ�͒��^�̃T�C�Y�C����100�ɂ���
    // �E�F�|���p�[�t�F�N�V����,�h���C�NC
    if (((sd->special_state.no_sizefix)
         || (pc_isriding (sd)
             && (sd->status.weapon == 4 || sd->status.weapon == 5)
             && t_size == 1) || skill_num == MO_EXTREMITYFIST))
    {                           //�y�R�R�悵�Ă��āA���Œ��^���U��
        atkmax = watk;
        atkmax_ = watk_;
    }
    else
    {
        atkmax = (watk * sd->atkmods[t_size]) / 100;
        atkmin = (atkmin * sd->atkmods[t_size]) / 100;
        atkmax_ = (watk_ * sd->atkmods_[t_size]) / 100;
        atkmin_ = (atkmin_ * sd->atkmods[t_size]) / 100;
    }
    if ((sc_data != NULL && sc_data[SC_WEAPONPERFECTION].timer != -1)
        || (sd->special_state.no_sizefix))
    {                           // �E�F�|���p�[�t�F�N�V���� || �h���C�N�J�[�h
        atkmax = watk;
        atkmax_ = watk_;
    }

    if (atkmin > atkmax && !(sd->state.arrow_atk))
        atkmin = atkmax;        //�|�͍ŒႪ����ꍇ����
    if (atkmin_ > atkmax_)
        atkmin_ = atkmax_;

    if (sc_data != NULL && sc_data[SC_MAXIMIZEPOWER].timer != -1)
    {                           // �}�L�V�}�C�Y�p���[
        atkmin = atkmax;
        atkmin_ = atkmax_;
    }

    //�_�u���A�^�b�N����
    if (sd->weapontype1 == 0x01)
    {
        if (skill_num == 0 && skill_lv >= 0
            && (skill = pc_checkskill (sd, TF_DOUBLE)) > 0)
            da = (MRAND (100) < (skill * 5)) ? 1 : 0;
    }

    //�O�i��
    if (skill_num == 0 && skill_lv >= 0
        && (skill = pc_checkskill (sd, MO_TRIPLEATTACK)) > 0
        && sd->status.weapon <= 16 && !sd->state.arrow_atk)
    {
        da = (MRAND (100) < (30 - skill)) ? 2 : 0;
    }

    if (sd->double_rate > 0 && da == 0 && skill_num == 0 && skill_lv >= 0)
        da = (MRAND (100) < sd->double_rate) ? 1 : 0;

    // �ߏ萸�B�{�[�i�X
    if (sd->overrefine > 0)
        damage += MPRAND (1, sd->overrefine);
    if (sd->overrefine_ > 0)
        damage2 += MPRAND (1, sd->overrefine_);

    if (da == 0)
    {                           //�_�u���A�^�b�N���������Ă��Ȃ�
        // �N���e�B�J���v�Z
        cri = battle_get_critical (src);

        if (sd->state.arrow_atk)
            cri += sd->arrow_cri;
        if (sd->status.weapon == 16)
            // �J�^�[���̏ꍇ�A�N���e�B�J����{��
            cri <<= 1;
        cri -= battle_get_luk (target) * 3;
        if (t_sc_data != NULL && t_sc_data[SC_SLEEP].timer != -1)   // �������̓N���e�B�J�����{��
            cri <<= 1;
        if (ac_flag)
            cri = 1000;

        if (skill_num == KN_AUTOCOUNTER)
        {
            if (!(battle_config.pc_auto_counter_type & 1))
                cri = 1000;
            else
                cri <<= 1;
        }

        if (skill_num == SN_SHARPSHOOTING && MRAND (100) < 50)
            cri = 1000;
    }

    if (tsd && tsd->critical_def)
        cri = cri * (100 - tsd->critical_def) / 100;

    if (da == 0 && (skill_num == 0 || skill_num == KN_AUTOCOUNTER || skill_num == SN_SHARPSHOOTING) && skill_lv >= 0 && //�_�u���A�^�b�N���������Ă��Ȃ�
        (MRAND (1000)) < cri)   // ����i�X�L���̏ꍇ�͖����j
    {
        damage += atkmax;
        damage2 += atkmax_;
        if (sd->atk_rate != 100)
        {
            damage = (damage * sd->atk_rate) / 100;
            damage2 = (damage2 * sd->atk_rate) / 100;
        }
        if (sd->state.arrow_atk)
            damage += sd->arrow_atk;
        type = 0x0a;

/*		if(def1 < 1000000) {
			if(sd->def_ratio_atk_ele & (1<<t_ele) || sd->def_ratio_atk_race & (1<<t_race)) {
				damage = (damage * (def1 + def2))/100;
				idef_flag = 1;
			}
			if(sd->def_ratio_atk_ele_ & (1<<t_ele) || sd->def_ratio_atk_race_ & (1<<t_race)) {
				damage2 = (damage2 * (def1 + def2))/100;
				idef_flag_ = 1;
			}
			if(t_mode & 0x20) {
				if(!idef_flag && sd->def_ratio_atk_race & (1<<10)) {
					damage = (damage * (def1 + def2))/100;
					idef_flag = 1;
				}
				if(!idef_flag_ && sd->def_ratio_atk_race_ & (1<<10)) {
					damage2 = (damage2 * (def1 + def2))/100;
					idef_flag_ = 1;
				}
			}
			else {
				if(!idef_flag && sd->def_ratio_atk_race & (1<<11)) {
					damage = (damage * (def1 + def2))/100;
					idef_flag = 1;
				}
				if(!idef_flag_ && sd->def_ratio_atk_race_ & (1<<11)) {
					damage2 = (damage2 * (def1 + def2))/100;
					idef_flag_ = 1;
				}
			}
		}*/
    }
    else
    {
        int  vitbonusmax;

        if (atkmax > atkmin)
            damage += atkmin + MRAND ((atkmax - atkmin + 1));
        else
            damage += atkmin;
        if (atkmax_ > atkmin_)
            damage2 += atkmin_ + MRAND ((atkmax_ - atkmin_ + 1));
        else
            damage2 += atkmin_;
        if (sd->atk_rate != 100)
        {
            damage = (damage * sd->atk_rate) / 100;
            damage2 = (damage2 * sd->atk_rate) / 100;
        }

        if (sd->state.arrow_atk)
        {
            if (sd->arrow_atk > 0)
                damage += MRAND ((sd->arrow_atk + 1));
            hitrate += sd->arrow_hit;
        }

        if (skill_num != MO_INVESTIGATE && def1 < 1000000)
        {
            if (sd->def_ratio_atk_ele & (1 << t_ele)
                || sd->def_ratio_atk_race & (1 << t_race))
            {
                damage = (damage * (def1 + def2)) / 100;
                idef_flag = 1;
            }
            if (sd->def_ratio_atk_ele_ & (1 << t_ele)
                || sd->def_ratio_atk_race_ & (1 << t_race))
            {
                damage2 = (damage2 * (def1 + def2)) / 100;
                idef_flag_ = 1;
            }
            if (t_mode & 0x20)
            {
                if (!idef_flag && sd->def_ratio_atk_race & (1 << 10))
                {
                    damage = (damage * (def1 + def2)) / 100;
                    idef_flag = 1;
                }
                if (!idef_flag_ && sd->def_ratio_atk_race_ & (1 << 10))
                {
                    damage2 = (damage2 * (def1 + def2)) / 100;
                    idef_flag_ = 1;
                }
            }
            else
            {
                if (!idef_flag && sd->def_ratio_atk_race & (1 << 11))
                {
                    damage = (damage * (def1 + def2)) / 100;
                    idef_flag = 1;
                }
                if (!idef_flag_ && sd->def_ratio_atk_race_ & (1 << 11))
                {
                    damage2 = (damage2 * (def1 + def2)) / 100;
                    idef_flag_ = 1;
                }
            }
        }

        // �X�L���C���P�i�U���͔{���n�j
        // �I�[�o�[�g���X�g(+5% �` +25%),���U���n�X�L���̏ꍇ�����ŕ␳
        // �o�b�V��,�}�O�i���u���C�N,
        // �{�[�����O�o�b�V��,�X�s�A�u�[������,�u�����f�B�b�V���X�s�A,�X�s�A�X�^�b�u,
        // ���}�[�i�C�g,�J�[�g���{�����[�V����
        // �_�u���X�g���C�t�B���O,�A���[�V�����[,�`���[�W�A���[,
        // �\�j�b�N�u���[
        if (sc_data)
        {                       //��Ԉُ풆�̃_���[�W�lj�
            if (sc_data[SC_OVERTHRUST].timer != -1)
            {                   // �I�[�o�[�g���X�g
                damage += damage * (5 * sc_data[SC_OVERTHRUST].val1) / 100;
                damage2 += damage2 * (5 * sc_data[SC_OVERTHRUST].val1) / 100;
            }
            if (sc_data[SC_TRUESIGHT].timer != -1)
            {                   // �g�D���[�T�C�g
                damage += damage * (2 * sc_data[SC_TRUESIGHT].val1) / 100;
                damage2 += damage2 * (2 * sc_data[SC_TRUESIGHT].val1) / 100;
            }
            if (sc_data[SC_BERSERK].timer != -1)
            {                   // �o�[�T�[�N
                damage += damage * 50 / 100;
                damage2 += damage2 * 50 / 100;
            }
        }

        if (skill_num > 0)
        {
            int  i;
            if ((i = skill_get_pl (skill_num)) > 0)
                s_ele = s_ele_ = i;

            flag = (flag & ~BF_SKILLMASK) | BF_SKILL;
            switch (skill_num)
            {
                case SM_BASH:  // �o�b�V��
                    damage = damage * (100 + 30 * skill_lv) / 100;
                    damage2 = damage2 * (100 + 30 * skill_lv) / 100;
                    hitrate = (hitrate * (100 + 5 * skill_lv)) / 100;
                    break;
                case SM_MAGNUM:    // �}�O�i���u���C�N
                    damage =
                        damage * (5 * skill_lv + (wflag) ? 65 : 115) / 100;
                    damage2 =
                        damage2 * (5 * skill_lv + (wflag) ? 65 : 115) / 100;
                    break;
                case MC_MAMMONITE: // ���}�[�i�C�g
                    damage = damage * (100 + 50 * skill_lv) / 100;
                    damage2 = damage2 * (100 + 50 * skill_lv) / 100;
                    break;
                case AC_DOUBLE:    // �_�u���X�g���C�t�B���O
                    if (!sd->state.arrow_atk && sd->arrow_atk > 0)
                    {
                        int  arr = MRAND ((sd->arrow_atk + 1));
                        damage += arr;
                        damage2 += arr;
                    }
                    damage = damage * (180 + 20 * skill_lv) / 100;
                    damage2 = damage2 * (180 + 20 * skill_lv) / 100;
                    div_ = 2;
                    if (sd->arrow_ele > 0)
                    {
                        s_ele = sd->arrow_ele;
                        s_ele_ = sd->arrow_ele;
                    }
                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
                    sd->state.arrow_atk = 1;
                    break;
                case AC_SHOWER:    // �A���[�V�����[
                    if (!sd->state.arrow_atk && sd->arrow_atk > 0)
                    {
                        int  arr = MRAND ((sd->arrow_atk + 1));
                        damage += arr;
                        damage2 += arr;
                    }
                    damage = damage * (75 + 5 * skill_lv) / 100;
                    damage2 = damage2 * (75 + 5 * skill_lv) / 100;
                    if (sd->arrow_ele > 0)
                    {
                        s_ele = sd->arrow_ele;
                        s_ele_ = sd->arrow_ele;
                    }
                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
                    sd->state.arrow_atk = 1;
                    break;
                case AC_CHARGEARROW:   // �`���[�W�A���[
                    if (!sd->state.arrow_atk && sd->arrow_atk > 0)
                    {
                        int  arr = MRAND ((sd->arrow_atk + 1));
                        damage += arr;
                        damage2 += arr;
                    }
                    damage = damage * 150 / 100;
                    damage2 = damage2 * 150 / 100;
                    if (sd->arrow_ele > 0)
                    {
                        s_ele = sd->arrow_ele;
                        s_ele_ = sd->arrow_ele;
                    }
                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
                    sd->state.arrow_atk = 1;
                    break;
                case KN_PIERCE:    // �s�A�[�X
                    damage = damage * (100 + 10 * skill_lv) / 100;
                    damage2 = damage2 * (100 + 10 * skill_lv) / 100;
                    hitrate = hitrate * (100 + 5 * skill_lv) / 100;
                    div_ = t_size + 1;
                    damage *= div_;
                    damage2 *= div_;
                    break;
                case KN_SPEARSTAB: // �X�s�A�X�^�u
                    damage = damage * (100 + 15 * skill_lv) / 100;
                    damage2 = damage2 * (100 + 15 * skill_lv) / 100;
                    break;
                case KN_SPEARBOOMERANG:    // �X�s�A�u�[������
                    damage = damage * (100 + 50 * skill_lv) / 100;
                    damage2 = damage2 * (100 + 50 * skill_lv) / 100;
                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
                    break;
                case KN_BRANDISHSPEAR: // �u�����f�B�b�V���X�s�A
                    damage = damage * (100 + 20 * skill_lv) / 100;
                    damage2 = damage2 * (100 + 20 * skill_lv) / 100;
                    if (skill_lv > 3 && wflag == 1)
                        damage3 += damage / 2;
                    if (skill_lv > 6 && wflag == 1)
                        damage3 += damage / 4;
                    if (skill_lv > 9 && wflag == 1)
                        damage3 += damage / 8;
                    if (skill_lv > 6 && wflag == 2)
                        damage3 += damage / 2;
                    if (skill_lv > 9 && wflag == 2)
                        damage3 += damage / 4;
                    if (skill_lv > 9 && wflag == 3)
                        damage3 += damage / 2;
                    damage += damage3;
                    if (skill_lv > 3 && wflag == 1)
                        damage4 += damage2 / 2;
                    if (skill_lv > 6 && wflag == 1)
                        damage4 += damage2 / 4;
                    if (skill_lv > 9 && wflag == 1)
                        damage4 += damage2 / 8;
                    if (skill_lv > 6 && wflag == 2)
                        damage4 += damage2 / 2;
                    if (skill_lv > 9 && wflag == 2)
                        damage4 += damage2 / 4;
                    if (skill_lv > 9 && wflag == 3)
                        damage4 += damage2 / 2;
                    damage2 += damage4;
                    blewcount = 0;
                    break;
                case KN_BOWLINGBASH:   // �{�E�����O�o�b�V��
                    damage = damage * (100 + 50 * skill_lv) / 100;
                    damage2 = damage2 * (100 + 50 * skill_lv) / 100;
                    blewcount = 0;
                    break;
                case KN_AUTOCOUNTER:
                    if (battle_config.pc_auto_counter_type & 1)
                        hitrate += 20;
                    else
                        hitrate = 1000000;
                    flag = (flag & ~BF_SKILLMASK) | BF_NORMAL;
                    break;
                case AS_SONICBLOW: // �\�j�b�N�u���E
                    hitrate += 30;  // hitrate +30, thanks to midas
                    damage = damage * (300 + 50 * skill_lv) / 100;
                    damage2 = damage2 * (300 + 50 * skill_lv) / 100;
                    div_ = 8;
                    break;
                case TF_SPRINKLESAND:  // ���܂�
                    damage = damage * 125 / 100;
                    damage2 = damage2 * 125 / 100;
                    break;
                case MC_CARTREVOLUTION:    // �J�[�g���{�����[�V����
                    if (sd->cart_max_weight > 0 && sd->cart_weight > 0)
                    {
                        damage =
                            (damage *
                             (150 + pc_checkskill (sd, BS_WEAPONRESEARCH) +
                              (sd->cart_weight * 100 /
                               sd->cart_max_weight))) / 100;
                        damage2 =
                            (damage2 *
                             (150 + pc_checkskill (sd, BS_WEAPONRESEARCH) +
                              (sd->cart_weight * 100 /
                               sd->cart_max_weight))) / 100;
                    }
                    else
                    {
                        damage = (damage * 150) / 100;
                        damage2 = (damage2 * 150) / 100;
                    }
                    break;
                    // �ȉ�MOB
                case NPC_COMBOATTACK:  // ���i�U��
                    div_ = skill_get_num (skill_num, skill_lv);
                    damage *= div_;
                    damage2 *= div_;
                    break;
                case NPC_RANDOMATTACK: // �����_��ATK�U��
                    damage = damage * (MPRAND (50, 150)) / 100;
                    damage2 = damage2 * (MPRAND (50, 150)) / 100;
                    break;
                    // �����U���i�K���j
                case NPC_WATERATTACK:
                case NPC_GROUNDATTACK:
                case NPC_FIREATTACK:
                case NPC_WINDATTACK:
                case NPC_POISONATTACK:
                case NPC_HOLYATTACK:
                case NPC_DARKNESSATTACK:
                case NPC_TELEKINESISATTACK:
                    damage = damage * (100 + 25 * skill_lv) / 100;
                    damage2 = damage2 * (100 + 25 * skill_lv) / 100;
                    break;
                case NPC_GUIDEDATTACK:
                    hitrate = 1000000;
                    break;
                case NPC_RANGEATTACK:
                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
                    break;
                case NPC_PIERCINGATT:
                    flag = (flag & ~BF_RANGEMASK) | BF_SHORT;
                    break;
                case RG_BACKSTAP:  // �o�b�N�X�^�u
                    if (battle_config.backstab_bow_penalty == 1
                        && sd->status.weapon == 11)
                    {
                        damage = (damage * (300 + 40 * skill_lv) / 100) / 2;
                        damage2 = (damage2 * (300 + 40 * skill_lv) / 100) / 2;
                    }
                    else
                    {
                        damage = damage * (300 + 40 * skill_lv) / 100;
                        damage2 = damage2 * (300 + 40 * skill_lv) / 100;
                    }
                    hitrate = 1000000;
                    break;
                case RG_RAID:  // �T�v���C�Y�A�^�b�N
                    damage = damage * (100 + 40 * skill_lv) / 100;
                    damage2 = damage2 * (100 + 40 * skill_lv) / 100;
                    break;
                case RG_INTIMIDATE:    // �C���e�B�~�f�C�g
                    damage = damage * (100 + 30 * skill_lv) / 100;
                    damage2 = damage2 * (100 + 30 * skill_lv) / 100;
                    break;
                case CR_SHIELDCHARGE:  // �V�[���h�`���[�W
                    damage = damage * (100 + 20 * skill_lv) / 100;
                    damage2 = damage2 * (100 + 20 * skill_lv) / 100;
                    flag = (flag & ~BF_RANGEMASK) | BF_SHORT;
                    s_ele = 0;
                    break;
                case CR_SHIELDBOOMERANG:   // �V�[���h�u�[������
                    damage = damage * (100 + 30 * skill_lv) / 100;
                    damage2 = damage2 * (100 + 30 * skill_lv) / 100;
                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
                    s_ele = 0;
                    break;
                case CR_HOLYCROSS: // �z�[���[�N���X
                    damage = damage * (100 + 35 * skill_lv) / 100;
                    damage2 = damage2 * (100 + 35 * skill_lv) / 100;
                    div_ = 2;
                    break;
                case CR_GRANDCROSS:
                    hitrate = 1000000;
                    break;
                case AM_DEMONSTRATION: // �f�����X�g���[�V����
                    damage = damage * (100 + 20 * skill_lv) / 100;
                    damage2 = damage2 * (100 + 20 * skill_lv) / 100;
                    break;
                case AM_ACIDTERROR:    // �A�V�b�h�e���[
                    damage = damage * (100 + 40 * skill_lv) / 100;
                    damage2 = damage2 * (100 + 40 * skill_lv) / 100;
                    break;
                case MO_FINGEROFFENSIVE:   //�w�e
                    if (battle_config.finger_offensive_type == 0)
                    {
                        damage =
                            damage * (100 +
                                      50 * skill_lv) / 100 *
                            sd->spiritball_old;
                        damage2 =
                            damage2 * (100 +
                                       50 * skill_lv) / 100 *
                            sd->spiritball_old;
                        div_ = sd->spiritball_old;
                    }
                    else
                    {
                        damage = damage * (100 + 50 * skill_lv) / 100;
                        damage2 = damage2 * (100 + 50 * skill_lv) / 100;
                        div_ = 1;
                    }
                    break;
                case MO_INVESTIGATE:   // �� ��
                    if (def1 < 1000000)
                    {
                        damage =
                            damage * (100 + 75 * skill_lv) / 100 * (def1 +
                                                                    def2) /
                            100;
                        damage2 =
                            damage2 * (100 + 75 * skill_lv) / 100 * (def1 +
                                                                     def2) /
                            100;
                    }
                    hitrate = 1000000;
                    s_ele = 0;
                    s_ele_ = 0;
                    break;
                case MO_EXTREMITYFIST: // ���C���e�P��
                    damage =
                        damage * (8 + ((sd->status.sp) / 10)) + 250 +
                        (skill_lv * 150);
                    damage2 =
                        damage2 * (8 + ((sd->status.sp) / 10)) + 250 +
                        (skill_lv * 150);
                    sd->status.sp = 0;
                    clif_updatestatus (sd, SP_SP);
                    hitrate = 1000000;
                    s_ele = 0;
                    s_ele_ = 0;
                    break;
                case MO_CHAINCOMBO:    // �A�ŏ�
                    damage = damage * (150 + 50 * skill_lv) / 100;
                    damage2 = damage2 * (150 + 50 * skill_lv) / 100;
                    div_ = 4;
                    break;
                case MO_COMBOFINISH:   // �җ���
                    damage = damage * (240 + 60 * skill_lv) / 100;
                    damage2 = damage2 * (240 + 60 * skill_lv) / 100;
                    break;
                case BA_MUSICALSTRIKE: // �~���[�W�J���X�g���C�N
                    if (!sd->state.arrow_atk && sd->arrow_atk > 0)
                    {
                        int  arr = MRAND ((sd->arrow_atk + 1));
                        damage += arr;
                        damage2 += arr;
                    }
                    damage = damage * (100 + 50 * skill_lv) / 100;
                    damage2 = damage2 * (100 + 50 * skill_lv) / 100;
                    if (sd->arrow_ele > 0)
                    {
                        s_ele = sd->arrow_ele;
                        s_ele_ = sd->arrow_ele;
                    }
                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
                    sd->state.arrow_atk = 1;
                    break;
                case DC_THROWARROW:    // ���
                    if (!sd->state.arrow_atk && sd->arrow_atk > 0)
                    {
                        int  arr = MRAND ((sd->arrow_atk + 1));
                        damage += arr;
                        damage2 += arr;
                    }
                    damage = damage * (100 + 50 * skill_lv) / 100;
                    damage2 = damage2 * (100 + 50 * skill_lv) / 100;
                    if (sd->arrow_ele > 0)
                    {
                        s_ele = sd->arrow_ele;
                        s_ele_ = sd->arrow_ele;
                    }
                    flag = (flag & ~BF_RANGEMASK) | BF_LONG;
                    sd->state.arrow_atk = 1;
                    break;
                case CH_TIGERFIST: // ���Ռ�
                    damage = damage * (100 + 20 * skill_lv) / 100;
                    damage2 = damage2 * (100 + 20 * skill_lv) / 100;
                    break;
                case CH_CHAINCRUSH:    // �A������
                    damage = damage * (100 + 20 * skill_lv) / 100;
                    damage2 = damage2 * (100 + 20 * skill_lv) / 100;
                    div_ = skill_get_num (skill_num, skill_lv);
                    break;
                case CH_PALMSTRIKE:    // �ҌՍd�h�R
                    damage = damage * (50 + 100 * skill_lv) / 100;
                    damage2 = damage2 * (50 + 100 * skill_lv) / 100;
                    break;
                case LK_SPIRALPIERCE:  /* �X�p�C�����s�A�[�X */
                    damage = damage * (100 + 50 * skill_lv) / 100;  //�����ʂ�������Ȃ��̂œK����
                    damage2 = damage2 * (100 + 50 * skill_lv) / 100;    //�����ʂ�������Ȃ��̂œK����
                    div_ = 5;
                    if (tsd)
                        tsd->canmove_tick = gettick () + 1000;
                    else if (tmd)
                        tmd->canmove_tick = gettick () + 1000;
                    break;
                case LK_HEADCRUSH: /* �w�b�h�N���b�V�� */
                    damage = damage * (100 + 20 * skill_lv) / 100;
                    damage2 = damage2 * (100 + 20 * skill_lv) / 100;
                    break;
                case LK_JOINTBEAT: /* �W���C���g�r�[�g */
                    damage = damage * (50 + 10 * skill_lv) / 100;
                    damage2 = damage2 * (50 + 10 * skill_lv) / 100;
                    break;
                case ASC_METEORASSAULT:    /* ���e�I�A�T���g */
                    damage = damage * (40 + 40 * skill_lv) / 100;
                    damage2 = damage2 * (40 + 40 * skill_lv) / 100;
                    break;
                case SN_SHARPSHOOTING: /* �V���[�v�V���[�e�B���O */
                    damage += damage * (30 * skill_lv) / 100;
                    damage2 += damage2 * (30 * skill_lv) / 100;
                    break;
                case CG_ARROWVULCAN:   /* �A���[�o���J�� */
                    damage = damage * (160 + 40 * skill_lv) / 100;
                    damage2 = damage2 * (160 + 40 * skill_lv) / 100;
                    div_ = 9;
                    break;
                case AS_SPLASHER:  /* �x�i���X�v���b�V���[ */
                    damage =
                        damage * (200 + 20 * skill_lv +
                                  20 * pc_checkskill (sd,
                                                      AS_POISONREACT)) / 100;
                    damage2 =
                        damage2 * (200 + 20 * skill_lv +
                                   20 * pc_checkskill (sd,
                                                       AS_POISONREACT)) / 100;
                    break;
                case PA_SACRIFICE:
                    if (sd)
                    {
                        int  hp, mhp, damage3;
                        hp = battle_get_hp (src);
                        mhp = battle_get_max_hp (src);
                        damage3 = mhp * ((skill_lv / 2) + (50 / 100)) / 100;
                        damage =
                            (((skill_lv * 15) + 90) / 100) * damage3 / 100;
                        damage2 =
                            (((skill_lv * 15) + 90) / 100) * damage3 / 100;
                    }
                    break;
                case ASC_BREAKER:  // -- moonsoul (special damage for ASC_BREAKER skill)
                    if (sd)
                    {
                        int  damage3;
                        int  mdef1 = battle_get_mdef (target);
                        int  mdef2 = battle_get_mdef2 (target);
                        int  imdef_flag = 0;

                        damage =
                            ((damage * 5) +
                             (skill_lv * battle_get_int (src) * 5) +
                             MRAND (500) + 500) / 2;
                        damage2 =
                            ((damage2 * 5) +
                             (skill_lv * battle_get_int (src) * 5) +
                             MRAND (500) + 500) / 2;
                        damage3 = damage;
                        hitrate = 1000000;

                        if (sd->ignore_mdef_ele & (1 << t_ele)
                            || sd->ignore_mdef_race & (1 << t_race))
                            imdef_flag = 1;
                        if (t_mode & 0x20)
                        {
                            if (sd->ignore_mdef_race & (1 << 10))
                                imdef_flag = 1;
                        }
                        else
                        {
                            if (sd->ignore_mdef_race & (1 << 11))
                                imdef_flag = 1;
                        }
                        if (!imdef_flag)
                        {
                            if (battle_config.magic_defense_type)
                            {
                                damage3 =
                                    damage3 -
                                    (mdef1 *
                                     battle_config.magic_defense_type) -
                                    mdef2;
                            }
                            else
                            {
                                damage3 =
                                    (damage3 * (100 - mdef1)) / 100 - mdef2;
                            }
                        }

                        if (damage3 < 1)
                            damage3 = 1;

                        damage3 =
                            battle_attr_fix (damage2, s_ele_,
                                             battle_get_element (target));
                    }
                    break;
            }
        }
        if (da == 2)
        {                       //�O�i�����������Ă��邩
            type = 0x08;
            div_ = 255;         //�O�i���p�Ɂc
            damage =
                damage * (100 +
                          20 * pc_checkskill (sd, MO_TRIPLEATTACK)) / 100;
        }

        if (skill_num != NPC_CRITICALSLASH)
        {
            // �� �ۂ̖h��͂ɂ��_���[�W�̌���
            // �f�B�o�C���v���e�N�V�����i�����ł����̂��ȁH�j
            if (skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST
                && skill_num != KN_AUTOCOUNTER && def1 < 1000000)
            {                   //DEF, VIT����
                int  t_def;
                target_count =
                    1 + battle_counttargeted (target, src,
                                              battle_config.vit_penaly_count_lv);
                if (battle_config.vit_penaly_type > 0)
                {
                    if (target_count >= battle_config.vit_penaly_count)
                    {
                        if (battle_config.vit_penaly_type == 1)
                        {
                            def1 =
                                (def1 *
                                 (100 -
                                  (target_count -
                                   (battle_config.vit_penaly_count -
                                    1)) * battle_config.vit_penaly_num)) /
                                100;
                            def2 =
                                (def2 *
                                 (100 -
                                  (target_count -
                                   (battle_config.vit_penaly_count -
                                    1)) * battle_config.vit_penaly_num)) /
                                100;
                            t_vit =
                                (t_vit *
                                 (100 -
                                  (target_count -
                                   (battle_config.vit_penaly_count -
                                    1)) * battle_config.vit_penaly_num)) /
                                100;
                        }
                        else if (battle_config.vit_penaly_type == 2)
                        {
                            def1 -=
                                (target_count -
                                 (battle_config.vit_penaly_count -
                                  1)) * battle_config.vit_penaly_num;
                            def2 -=
                                (target_count -
                                 (battle_config.vit_penaly_count -
                                  1)) * battle_config.vit_penaly_num;
                            t_vit -=
                                (target_count -
                                 (battle_config.vit_penaly_count -
                                  1)) * battle_config.vit_penaly_num;
                        }
                        if (def1 < 0)
                            def1 = 0;
                        if (def2 < 1)
                            def2 = 1;
                        if (t_vit < 1)
                            t_vit = 1;
                    }
                }
                t_def = def2 * 8 / 10;
                vitbonusmax = (t_vit / 20) * (t_vit / 20) - 1;
                if (sd->ignore_def_ele & (1 << t_ele)
                    || sd->ignore_def_race & (1 << t_race))
                    idef_flag = 1;
                if (sd->ignore_def_ele_ & (1 << t_ele)
                    || sd->ignore_def_race_ & (1 << t_race))
                    idef_flag_ = 1;
                if (t_mode & 0x20)
                {
                    if (sd->ignore_def_race & (1 << 10))
                        idef_flag = 1;
                    if (sd->ignore_def_race_ & (1 << 10))
                        idef_flag_ = 1;
                }
                else
                {
                    if (sd->ignore_def_race & (1 << 11))
                        idef_flag = 1;
                    if (sd->ignore_def_race_ & (1 << 11))
                        idef_flag_ = 1;
                }

                if (!idef_flag)
                {
                    if (battle_config.player_defense_type)
                    {
                        damage =
                            damage -
                            (def1 * battle_config.player_defense_type) -
                            t_def -
                            ((vitbonusmax <
                              1) ? 0 : MRAND ((vitbonusmax + 1)));
                    }
                    else
                    {
                        damage =
                            damage * (100 - def1) / 100 - t_def -
                            ((vitbonusmax <
                              1) ? 0 : MRAND ((vitbonusmax + 1)));
                    }
                }
                if (!idef_flag_)
                {
                    if (battle_config.player_defense_type)
                    {
                        damage2 =
                            damage2 -
                            (def1 * battle_config.player_defense_type) -
                            t_def -
                            ((vitbonusmax <
                              1) ? 0 : MRAND ((vitbonusmax + 1)));
                    }
                    else
                    {
                        damage2 =
                            damage2 * (100 - def1) / 100 - t_def -
                            ((vitbonusmax <
                              1) ? 0 : MRAND ((vitbonusmax + 1)));
                    }
                }
            }
        }
    }
    // ���B�_���[�W�̒lj�
    if (skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST)
    {                           //DEF, VIT����
        damage += battle_get_atk2 (src);
        damage2 += battle_get_atk_2 (src);
    }
    if (skill_num == CR_SHIELDBOOMERANG)
    {
        if (sd->equip_index[8] >= 0)
        {
            int  index = sd->equip_index[8];
            if (sd->inventory_data[index]
                && sd->inventory_data[index]->type == 5)
            {
                damage += sd->inventory_data[index]->weight / 10;
                damage +=
                    sd->status.inventory[index].refine * pc_getrefinebonus (0,
                                                                            1);
            }
        }
    }
    if (skill_num == LK_SPIRALPIERCE)
    {                           /* �X�p�C�����s�A�[�X */
        if (sd->equip_index[9] >= 0)
        {                       //�d�ʂŒlj��_���[�W�炵���̂ŃV�[���h�u�[���������Q�l�ɒlj�
            int  index = sd->equip_index[9];
            if (sd->inventory_data[index]
                && sd->inventory_data[index]->type == 4)
            {
                damage +=
                    (int) (double) (sd->inventory_data[index]->weight *
                                    (0.8 * skill_lv * 4 / 10));
                damage +=
                    sd->status.inventory[index].refine * pc_getrefinebonus (0,
                                                                            1);
            }
        }
    }

    // 0�����������ꍇ1�ɕ␳
    if (damage < 1)
        damage = 1;
    if (damage2 < 1)
        damage2 = 1;

    // �X�L���C���Q�i�C���n�j
    // �C���_���[�W(�E��̂�) �\�j�b�N�u���[���͕ʏ����i1���ɕt��1/8�K��)
    if (skill_num != MO_INVESTIGATE && skill_num != MO_EXTREMITYFIST
        && skill_num != CR_GRANDCROSS)
    {                           //�C���_���[�W����
        damage = battle_addmastery (sd, target, damage, 0);
        damage2 = battle_addmastery (sd, target, damage2, 1);
    }

    if (sd->perfect_hit > 0)
    {
        if (MRAND (100) < sd->perfect_hit)
            hitrate = 1000000;
    }

    // ����C��
    hitrate = (hitrate < 5) ? 5 : hitrate;
    if (hitrate < 1000000 &&    // �K���U��
        (t_sc_data != NULL && (t_sc_data[SC_SLEEP].timer != -1 ||   // �����͕K��
                               t_sc_data[SC_STAN].timer != -1 ||    // �X�^���͕K��
                               t_sc_data[SC_FREEZE].timer != -1 || (t_sc_data[SC_STONE].timer != -1 && t_sc_data[SC_STONE].val2 == 0))))    // �����͕K��
        hitrate = 1000000;
    if (type == 0 && MRAND (100) >= hitrate)
    {
        damage = damage2 = 0;
        dmg_lv = ATK_FLEE;
    }
    else
    {
        dmg_lv = ATK_DEF;
    }
    // �X�L���C���R�i���팤���j
    if ((skill = pc_checkskill (sd, BS_WEAPONRESEARCH)) > 0)
    {
        damage += skill * 2;
        damage2 += skill * 2;
    }
    //Advanced Katar Research by zanetheinsane
    if (sd->weapontype1 == 0x10 || sd->weapontype2 == 0x10)
    {
        if ((skill = pc_checkskill (sd, ASC_KATAR)) > 0)
        {
            damage += (damage * ((skill * 2) + 10)) / 100;
        }
    }

//�X�L���ɂ��_���[�W�␳�����܂�

//�J�[�h�ɂ��_���[�W�lj�������������
    cardfix = 100;
    if (!sd->state.arrow_atk)
    {                           //�|��ȊO
        if (!battle_config.left_cardfix_to_right)
        {                       //����J�[�h�␳�ݒ薳��
            cardfix = cardfix * (100 + sd->addrace[t_race]) / 100;  // �푰�ɂ��_���[�W�C��
            cardfix = cardfix * (100 + sd->addele[t_ele]) / 100;    // �����ɂ��_���[�W�C��
            cardfix = cardfix * (100 + sd->addsize[t_size]) / 100;  // �T�C�Y�ɂ��_���[�W�C��
        }
        else
        {
            cardfix = cardfix * (100 + sd->addrace[t_race] + sd->addrace_[t_race]) / 100;   // �푰�ɂ��_���[�W�C��(����ɂ��lj�����)
            cardfix = cardfix * (100 + sd->addele[t_ele] + sd->addele_[t_ele]) / 100;   // �����ɂ��_���[�W�C��(����ɂ��lj�����)
            cardfix = cardfix * (100 + sd->addsize[t_size] + sd->addsize_[t_size]) / 100;   // �T�C�Y�ɂ��_���[�W�C��(����ɂ��lj�����)
        }
    }
    else
    {                           //�|��
        cardfix = cardfix * (100 + sd->addrace[t_race] + sd->arrow_addrace[t_race]) / 100;  // �푰�ɂ��_���[�W�C��(�|��ɂ��lj�����)
        cardfix = cardfix * (100 + sd->addele[t_ele] + sd->arrow_addele[t_ele]) / 100;  // �����ɂ��_���[�W�C��(�|��ɂ��lj�����)
        cardfix = cardfix * (100 + sd->addsize[t_size] + sd->arrow_addsize[t_size]) / 100;  // �T�C�Y�ɂ��_���[�W�C��(�|��ɂ��lj�����)
    }
    if (t_mode & 0x20)
    {                           //�{�X
        if (!sd->state.arrow_atk)
        {                       //�|��U���ȊO�Ȃ�
            if (!battle_config.left_cardfix_to_right)   //����J�[�h�␳�ݒ薳��
                cardfix = cardfix * (100 + sd->addrace[10]) / 100;  //�{�X�����X�^�[�ɒlj��_���[�W
            else                //����J�[�h�␳�ݒ肠��
                cardfix = cardfix * (100 + sd->addrace[10] + sd->addrace_[10]) / 100;   //�{�X�����X�^�[�ɒlj��_���[�W(����ɂ��lj�����)
        }
        else                    //�|��U��
            cardfix = cardfix * (100 + sd->addrace[10] + sd->arrow_addrace[10]) / 100;  //�{�X�����X�^�[�ɒlj��_���[�W(�|��ɂ��lj�����)
    }
    else
    {                           //�{�X����Ȃ�
        if (!sd->state.arrow_atk)
        {                       //�|��U���ȊO
            if (!battle_config.left_cardfix_to_right)   //����J�[�h�␳�ݒ薳��
                cardfix = cardfix * (100 + sd->addrace[11]) / 100;  //�{�X�ȊO�����X�^�[�ɒlj��_���[�W
            else                //����J�[�h�␳�ݒ肠��
                cardfix = cardfix * (100 + sd->addrace[11] + sd->addrace_[11]) / 100;   //�{�X�ȊO�����X�^�[�ɒlj��_���[�W(����ɂ��lj�����)
        }
        else
            cardfix = cardfix * (100 + sd->addrace[11] + sd->arrow_addrace[11]) / 100;  //�{�X�ȊO�����X�^�[�ɒlj��_���[�W(�|��ɂ��lj�����)
    }
    //����Class�p�␳����(�����̓��L���{���S���p�H)
    t_class = battle_get_class (target);
    for (i = 0; i < sd->add_damage_class_count; i++)
    {
        if (sd->add_damage_classid[i] == t_class)
        {
            cardfix = cardfix * (100 + sd->add_damage_classrate[i]) / 100;
            break;
        }
    }
    if (skill_num != CR_GRANDCROSS || !battle_config.gx_cardfix)
        damage = damage * cardfix / 100;    //�J�[�h�␳�ɂ��_���[�W����
//�J�[�h�ɂ��_���[�W�������������܂�

//�J�[�h�ɂ��_���[�W�lj�����(����)��������
    cardfix = 100;
    if (!battle_config.left_cardfix_to_right)
    {                           //����J�[�h�␳�ݒ薳��
        cardfix = cardfix * (100 + sd->addrace_[t_race]) / 100; // �푰�ɂ��_���[�W�C������
        cardfix = cardfix * (100 + sd->addele_[t_ele]) / 100;   // �� ���ɂ��_���[�W�C������
        cardfix = cardfix * (100 + sd->addsize_[t_size]) / 100; // �T�C�Y�ɂ��_���[�W�C������
        if (t_mode & 0x20)      //�{�X
            cardfix = cardfix * (100 + sd->addrace_[10]) / 100; //�{�X�����X�^�[�ɒlj��_���[�W����
        else
            cardfix = cardfix * (100 + sd->addrace_[11]) / 100; //�{�X�ȊO�����X�^�[�ɒlj��_���[�W����
    }
    //����Class�p�␳��������(�����̓��L���{���S���p�H)
    for (i = 0; i < sd->add_damage_class_count_; i++)
    {
        if (sd->add_damage_classid_[i] == t_class)
        {
            cardfix = cardfix * (100 + sd->add_damage_classrate_[i]) / 100;
            break;
        }
    }
    if (skill_num != CR_GRANDCROSS)
        damage2 = damage2 * cardfix / 100;  //�J�[�h�␳�ɂ�鍶��_���[�W����
//�J�[�h�ɂ��_���[�W��������(����)�����܂�

// -- moonsoul (cardfix for magic damage portion of ASC_BREAKER)
    if (skill_num == ASC_BREAKER)
        damage3 = damage3 * cardfix / 100;

//�J�[�h�ɂ��_���[�W����������������
    if (tsd)
    {                           //�Ώۂ�PC�̏ꍇ
        cardfix = 100;
        cardfix = cardfix * (100 - tsd->subrace[s_race]) / 100; // �푰�ɂ��_���[�W�ϐ�
        cardfix = cardfix * (100 - tsd->subele[s_ele]) / 100;   // �����ɂ��_���[�W�ϐ�
        if (battle_get_mode (src) & 0x20)
            cardfix = cardfix * (100 - tsd->subrace[10]) / 100; //�{�X����̍U���̓_���[�W����
        else
            cardfix = cardfix * (100 - tsd->subrace[11]) / 100; //�{�X�ȊO����̍U���̓_���[�W����
        //����Class�p�␳��������(�����̓��L���{���S���p�H)
        for (i = 0; i < tsd->add_def_class_count; i++)
        {
            if (tsd->add_def_classid[i] == sd->status.class)
            {
                cardfix = cardfix * (100 - tsd->add_def_classrate[i]) / 100;
                break;
            }
        }
        if (flag & BF_LONG)
            cardfix = cardfix * (100 - tsd->long_attack_def_rate) / 100;    //�������U���̓_���[�W����(�z����C�Ƃ�)
        if (flag & BF_SHORT)
            cardfix = cardfix * (100 - tsd->near_attack_def_rate) / 100;    //�ߋ����U���̓_���[�W����(�Y�������H)
        damage = damage * cardfix / 100;    //�J�[�h�␳�ɂ��_���[�W����
        damage2 = damage2 * cardfix / 100;  //�J�[�h�␳�ɂ�鍶��_���[�W����
    }
//�J�[�h�ɂ��_���[�W�������������܂�

//�ΏۂɃX�e�[�^�X�ُ킪����ꍇ�̃_���[�W���Z������������
    if (t_sc_data)
    {
        cardfix = 100;
        if (t_sc_data[SC_DEFENDER].timer != -1 && flag & BF_LONG)   //�f�B�t�F���_�[��Ԃʼn������U��
            cardfix = cardfix * (100 - t_sc_data[SC_DEFENDER].val2) / 100;  //�f�B�t�F���_�[�ɂ�錸��
        if (cardfix != 100)
        {
            damage = damage * cardfix / 100;    //�f�B�t�F���_�[�␳�ɂ��_���[�W����
            damage2 = damage2 * cardfix / 100;  //�f�B�t�F���_�[�␳�ɂ�鍶��_���[�W����
        }
        if (t_sc_data[SC_ASSUMPTIO].timer != -1)
        {                       //�A�X���v�e�B�I
            if (!map[target->m].flag.pvp)
            {
                damage = damage / 3;
                damage2 = damage2 / 3;
            }
            else
            {
                damage = damage / 2;
                damage2 = damage2 / 2;
            }
        }
    }
//�ΏۂɃX�e�[�^�X�ُ킪����ꍇ�̃_���[�W���Z���������܂�

    if (damage < 0)
        damage = 0;
    if (damage2 < 0)
        damage2 = 0;

    // �� ���̓K�p
    damage = battle_attr_fix (damage, s_ele, battle_get_element (target));
    damage2 = battle_attr_fix (damage2, s_ele_, battle_get_element (target));

    // ���̂�����A�C���̓K�p
    damage += sd->star;
    damage2 += sd->star_;
    damage += sd->spiritball * 3;
    damage2 += sd->spiritball * 3;

    if (sc_data && sc_data[SC_AURABLADE].timer != -1)
    {                           /* �I�[���u���[�h �K�� */
        damage += sc_data[SC_AURABLADE].val1 * 10;
        damage2 += sc_data[SC_AURABLADE].val1 * 10;
    }
    if (skill_num == PA_PRESSURE)
    {                           /* �v���b�V���[ �K��? */
        damage = 700 + 100 * skill_lv;
        damage2 = 700 + 100 * skill_lv;
    }

    // >�񓁗��̍��E�_���[�W�v�Z�N������Ă��ꂥ�������������I
    // >map_session_data �ɍ���_���[�W(atk,atk2)�lj�����
    // >pc_calcstatus()�ł��ׂ����ȁH
    // map_session_data �ɍ��蕐��(atk,atk2,ele,star,atkmods)�lj�����
    // pc_calcstatus()�Ńf�[�^����͂��Ă��܂�

    //����̂ݕ��푕��
    if (sd->weapontype1 == 0 && sd->weapontype2 > 0)
    {
        damage = damage2;
        damage2 = 0;
    }
    // �E��A����C���̓K�p
    if (sd->status.weapon > 16)
    {                           // �񓁗���?
        int  dmg = damage, dmg2 = damage2;
        // �E��C��(60% �` 100%) �E��S��
        skill = pc_checkskill (sd, AS_RIGHT);
        damage = damage * (50 + (skill * 10)) / 100;
        if (dmg > 0 && damage < 1)
            damage = 1;
        // ����C��(40% �` 80%) ����S��
        skill = pc_checkskill (sd, AS_LEFT);
        damage2 = damage2 * (30 + (skill * 10)) / 100;
        if (dmg2 > 0 && damage2 < 1)
            damage2 = 1;
    }
    else                        //�񓁗��łȂ���΍���_���[�W��0
        damage2 = 0;

    // �E��,�Z���̂�
    if (da == 1)
    {                           //�_�u���A�^�b�N���������Ă��邩
        div_ = 2;
        damage += damage;
        type = 0x08;
    }

    if (sd->status.weapon == 16)
    {
        // �J�^�[���nj��_���[�W
        skill = pc_checkskill (sd, TF_DOUBLE);
        damage2 = damage * (1 + (skill * 2)) / 100;
        if (damage > 0 && damage2 < 1)
            damage2 = 1;
    }

    // �C���x�i���C��
    if (skill_num == TF_POISON)
    {
        damage =
            battle_attr_fix (damage + 15 * skill_lv, s_ele,
                             battle_get_element (target));
    }
    if (skill_num == MC_CARTREVOLUTION)
    {
        damage = battle_attr_fix (damage, 0, battle_get_element (target));
    }

    // ���S����̔���
    if (skill_num == 0 && skill_lv >= 0 && tsd != NULL && div_ < 255
        && MRAND (1000) < battle_get_flee2 (target))
    {
        damage = damage2 = 0;
        type = 0x0b;
        dmg_lv = ATK_LUCKY;
    }

    // �Ώۂ����S���������ݒ肪ON�Ȃ�
    if (battle_config.enemy_perfect_flee)
    {
        if (skill_num == 0 && skill_lv >= 0 && tmd != NULL && div_ < 255
            && MRAND (1000) < battle_get_flee2 (target))
        {
            damage = damage2 = 0;
            type = 0x0b;
            dmg_lv = ATK_LUCKY;
        }
    }

    //Mob��Mode�Ɋ拭�t���O�������Ă���Ƃ��̏���
    if (t_mode & 0x40)
    {
        if (damage > 0)
            damage = 1;
        if (damage2 > 0)
            damage2 = 1;
    }

    //bNoWeaponDamage(�ݒ�A�C�e�������H)�ŃO�����h�N���X����Ȃ��ꍇ�̓_���[�W��0
    if (tsd && tsd->special_state.no_weapon_damage
        && skill_num != CR_GRANDCROSS)
        damage = damage2 = 0;

    if (skill_num != CR_GRANDCROSS && (damage > 0 || damage2 > 0))
    {
        if (damage2 < 1)        // �_���[�W�ŏI�C��
            damage =
                battle_calc_damage (src, target, damage, div_, skill_num,
                                    skill_lv, flag);
        else if (damage < 1)    // �E�肪�~�X�H
            damage2 =
                battle_calc_damage (src, target, damage2, div_, skill_num,
                                    skill_lv, flag);
        else
        {                       // �� ��/�J�^�[���̏ꍇ�͂�����ƌv�Z��₱����
            int  d1 = damage + damage2, d2 = damage2;
            damage =
                battle_calc_damage (src, target, damage + damage2, div_,
                                    skill_num, skill_lv, flag);
            damage2 = (d2 * 100 / d1) * damage / 100;
            if (damage > 1 && damage2 < 1)
                damage2 = 1;
            damage -= damage2;
        }
    }

    /*              For executioner card [Valaris]              */
    if (src->type == BL_PC && sd->random_attack_increase_add > 0
        && sd->random_attack_increase_per > 0 && skill_num == 0)
    {
        if (MRAND (100) < sd->random_attack_increase_per)
        {
            if (damage > 0)
                damage *= sd->random_attack_increase_add / 100;
            if (damage2 > 0)
                damage2 *= sd->random_attack_increase_add / 100;
        }
    }
    /*                  End addition                    */

// -- moonsoul (final combination of phys, mag damage for ASC_BREAKER)
    if (skill_num == ASC_BREAKER)
    {
        damage += damage3;
        damage2 += damage3;
    }

    wd.damage = damage;
    wd.damage2 = damage2;
    wd.type = type;
    wd.div_ = div_;
    wd.amotion = battle_get_amotion (src);
    if (skill_num == KN_AUTOCOUNTER)
        wd.amotion >>= 1;
    wd.dmotion = battle_get_dmotion (target);
    wd.blewcount = blewcount;
    wd.flag = flag;
    wd.dmg_lv = dmg_lv;

    return wd;
}

/*==========================================
 * ����_���[�W�v�Z
 *------------------------------------------
 */
struct Damage battle_calc_weapon_attack (struct block_list *src,
                                         struct block_list *target,
                                         int skill_num, int skill_lv,
                                         int wflag)
{
    struct Damage wd;

    //return�O�̏���������̂ŏ��o�͕��̂ݕύX
    if (src == NULL || target == NULL)
    {
        nullpo_info (NLP_MARK);
        memset (&wd, 0, sizeof (wd));
        return wd;
    }

    else if (src->type == BL_PC)
        wd = battle_calc_pc_weapon_attack (src, target, skill_num, skill_lv, wflag);    // weapon breaking [Valaris]
    else if (src->type == BL_MOB)
        wd = battle_calc_mob_weapon_attack (src, target, skill_num, skill_lv,
                                            wflag);
    else
        memset (&wd, 0, sizeof (wd));

    if (battle_config.equipment_breaking && src->type == BL_PC
        && (wd.damage > 0 || wd.damage2 > 0))
    {
        struct map_session_data *sd = (struct map_session_data *) src;
        if (sd->status.weapon && sd->status.weapon != 11)
        {
            int  breakrate = 1;
            if (target->type == BL_PC && sd->sc_data[SC_MELTDOWN].timer != -1)
            {
                breakrate += 100 * sd->sc_data[SC_MELTDOWN].val1;
                if (MRAND (10000) <
                    breakrate * battle_config.equipment_break_rate / 100
                    || breakrate >= 10000)
                    pc_breakweapon ((struct map_session_data *) target);
            }
            if (sd->sc_data[SC_OVERTHRUST].timer != -1)
                breakrate += 20 * sd->sc_data[SC_OVERTHRUST].val1;
            if (wd.type == 0x0a)
                breakrate *= 2;
            if (MRAND (10000) <
                breakrate * battle_config.equipment_break_rate / 100
                || breakrate >= 10000)
            {
                pc_breakweapon (sd);
                memset (&wd, 0, sizeof (wd));
            }
        }
    }

    if (battle_config.equipment_breaking && target->type == BL_PC
        && (wd.damage > 0 || wd.damage2 > 0))
    {
        int  breakrate = 1;
        if (src->type == BL_PC
            && ((struct map_session_data *) src)->
            sc_data[SC_MELTDOWN].timer != -1)
            breakrate +=
                70 *
                ((struct map_session_data *) src)->sc_data[SC_MELTDOWN].val1;
        if (wd.type == 0x0a)
            breakrate *= 2;
        if (MRAND (10000) <
            breakrate * battle_config.equipment_break_rate / 100
            || breakrate >= 10000)
        {
            pc_breakarmor ((struct map_session_data *) target);
        }
    }

    return wd;
}

/*==========================================
 * ���@�_���[�W�v�Z
 *------------------------------------------
 */
struct Damage battle_calc_magic_attack (struct block_list *bl,
                                        struct block_list *target,
                                        int skill_num, int skill_lv, int flag)
{
    int  mdef1 = battle_get_mdef (target);
    int  mdef2 = battle_get_mdef2 (target);
    int  matk1, matk2, damage = 0, div_ = 1, blewcount =
        skill_get_blewcount (skill_num, skill_lv), rdamage = 0;
    struct Damage md;
    int  aflag;
    int  normalmagic_flag = 1;
    int  ele = 0, race = 7, t_ele = 0, t_race = 7, t_mode =
        0, cardfix, t_class, i;
    struct map_session_data *sd = NULL, *tsd = NULL;
    struct mob_data *tmd = NULL;

    //return�O�̏���������̂ŏ��o�͕��̂ݕύX
    if (bl == NULL || target == NULL)
    {
        nullpo_info (NLP_MARK);
        memset (&md, 0, sizeof (md));
        return md;
    }

    matk1 = battle_get_matk1 (bl);
    matk2 = battle_get_matk2 (bl);
    ele = skill_get_pl (skill_num);
    race = battle_get_race (bl);
    t_ele = battle_get_elem_type (target);
    t_race = battle_get_race (target);
    t_mode = battle_get_mode (target);

#define MATK_FIX( a,b ) { matk1=matk1*(a)/(b); matk2=matk2*(a)/(b); }

    if (bl->type == BL_PC && (sd = (struct map_session_data *) bl))
    {
        sd->state.attack_type = BF_MAGIC;
        if (sd->matk_rate != 100)
            MATK_FIX (sd->matk_rate, 100);
        sd->state.arrow_atk = 0;
    }
    if (target->type == BL_PC)
        tsd = (struct map_session_data *) target;
    else if (target->type == BL_MOB)
        tmd = (struct mob_data *) target;

    aflag = BF_MAGIC | BF_LONG | BF_SKILL;

    if (skill_num > 0)
    {
        switch (skill_num)
        {                       // ��{�_���[�W�v�Z(�X�L�����Ƃɏ���)
                // �q�[��or����
            case AL_HEAL:
            case PR_BENEDICTIO:
                damage = skill_calc_heal (bl, skill_lv) / 2;
                normalmagic_flag = 0;
                break;
            case PR_ASPERSIO:  /* �A�X�y���V�I */
                damage = 40;    //�Œ�_���[�W
                normalmagic_flag = 0;
                break;
            case PR_SANCTUARY: // �T���N�`���A��
                damage = (skill_lv > 6) ? 388 : skill_lv * 50;
                normalmagic_flag = 0;
                blewcount |= 0x10000;
                break;
            case ALL_RESURRECTION:
            case PR_TURNUNDEAD:    // �U�����U���N�V�����ƃ^�[���A���f�b�h
                if (target->type != BL_PC
                    && battle_check_undead (t_race, t_ele))
                {
                    int  hp, mhp, thres;
                    hp = battle_get_hp (target);
                    mhp = battle_get_max_hp (target);
                    thres = (skill_lv * 20) + battle_get_luk (bl) +
                        battle_get_int (bl) + battle_get_lv (bl) +
                        ((200 - hp * 200 / mhp));
                    if (thres > 700)
                        thres = 700;
//              if(battle_config.battle_log)
//                  printf("�^�[���A���f�b�h�I �m��%d ��(�番��)\n", thres);
                    if (MRAND (1000) < thres && !(t_mode & 0x20))   // ����
                        damage = hp;
                    else        // ���s
                        damage =
                            battle_get_lv (bl) + battle_get_int (bl) +
                            skill_lv * 10;
                }
                normalmagic_flag = 0;
                break;

            case MG_NAPALMBEAT:    // �i�p�[���r�[�g�i���U�v�Z���݁j
                MATK_FIX (70 + skill_lv * 10, 100);
                if (flag > 0)
                {
                    MATK_FIX (1, flag);
                }
                else
                {
                    if (battle_config.error_log)
                        printf
                            ("battle_calc_magic_attack(): napam enemy count=0 !\n");
                }
                break;
            case MG_FIREBALL:  // �t�@�C���[�{�[��
            {
                const int drate[] = { 100, 90, 70 };
                if (flag > 2)
                    matk1 = matk2 = 0;
                else
                    MATK_FIX ((95 + skill_lv * 5) * drate[flag], 10000);
            }
                break;
            case MG_FIREWALL:  // �t�@�C���[�E�H�[��
/*
			if( (t_ele!=3 && !battle_check_undead(t_race,t_ele)) || target->type==BL_PC ) //PC�͉Α����ł���ԁH���������_���[�W�󂯂�H
				blewcount |= 0x10000;
			else
				blewcount = 0;
*/
                if ((t_ele == 3 || battle_check_undead (t_race, t_ele))
                    && target->type != BL_PC)
                    blewcount = 0;
                else
                    blewcount |= 0x10000;
                MATK_FIX (1, 2);
                break;
            case MG_THUNDERSTORM:  // �T���_�[�X�g�[��
                MATK_FIX (80, 100);
                break;
            case MG_FROSTDIVER:    // �t���X�g�_�C�o
                MATK_FIX (100 + skill_lv * 10, 100);
                break;
            case WZ_FROSTNOVA: // �t���X�g�_�C�o
                MATK_FIX (((100 + skill_lv * 10) * (2 / 3)), 100);
                break;
            case WZ_FIREPILLAR:    // �t�@�C���[�s���[
                if (mdef1 < 1000000)
                    mdef1 = mdef2 = 0;  // MDEF����
                MATK_FIX (1, 5);
                matk1 += 50;
                matk2 += 50;
                break;
            case WZ_SIGHTRASHER:
                MATK_FIX (100 + skill_lv * 20, 100);
                break;
            case WZ_METEOR:
            case WZ_JUPITEL:   // ���s�e���T���_�[
                break;
            case WZ_VERMILION: // ���[�h�I�u�o�[�~���I��
                MATK_FIX (skill_lv * 20 + 80, 100);
                break;
            case WZ_WATERBALL: // �E�H�[�^�[�{�[��
                matk1 += skill_lv * 30;
                matk2 += skill_lv * 30;
                break;
            case WZ_STORMGUST: // �X�g�[���K�X�g
                MATK_FIX (skill_lv * 40 + 100, 100);
                blewcount |= 0x10000;
                break;
            case AL_HOLYLIGHT: // �z�[���[���C�g
                MATK_FIX (125, 100);
                break;
            case AL_RUWACH:
                MATK_FIX (145, 100);
                break;
            case HW_NAPALMVULCAN:  // �i�p�[���r�[�g�i���U�v�Z���݁j
                MATK_FIX (70 + skill_lv * 10, 100);
                if (flag > 0)
                {
                    MATK_FIX (1, flag);
                }
                else
                {
                    if (battle_config.error_log)
                        printf
                            ("battle_calc_magic_attack(): napalmvulcan enemy count=0 !\n");
                }
                break;
        }
    }

    if (normalmagic_flag)
    {                           // ��ʖ��@�_���[�W�v�Z
        int  imdef_flag = 0;
        if (matk1 > matk2)
            damage = matk2 + MRAND ((matk1 - matk2 + 1));
        else
            damage = matk2;
        if (sd)
        {
            if (sd->ignore_mdef_ele & (1 << t_ele)
                || sd->ignore_mdef_race & (1 << t_race))
                imdef_flag = 1;
            if (t_mode & 0x20)
            {
                if (sd->ignore_mdef_race & (1 << 10))
                    imdef_flag = 1;
            }
            else
            {
                if (sd->ignore_mdef_race & (1 << 11))
                    imdef_flag = 1;
            }
        }
        if (!imdef_flag)
        {
            if (battle_config.magic_defense_type)
            {
                damage =
                    damage - (mdef1 * battle_config.magic_defense_type) -
                    mdef2;
            }
            else
            {
                damage = (damage * (100 - mdef1)) / 100 - mdef2;
            }
        }

        if (damage < 1)
            damage = 1;
    }

    if (sd)
    {
        cardfix = 100;
        cardfix = cardfix * (100 + sd->magic_addrace[t_race]) / 100;
        cardfix = cardfix * (100 + sd->magic_addele[t_ele]) / 100;
        if (t_mode & 0x20)
            cardfix = cardfix * (100 + sd->magic_addrace[10]) / 100;
        else
            cardfix = cardfix * (100 + sd->magic_addrace[11]) / 100;
        t_class = battle_get_class (target);
        for (i = 0; i < sd->add_magic_damage_class_count; i++)
        {
            if (sd->add_magic_damage_classid[i] == t_class)
            {
                cardfix =
                    cardfix * (100 + sd->add_magic_damage_classrate[i]) / 100;
                break;
            }
        }
        damage = damage * cardfix / 100;
    }

    if (tsd)
    {
        int  s_class = battle_get_class (bl);
        cardfix = 100;
        cardfix = cardfix * (100 - tsd->subele[ele]) / 100; // �� ���ɂ��_���[�W�ϐ�
        cardfix = cardfix * (100 - tsd->subrace[race]) / 100;   // �푰�ɂ��_���[�W�ϐ�
        cardfix = cardfix * (100 - tsd->magic_subrace[race]) / 100;
        if (battle_get_mode (bl) & 0x20)
            cardfix = cardfix * (100 - tsd->magic_subrace[10]) / 100;
        else
            cardfix = cardfix * (100 - tsd->magic_subrace[11]) / 100;
        for (i = 0; i < tsd->add_mdef_class_count; i++)
        {
            if (tsd->add_mdef_classid[i] == s_class)
            {
                cardfix = cardfix * (100 - tsd->add_mdef_classrate[i]) / 100;
                break;
            }
        }
        cardfix = cardfix * (100 - tsd->magic_def_rate) / 100;
        damage = damage * cardfix / 100;
    }
    if (damage < 0)
        damage = 0;

    damage = battle_attr_fix (damage, ele, battle_get_element (target));    // �� ���C��

    if (skill_num == CR_GRANDCROSS)
    {                           // �O�����h�N���X
        struct Damage wd;
        wd = battle_calc_weapon_attack (bl, target, skill_num, skill_lv,
                                        flag);
        damage = (damage + wd.damage) * (100 + 40 * skill_lv) / 100;
        if (battle_config.gx_dupele)
            damage = battle_attr_fix (damage, ele, battle_get_element (target));    //����2�񂩂���
        if (bl == target)
            damage = damage / 2;    //�����͔���
    }

    div_ = skill_get_num (skill_num, skill_lv);

    if (div_ > 1 && skill_num != WZ_VERMILION)
        damage *= div_;

//  if(mdef1 >= 1000000 && damage > 0)
    if (t_mode & 0x40 && damage > 0)
        damage = 1;

    if (tsd && tsd->special_state.no_magic_damage)
    {
        if (battle_config.gtb_pvp_only != 0)
        {                       // [MouseJstr]
            if ((map[target->m].flag.pvp || map[target->m].flag.gvg)
                && target->type == BL_PC)
                damage = (damage * (100 - battle_config.gtb_pvp_only)) / 100;
        }
        else
            damage = 0;         // �� ��峃J�[�h�i���@�_���[�W�O�j
    }

    damage = battle_calc_damage (bl, target, damage, div_, skill_num, skill_lv, aflag); // �ŏI�C��

    /* magic_damage_return by [AppleGirl] and [Valaris]     */
    if (target->type == BL_PC && tsd && tsd->magic_damage_return > 0)
    {
        rdamage += damage * tsd->magic_damage_return / 100;
        if (rdamage < 1)
            rdamage = 1;
        clif_damage (target, bl, gettick (), 0, 0, rdamage, 0, 0, 0);
        battle_damage (target, bl, rdamage, 0);
    }
    /*          end magic_damage_return         */

    md.damage = damage;
    md.div_ = div_;
    md.amotion = battle_get_amotion (bl);
    md.dmotion = battle_get_dmotion (target);
    md.damage2 = 0;
    md.type = 0;
    md.blewcount = blewcount;
    md.flag = aflag;

    return md;
}

/*==========================================
 * ���̑��_���[�W�v�Z
 *------------------------------------------
 */
struct Damage battle_calc_misc_attack (struct block_list *bl,
                                       struct block_list *target,
                                       int skill_num, int skill_lv, int flag)
{
    int  int_ = battle_get_int (bl);
//  int luk=battle_get_luk(bl);
    int  dex = battle_get_dex (bl);
    int  skill, ele, race, cardfix;
    struct map_session_data *sd = NULL, *tsd = NULL;
    int  damage = 0, div_ = 1, blewcount =
        skill_get_blewcount (skill_num, skill_lv);
    struct Damage md;
    int  damagefix = 1;

    int  aflag = BF_MISC | BF_LONG | BF_SKILL;

    //return�O�̏���������̂ŏ��o�͕��̂ݕύX
    if (bl == NULL || target == NULL)
    {
        nullpo_info (NLP_MARK);
        memset (&md, 0, sizeof (md));
        return md;
    }

    if (bl->type == BL_PC && (sd = (struct map_session_data *) bl))
    {
        sd->state.attack_type = BF_MISC;
        sd->state.arrow_atk = 0;
    }

    if (target->type == BL_PC)
        tsd = (struct map_session_data *) target;

    switch (skill_num)
    {

        case HT_LANDMINE:      // �����h�}�C��
            damage = skill_lv * (dex + 75) * (100 + int_) / 100;
            break;

        case HT_BLASTMINE:     // �u���X�g�}�C��
            damage = skill_lv * (dex / 2 + 50) * (100 + int_) / 100;
            break;

        case HT_CLAYMORETRAP:  // �N���C���A�[�g���b�v
            damage = skill_lv * (dex / 2 + 75) * (100 + int_) / 100;
            break;

        case HT_BLITZBEAT:     // �u���b�c�r�[�g
            if (sd == NULL || (skill = pc_checkskill (sd, HT_STEELCROW)) <= 0)
                skill = 0;
            damage = (dex / 10 + int_ / 2 + skill * 3 + 40) * 2;
            if (flag > 1)
                damage /= flag;
            break;

        case TF_THROWSTONE:    // ����
            damage = 30;
            damagefix = 0;
            break;

        case BA_DISSONANCE:    // �s���a��
            damage =
                (skill_lv) * 20 + pc_checkskill (sd, BA_MUSICALLESSON) * 3;
            break;

        case NPC_SELFDESTRUCTION:  // ����
            damage = battle_get_hp (bl) - (bl == target ? 1 : 0);
            damagefix = 0;
            break;

        case NPC_SMOKING:      // �^�o�R���z��
            damage = 3;
            damagefix = 0;
            break;

        case NPC_DARKBREATH:
        {
            struct status_change *sc_data = battle_get_sc_data (target);
            int  hitrate =
                battle_get_hit (bl) - battle_get_flee (target) + 80;
            hitrate = ((hitrate > 95) ? 95 : ((hitrate < 5) ? 5 : hitrate));
            if (sc_data
                && (sc_data[SC_SLEEP].timer != -1
                    || sc_data[SC_STAN].timer != -1
                    || sc_data[SC_FREEZE].timer != -1
                    || (sc_data[SC_STONE].timer != -1
                        && sc_data[SC_STONE].val2 == 0)))
                hitrate = 1000000;
            if (MRAND (100) < hitrate)
            {
                damage = 500 + (skill_lv - 1) * 1000 + MRAND (1000);
                if (damage > 9999)
                    damage = 9999;
            }
        }
            break;
        case SN_FALCONASSAULT: /* �t�@���R���A�T���g */
            skill = pc_checkskill (sd, HT_BLITZBEAT);
            damage =
                (100 + 50 * skill_lv +
                 (dex / 10 + int_ / 2 + skill * 3 + 40) * 2);
            break;
    }

    ele = skill_get_pl (skill_num);
    race = battle_get_race (bl);

    if (damagefix)
    {
        if (damage < 1 && skill_num != NPC_DARKBREATH)
            damage = 1;

        if (tsd)
        {
            cardfix = 100;
            cardfix = cardfix * (100 - tsd->subele[ele]) / 100; // �����ɂ��_���[�W�ϐ�
            cardfix = cardfix * (100 - tsd->subrace[race]) / 100;   // �푰�ɂ��_���[�W�ϐ�
            cardfix = cardfix * (100 - tsd->misc_def_rate) / 100;
            damage = damage * cardfix / 100;
        }
        if (damage < 0)
            damage = 0;
        damage = battle_attr_fix (damage, ele, battle_get_element (target));    // �����C��
    }

    div_ = skill_get_num (skill_num, skill_lv);
    if (div_ > 1)
        damage *= div_;

    if (damage > 0
        && (damage < div_
            || (battle_get_def (target) >= 1000000
                && battle_get_mdef (target) >= 1000000)))
    {
        damage = div_;
    }

    damage = battle_calc_damage (bl, target, damage, div_, skill_num, skill_lv, aflag); // �ŏI�C��

    md.damage = damage;
    md.div_ = div_;
    md.amotion = battle_get_amotion (bl);
    md.dmotion = battle_get_dmotion (target);
    md.damage2 = 0;
    md.type = 0;
    md.blewcount = blewcount;
    md.flag = aflag;
    return md;

}

/*==========================================
 * �_���[�W�v�Z�ꊇ�����p
 *------------------------------------------
 */
struct Damage battle_calc_attack (int attack_type,
                                  struct block_list *bl,
                                  struct block_list *target, int skill_num,
                                  int skill_lv, int flag)
{
    struct Damage d;
    memset (&d, 0, sizeof (d));

    switch (attack_type)
    {
        case BF_WEAPON:
            return battle_calc_weapon_attack (bl, target, skill_num, skill_lv,
                                              flag);
        case BF_MAGIC:
            return battle_calc_magic_attack (bl, target, skill_num, skill_lv,
                                             flag);
        case BF_MISC:
            return battle_calc_misc_attack (bl, target, skill_num, skill_lv,
                                            flag);
        default:
            if (battle_config.error_log)
                printf ("battle_calc_attack: unknwon attack type ! %d\n",
                        attack_type);
            break;
    }
    return d;
}

/*==========================================
 * �ʏ�U�������܂Ƃ�
 *------------------------------------------
 */
int battle_weapon_attack (struct block_list *src, struct block_list *target,
                          unsigned int tick, int flag)
{
    struct map_session_data *sd = NULL;
    struct status_change *sc_data = battle_get_sc_data (src), *t_sc_data =
        battle_get_sc_data (target);
    short *opt1;
    int  race = 7, ele = 0;
    int  damage, rdamage = 0;
    struct Damage wd;

    nullpo_retr (0, src);
    nullpo_retr (0, target);

    if (src->type == BL_PC)
        sd = (struct map_session_data *) src;

    if (src->prev == NULL || target->prev == NULL)
        return 0;
    if (src->type == BL_PC && pc_isdead (sd))
        return 0;
    if (target->type == BL_PC
        && pc_isdead ((struct map_session_data *) target))
        return 0;

    opt1 = battle_get_opt1 (src);
    if (opt1 && *opt1 > 0)
    {
        battle_stopattack (src);
        return 0;
    }
    if (sc_data && sc_data[SC_BLADESTOP].timer != -1)
    {
        battle_stopattack (src);
        return 0;
    }

    race = battle_get_race (target);
    ele = battle_get_elem_type (target);
    if (battle_check_target (src, target, BCT_ENEMY) > 0 &&
        battle_check_range (src, target, 0))
    {
        // �U���ΏۂƂȂ肤��̂ōU��
        if (sd && sd->status.weapon == 11)
        {
            if (sd->equip_index[10] >= 0)
            {
                if (battle_config.arrow_decrement)
                    pc_delitem (sd, sd->equip_index[10], 1, 0);
            }
            else
            {
                clif_arrow_fail (sd, 0);
                return 0;
            }
        }
        if (flag & 0x8000)
        {
            if (sd && battle_config.pc_attack_direction_change)
                sd->dir = sd->head_dir =
                    map_calc_dir (src, target->x, target->y);
            else if (src->type == BL_MOB
                     && battle_config.monster_attack_direction_change)
                ((struct mob_data *) src)->dir =
                    map_calc_dir (src, target->x, target->y);
            wd = battle_calc_weapon_attack (src, target, KN_AUTOCOUNTER,
                                            flag & 0xff, 0);
        }
        else
            wd = battle_calc_weapon_attack (src, target, 0, 0, 0);

        // significantly increase injuries for hasted characters
        if (wd.damage > 0 && (t_sc_data[SC_HASTE].timer != -1))
        {
            wd.damage = (wd.damage * (16 + t_sc_data[SC_HASTE].val1)) >> 4;
        }

        if (wd.damage > 0
            && t_sc_data[SC_PHYS_SHIELD].timer != -1 && target->type == BL_PC)
        {
            int  reduction = t_sc_data[SC_PHYS_SHIELD].val1;
            if (reduction > wd.damage)
                reduction = wd.damage;

            wd.damage -= reduction;
            MAP_LOG_PC (((struct map_session_data *) target),
                        "MAGIC-ABSORB-DMG %d", reduction);
        }

        if ((damage = wd.damage + wd.damage2) > 0 && src != target)
        {
            if (wd.flag & BF_SHORT)
            {
                if (target->type == BL_PC)
                {
                    struct map_session_data *tsd =
                        (struct map_session_data *) target;
                    if (tsd && tsd->short_weapon_damage_return > 0)
                    {
                        rdamage +=
                            damage * tsd->short_weapon_damage_return / 100;
                        if (rdamage < 1)
                            rdamage = 1;
                    }
                }
                if (t_sc_data && t_sc_data[SC_REFLECTSHIELD].timer != -1)
                {
                    rdamage +=
                        damage * t_sc_data[SC_REFLECTSHIELD].val2 / 100;
                    if (rdamage < 1)
                        rdamage = 1;
                }
            }
            else if (wd.flag & BF_LONG)
            {
                if (target->type == BL_PC)
                {
                    struct map_session_data *tsd =
                        (struct map_session_data *) target;
                    if (tsd && tsd->long_weapon_damage_return > 0)
                    {
                        rdamage +=
                            damage * tsd->long_weapon_damage_return / 100;
                        if (rdamage < 1)
                            rdamage = 1;
                    }
                }
            }

            if (rdamage > 0)
                clif_damage (src, src, tick, wd.amotion, 0, rdamage, 1, 4, 0);
        }

        if (wd.div_ == 255 && sd)
        {                       //�O�i��
            int  delay =
                1000 - 4 * battle_get_agi (src) - 2 * battle_get_dex (src);
            int  skilllv;
            if (wd.damage + wd.damage2 < battle_get_hp (target))
            {
                if ((skilllv = pc_checkskill (sd, MO_CHAINCOMBO)) > 0)
                    delay += 300 * battle_config.combo_delay_rate / 100;    //�lj��f�B���C��conf�ɂ�蒲��

                skill_status_change_start (src, SC_COMBO, MO_TRIPLEATTACK,
                                           skilllv, 0, 0, delay, 0);
            }
            sd->attackabletime = sd->canmove_tick = tick + delay;
            clif_combo_delay (src, delay);
            clif_skill_damage (src, target, tick, wd.amotion, wd.dmotion,
                               wd.damage, 3, MO_TRIPLEATTACK,
                               pc_checkskill (sd, MO_TRIPLEATTACK), -1);
        }
        else
        {
            clif_damage (src, target, tick, wd.amotion, wd.dmotion,
                         wd.damage, wd.div_, wd.type, wd.damage2);
            //�񓁗�����ƃJ�^�[���nj��̃~�X�\��(�������`)
            if (sd && sd->status.weapon >= 16 && wd.damage2 == 0)
                clif_damage (src, target, tick + 10, wd.amotion, wd.dmotion,
                             0, 1, 0, 0);
        }
        if (sd && sd->splash_range > 0 && (wd.damage > 0 || wd.damage2 > 0))
            skill_castend_damage_id (src, target, 0, -1, tick, 0);
        map_freeblock_lock ();

        if (src->type == BL_PC)
        {
            int  weapon_index = sd->equip_index[9];
            int  weapon = 0;
            if (sd->inventory_data[weapon_index]
                && sd->status.inventory[weapon_index].equip & 0x2)
                weapon = sd->inventory_data[weapon_index]->nameid;

            MAP_LOG ("PC%d %d:%d,%d WPNDMG %s%d %d FOR %d WPN %d",
                     sd->status.char_id, src->m, src->x, src->y,
                     (target->type == BL_PC) ? "PC" : "MOB",
                     (target->type ==
                      BL_PC) ? ((struct map_session_data *) target)->
                     status.char_id : target->id,
                     (target->type ==
                      BL_PC) ? 0 : ((struct mob_data *) target)->class,
                     wd.damage + wd.damage2, weapon);
        }

        if (target->type == BL_PC)
        {
            struct map_session_data *sd2 = (struct map_session_data *) target;
            MAP_LOG ("PC%d %d:%d,%d WPNINJURY %s%d %d FOR %d",
                     sd2->status.char_id, target->m, target->x, target->y,
                     (src->type == BL_PC) ? "PC" : "MOB",
                     (src->type ==
                      BL_PC) ? ((struct map_session_data *) src)->
                     status.char_id : src->id,
                     (src->type ==
                      BL_PC) ? 0 : ((struct mob_data *) src)->class,
                     wd.damage + wd.damage2);
        }

        battle_damage (src, target, (wd.damage + wd.damage2), 0);
        if (target->prev != NULL &&
            (target->type != BL_PC
             || (target->type == BL_PC
                 && !pc_isdead ((struct map_session_data *) target))))
        {
            if (wd.damage > 0 || wd.damage2 > 0)
            {
                skill_additional_effect (src, target, 0, 0, BF_WEAPON, tick);
                if (sd)
                {
                    if (sd->weapon_coma_ele[ele] > 0
                        && MRAND (10000) < sd->weapon_coma_ele[ele])
                        battle_damage (src, target,
                                       battle_get_max_hp (target), 1);
                    if (sd->weapon_coma_race[race] > 0
                        && MRAND (10000) < sd->weapon_coma_race[race])
                        battle_damage (src, target,
                                       battle_get_max_hp (target), 1);
                    if (battle_get_mode (target) & 0x20)
                    {
                        if (sd->weapon_coma_race[10] > 0
                            && MRAND (10000) < sd->weapon_coma_race[10])
                            battle_damage (src, target,
                                           battle_get_max_hp (target), 1);
                    }
                    else
                    {
                        if (sd->weapon_coma_race[11] > 0
                            && MRAND (10000) < sd->weapon_coma_race[11])
                            battle_damage (src, target,
                                           battle_get_max_hp (target), 1);
                    }
                }
            }
        }
        if (sc_data && sc_data[SC_AUTOSPELL].timer != -1
            && MRAND (100) < sc_data[SC_AUTOSPELL].val4)
        {
            int  skilllv = sc_data[SC_AUTOSPELL].val3, i, f = 0;
            i = MRAND (100);
            if (i >= 50)
                skilllv -= 2;
            else if (i >= 15)
                skilllv--;
            if (skilllv < 1)
                skilllv = 1;
            if (sd)
            {
                int  sp = skill_get_sp (sc_data[SC_AUTOSPELL].val2,
                                        skilllv) * 2 / 3;
                if (sd->status.sp >= sp)
                {
                    if ((i = skill_get_inf (sc_data[SC_AUTOSPELL].val2) == 2)
                        || i == 32)
                        f = skill_castend_pos2 (src, target->x, target->y,
                                                sc_data[SC_AUTOSPELL].val2,
                                                skilllv, tick, flag);
                    else
                    {
                        switch (skill_get_nk (sc_data[SC_AUTOSPELL].val2))
                        {
                            case 0:
                            case 2:
                                f = skill_castend_damage_id (src, target,
                                                             sc_data
                                                             [SC_AUTOSPELL].val2,
                                                             skilllv, tick,
                                                             flag);
                                break;
                            case 1:    /* �x���n */
                                if ((sc_data[SC_AUTOSPELL].val2 == AL_HEAL
                                     || (sc_data[SC_AUTOSPELL].val2 ==
                                         ALL_RESURRECTION
                                         && target->type != BL_PC))
                                    && battle_check_undead (race, ele))
                                    f = skill_castend_damage_id (src, target,
                                                                 sc_data
                                                                 [SC_AUTOSPELL].val2,
                                                                 skilllv,
                                                                 tick, flag);
                                else
                                    f = skill_castend_nodamage_id (src,
                                                                   target,
                                                                   sc_data
                                                                   [SC_AUTOSPELL].val2,
                                                                   skilllv,
                                                                   tick,
                                                                   flag);
                                break;
                        }
                    }
                    if (!f)
                        pc_heal (sd, 0, -sp);
                }
            }
            else
            {
                if ((i = skill_get_inf (sc_data[SC_AUTOSPELL].val2) == 2)
                    || i == 32)
                    skill_castend_pos2 (src, target->x, target->y,
                                        sc_data[SC_AUTOSPELL].val2, skilllv,
                                        tick, flag);
                else
                {
                    switch (skill_get_nk (sc_data[SC_AUTOSPELL].val2))
                    {
                        case 0:
                        case 2:
                            skill_castend_damage_id (src, target,
                                                     sc_data
                                                     [SC_AUTOSPELL].val2,
                                                     skilllv, tick, flag);
                            break;
                        case 1:    /* �x���n */
                            if ((sc_data[SC_AUTOSPELL].val2 == AL_HEAL
                                 || (sc_data[SC_AUTOSPELL].val2 ==
                                     ALL_RESURRECTION
                                     && target->type != BL_PC))
                                && battle_check_undead (race, ele))
                                skill_castend_damage_id (src, target,
                                                         sc_data
                                                         [SC_AUTOSPELL].val2,
                                                         skilllv, tick, flag);
                            else
                                skill_castend_nodamage_id (src, target,
                                                           sc_data
                                                           [SC_AUTOSPELL].val2,
                                                           skilllv, tick,
                                                           flag);
                            break;
                    }
                }
            }
        }
        if (sd)
        {
            if (sd->autospell_id > 0 && sd->autospell_lv > 0
                && MRAND (100) < sd->autospell_rate)
            {
                int  skilllv = sd->autospell_lv, i, f = 0, sp;
                i = MRAND (100);
                if (i >= 50)
                    skilllv -= 2;
                else if (i >= 15)
                    skilllv--;
                if (skilllv < 1)
                    skilllv = 1;
                sp = skill_get_sp (sd->autospell_id, skilllv) * 2 / 3;
                if (sd->status.sp >= sp)
                {
                    if ((i = skill_get_inf (sd->autospell_id) == 2)
                        || i == 32)
                        f = skill_castend_pos2 (src, target->x, target->y,
                                                sd->autospell_id, skilllv,
                                                tick, flag);
                    else
                    {
                        switch (skill_get_nk (sd->autospell_id))
                        {
                            case 0:
                            case 2:
                                f = skill_castend_damage_id (src, target,
                                                             sd->autospell_id,
                                                             skilllv, tick,
                                                             flag);
                                break;
                            case 1:    /* �x���n */
                                if ((sd->autospell_id == AL_HEAL
                                     || (sd->autospell_id == ALL_RESURRECTION
                                         && target->type != BL_PC))
                                    && battle_check_undead (race, ele))
                                    f = skill_castend_damage_id (src, target,
                                                                 sd->autospell_id,
                                                                 skilllv,
                                                                 tick, flag);
                                else
                                    f = skill_castend_nodamage_id (src,
                                                                   target,
                                                                   sd->autospell_id,
                                                                   skilllv,
                                                                   tick,
                                                                   flag);
                                break;
                        }
                    }
                    if (!f)
                        pc_heal (sd, 0, -sp);
                }
            }
            if (wd.flag & BF_WEAPON && src != target
                && (wd.damage > 0 || wd.damage2 > 0))
            {
                int  hp = 0, sp = 0;
                if (sd->hp_drain_rate && sd->hp_drain_per > 0 && wd.damage > 0
                    && MRAND (100) < sd->hp_drain_rate)
                {
                    hp += (wd.damage * sd->hp_drain_per) / 100;
                    if (sd->hp_drain_rate > 0 && hp < 1)
                        hp = 1;
                    else if (sd->hp_drain_rate < 0 && hp > -1)
                        hp = -1;
                }
                if (sd->hp_drain_rate_ && sd->hp_drain_per_ > 0
                    && wd.damage2 > 0 && MRAND (100) < sd->hp_drain_rate_)
                {
                    hp += (wd.damage2 * sd->hp_drain_per_) / 100;
                    if (sd->hp_drain_rate_ > 0 && hp < 1)
                        hp = 1;
                    else if (sd->hp_drain_rate_ < 0 && hp > -1)
                        hp = -1;
                }
                if (sd->sp_drain_rate && sd->sp_drain_per > 0 && wd.damage > 0
                    && MRAND (100) < sd->sp_drain_rate)
                {
                    sp += (wd.damage * sd->sp_drain_per) / 100;
                    if (sd->sp_drain_rate > 0 && sp < 1)
                        sp = 1;
                    else if (sd->sp_drain_rate < 0 && sp > -1)
                        sp = -1;
                }
                if (sd->sp_drain_rate_ && sd->sp_drain_per_ > 0
                    && wd.damage2 > 0 && MRAND (100) < sd->sp_drain_rate_)
                {
                    sp += (wd.damage2 * sd->sp_drain_per_) / 100;
                    if (sd->sp_drain_rate_ > 0 && sp < 1)
                        sp = 1;
                    else if (sd->sp_drain_rate_ < 0 && sp > -1)
                        sp = -1;
                }
                if (hp || sp)
                    pc_heal (sd, hp, sp);
            }
        }

        if (rdamage > 0)
            battle_damage (target, src, rdamage, 0);
        if (t_sc_data && t_sc_data[SC_AUTOCOUNTER].timer != -1
            && t_sc_data[SC_AUTOCOUNTER].val4 > 0)
        {
            if (t_sc_data[SC_AUTOCOUNTER].val3 == src->id)
                battle_weapon_attack (target, src, tick,
                                      0x8000 |
                                      t_sc_data[SC_AUTOCOUNTER].val1);
            skill_status_change_end (target, SC_AUTOCOUNTER, -1);
        }
        if (t_sc_data && t_sc_data[SC_BLADESTOP_WAIT].timer != -1)
        {
            int  lv = t_sc_data[SC_BLADESTOP_WAIT].val1;
            skill_status_change_end (target, SC_BLADESTOP_WAIT, -1);
            skill_status_change_start (src, SC_BLADESTOP, lv, 1, (int) src,
                                       (int) target,
                                       skill_get_time2 (MO_BLADESTOP, lv), 0);
            skill_status_change_start (target, SC_BLADESTOP, lv, 2,
                                       (int) target, (int) src,
                                       skill_get_time2 (MO_BLADESTOP, lv), 0);
        }
        if (t_sc_data && t_sc_data[SC_SPLASHER].timer != -1)    //�������̂őΏۂ̃x�i���X�v���b�V���[��Ԃ�����
            skill_status_change_end (target, SC_SPLASHER, -1);

        map_freeblock_unlock ();
    }
    return wd.dmg_lv;
}

int battle_check_undead (int race, int element)
{
    if (battle_config.undead_detect_type == 0)
    {
        if (element == 9)
            return 1;
    }
    else if (battle_config.undead_detect_type == 1)
    {
        if (race == 1)
            return 1;
    }
    else
    {
        if (element == 9 || race == 1)
            return 1;
    }
    return 0;
}

/*==========================================
 * �G��������(1=�m��,0=�ے�,-1=�G���[)
 * flag&0xf0000 = 0x00000:�G����Ȃ�������iret:1���G�ł͂Ȃ��j
 *				= 0x10000:�p�[�e�B�[����iret:1=�p�[�e�B�[�����o)
 *				= 0x20000:�S��(ret:1=�G��������)
 *				= 0x40000:�G������(ret:1=�G)
 *				= 0x50000:�p�[�e�B�[����Ȃ�������(ret:1=�p�[�e�B�łȂ�)
 *------------------------------------------
 */
int battle_check_target (struct block_list *src, struct block_list *target,
                         int flag)
{
    int  s_p, s_g, t_p, t_g;
    struct block_list *ss = src;

    nullpo_retr (0, src);
    nullpo_retr (0, target);

    if (flag & 0x40000)
    {                           // ���]�t���O
        int  ret = battle_check_target (src, target, flag & 0x30000);
        if (ret != -1)
            return !ret;
        return -1;
    }

    if (flag & 0x20000)
    {
        if (target->type == BL_MOB || target->type == BL_PC)
            return 1;
        else
            return -1;
    }

    if (src->type == BL_SKILL && target->type == BL_SKILL)  // �Ώۂ��X�L�����j�b�g�Ȃ疳�����m��
        return -1;

    if (target->type == BL_PC
        && ((struct map_session_data *) target)->invincible_timer != -1)
        return -1;

    if (target->type == BL_SKILL)
    {
        switch (((struct skill_unit *) target)->group->unit_id)
        {
            case 0x8d:
            case 0x8f:
            case 0x98:
                return 0;
                break;
        }
    }

    // �X�L�����j�b�g�̏ꍇ�A�e�����߂�
    if (src->type == BL_SKILL)
    {
        int  inf2 =
            skill_get_inf2 (((struct skill_unit *) src)->group->skill_id);
        if ((ss =
             map_id2bl (((struct skill_unit *) src)->group->src_id)) == NULL)
            return -1;
        if (ss->prev == NULL)
            return -1;
        if (inf2 & 0x80 && (map[src->m].flag.pvp || pc_iskiller ((struct map_session_data *) src, (struct map_session_data *) target)) &&   // [MouseJstr]
            !(target->type == BL_PC
              && pc_isinvisible ((struct map_session_data *) target)))
            return 0;
        if (ss == target)
        {
            if (inf2 & 0x100)
                return 0;
            if (inf2 & 0x200)
                return -1;
        }
    }
    // Mob��master_id��������special_mob_ai�Ȃ�A����������߂�
    if (src->type == BL_MOB)
    {
        struct mob_data *md = (struct mob_data *) src;
        if (md && md->master_id > 0)
        {
            if (md->master_id == target->id)    // ��Ȃ�m��
                return 1;
            if (md->state.special_mob_ai)
            {
                if (target->type == BL_MOB)
                {               //special_mob_ai�őΏۂ�Mob
                    struct mob_data *tmd = (struct mob_data *) target;
                    if (tmd)
                    {
                        if (tmd->master_id != md->master_id)    //�����傪�ꏏ�łȂ���Δے�
                            return 0;
                        else
                        {       //�����傪�ꏏ�Ȃ̂ōm�肵�������ǎ����͔ے�
                            if (md->state.special_mob_ai > 2)
                                return 0;
                            else
                                return 1;
                        }
                    }
                }
            }
            if ((ss = map_id2bl (md->master_id)) == NULL)
                return -1;
        }
    }

    if (src == target || ss == target)  // �����Ȃ�m��
        return 1;

    if (target->type == BL_PC
        && pc_isinvisible ((struct map_session_data *) target))
        return -1;

    if (src->prev == NULL ||    // ����ł�Ȃ�G���[
        (src->type == BL_PC && pc_isdead ((struct map_session_data *) src)))
        return -1;

    if ((ss->type == BL_PC && target->type == BL_MOB) ||
        (ss->type == BL_MOB && target->type == BL_PC))
        return 0;               // PCvsMOB�Ȃ�ے�

    s_p = battle_get_party_id (ss);
    s_g = battle_get_guild_id (ss);

    t_p = battle_get_party_id (target);
    t_g = battle_get_guild_id (target);

    if (flag & 0x10000)
    {
        if (s_p && t_p && s_p == t_p)   // �����p�[�e�B�Ȃ�m��i�����j
            return 1;
        else                    // �p�[�e�B�����Ȃ瓯���p�[�e�B����Ȃ����_�Ŕے�
            return 0;
    }

    if (ss->type == BL_MOB && s_g > 0 && t_g > 0 && s_g == t_g) // �����M���h/mob�N���X�Ȃ�m��i�����j
        return 1;

//printf("ss:%d src:%d target:%d flag:0x%x %d %d ",ss->id,src->id,target->id,flag,src->type,target->type);
//printf("p:%d %d g:%d %d\n",s_p,t_p,s_g,t_g);

    if (ss->type == BL_PC && target->type == BL_PC)
    {                           // ����PVP���[�h�Ȃ�ے�i�G�j
        struct skill_unit *su = NULL;
        if (src->type == BL_SKILL)
            su = (struct skill_unit *) src;
        if (map[ss->m].flag.pvp
            || pc_iskiller ((struct map_session_data *) ss,
                            (struct map_session_data *) target))
        {                       // [MouseJstr]
            if (su && su->group->target_flag == BCT_NOENEMY)
                return 1;
            else if (battle_config.pk_mode
                     && (((struct map_session_data *) ss)->status.class == 0
                         || ((struct map_session_data *) target)->
                         status.class == 0))
                return 1;       // prevent novice engagement in pk_mode [Valaris]
            else if (map[ss->m].flag.pvp_noparty && s_p > 0 && t_p > 0
                     && s_p == t_p)
                return 1;
            else if (map[ss->m].flag.pvp_noguild && s_g > 0 && t_g > 0
                     && s_g == t_g)
                return 1;
            return 0;
        }
        if (map[src->m].flag.gvg)
        {
            struct guild *g = NULL;
            if (su && su->group->target_flag == BCT_NOENEMY)
                return 1;
            if (s_g > 0 && s_g == t_g)
                return 1;
            if (map[src->m].flag.gvg_noparty && s_p > 0 && t_p > 0
                && s_p == t_p)
                return 1;
            if ((g = guild_search (s_g)))
            {
                int  i;
                for (i = 0; i < MAX_GUILDALLIANCE; i++)
                {
                    if (g->alliance[i].guild_id > 0
                        && g->alliance[i].guild_id == t_g)
                    {
                        if (g->alliance[i].opposition)
                            return 0;   //�G�΃M���h�Ȃ疳�����ɓG
                        else
                            return 1;   //�����M���h�Ȃ疳�����ɖ���
                    }
                }
            }
            return 0;
        }
    }

    return 1;                   // �Y�����Ȃ��̂Ŗ��֌W�l���i�܂��G����Ȃ��̂Ŗ����j
}

/*==========================================
 * �˒�����
 *------------------------------------------
 */
int battle_check_range (struct block_list *src, struct block_list *bl,
                        int range)
{

    int  dx, dy;
    struct walkpath_data wpd;
    int  arange;

    nullpo_retr (0, src);
    nullpo_retr (0, bl);

    dx = abs (bl->x - src->x);
    dy = abs (bl->y - src->y);
    arange = ((dx > dy) ? dx : dy);

    if (src->m != bl->m)        // �Ⴄ�}�b�v
        return 0;

    if (range > 0 && range < arange)    // ��������
        return 0;

    if (arange < 2)             // �����}�X���א�
        return 1;

//  if(bl->type == BL_SKILL && ((struct skill_unit *)bl)->group->unit_id == 0x8d)
//      return 1;

    // ��Q������
    wpd.path_len = 0;
    wpd.path_pos = 0;
    wpd.path_half = 0;
    if (path_search (&wpd, src->m, src->x, src->y, bl->x, bl->y, 0x10001) !=
        -1)
        return 1;

    dx = (dx > 0) ? 1 : ((dx < 0) ? -1 : 0);
    dy = (dy > 0) ? 1 : ((dy < 0) ? -1 : 0);
    return (path_search (&wpd, src->m, src->x + dx, src->y + dy,
                         bl->x - dx, bl->y - dy, 0x10001) != -1) ? 1 : 0;
}

/*==========================================
 * Return numerical value of a switch configuration (modified by [Yor])
 * on/off, english, fran�ais, deutsch, espa�ol
 *------------------------------------------
 */
int battle_config_switch (const char *str)
{
    if (strcmpi (str, "on") == 0 || strcmpi (str, "yes") == 0
        || strcmpi (str, "oui") == 0 || strcmpi (str, "ja") == 0
        || strcmpi (str, "si") == 0)
        return 1;
    if (strcmpi (str, "off") == 0 || strcmpi (str, "no") == 0
        || strcmpi (str, "non") == 0 || strcmpi (str, "nein") == 0)
        return 0;
    return atoi (str);
}

/*==========================================
 * �ݒ�t�@�C����ǂݍ���
 *------------------------------------------
 */
int battle_config_read (const char *cfgName)
{
    int  i;
    char line[1024], w1[1024], w2[1024];
    FILE *fp;
    static int count = 0;

    if ((count++) == 0)
    {
        battle_config.warp_point_debug = 0;
        battle_config.enemy_critical = 0;
        battle_config.enemy_critical_rate = 100;
        battle_config.enemy_str = 1;
        battle_config.enemy_perfect_flee = 0;
        battle_config.cast_rate = 100;
        battle_config.delay_rate = 100;
        battle_config.delay_dependon_dex = 0;
        battle_config.sdelay_attack_enable = 0;
        battle_config.left_cardfix_to_right = 0;
        battle_config.pc_skill_add_range = 0;
        battle_config.skill_out_range_consume = 1;
        battle_config.mob_skill_add_range = 0;
        battle_config.pc_damage_delay = 1;
        battle_config.pc_damage_delay_rate = 100;
        battle_config.defnotenemy = 1;
        battle_config.random_monster_checklv = 1;
        battle_config.attr_recover = 1;
        battle_config.flooritem_lifetime = LIFETIME_FLOORITEM * 1000;
        battle_config.item_auto_get = 0;
        battle_config.drop_pickup_safety_zone = 20;
        battle_config.item_first_get_time = 3000;
        battle_config.item_second_get_time = 1000;
        battle_config.item_third_get_time = 1000;
        battle_config.mvp_item_first_get_time = 10000;
        battle_config.mvp_item_second_get_time = 10000;
        battle_config.mvp_item_third_get_time = 2000;

        battle_config.drop_rate0item = 0;
        battle_config.base_exp_rate = 100;
        battle_config.job_exp_rate = 100;
        battle_config.pvp_exp = 1;
        battle_config.gtb_pvp_only = 0;
        battle_config.death_penalty_type = 0;
        battle_config.death_penalty_base = 0;
        battle_config.death_penalty_job = 0;
        battle_config.zeny_penalty = 0;
        battle_config.restart_hp_rate = 0;
        battle_config.restart_sp_rate = 0;
        battle_config.mvp_item_rate = 100;
        battle_config.mvp_exp_rate = 100;
        battle_config.mvp_hp_rate = 100;
        battle_config.monster_hp_rate = 100;
        battle_config.monster_max_aspd = 199;
        battle_config.atc_gmonly = 0;
        battle_config.gm_allskill = 0;
        battle_config.gm_allequip = 0;
        battle_config.gm_skilluncond = 0;
        battle_config.guild_max_castles = 0;
        battle_config.skillfree = 0;
        battle_config.skillup_limit = 0;
        battle_config.wp_rate = 100;
        battle_config.pp_rate = 100;
        battle_config.monster_active_enable = 1;
        battle_config.monster_damage_delay_rate = 100;
        battle_config.monster_loot_type = 0;
        battle_config.mob_skill_use = 1;
        battle_config.mob_count_rate = 100;
        battle_config.quest_skill_learn = 0;
        battle_config.quest_skill_reset = 1;
        battle_config.basic_skill_check = 1;
        battle_config.guild_emperium_check = 1;
        battle_config.guild_exp_limit = 50;
        battle_config.pc_invincible_time = 5000;
        battle_config.skill_min_damage = 0;
        battle_config.finger_offensive_type = 0;
        battle_config.heal_exp = 0;
        battle_config.resurrection_exp = 0;
        battle_config.shop_exp = 0;
        battle_config.combo_delay_rate = 100;
        battle_config.item_check = 1;
        battle_config.wedding_modifydisplay = 0;
        battle_config.natural_healhp_interval = 6000;
        battle_config.natural_healsp_interval = 8000;
        battle_config.natural_heal_skill_interval = 10000;
        battle_config.natural_heal_weight_rate = 50;
        battle_config.itemheal_regeneration_factor = 1;
        battle_config.item_name_override_grffile = 1;
        battle_config.arrow_decrement = 1;
        battle_config.max_aspd = 199;
        battle_config.max_hp = 32500;
        battle_config.max_sp = 32500;
        battle_config.max_lv = 99;  // [MouseJstr]
        battle_config.max_parameter = 99;
        battle_config.max_cart_weight = 8000;
        battle_config.pc_skill_log = 0;
        battle_config.mob_skill_log = 0;
        battle_config.battle_log = 0;
        battle_config.save_log = 0;
        battle_config.error_log = 1;
        battle_config.etc_log = 1;
        battle_config.save_clothcolor = 0;
        battle_config.undead_detect_type = 0;
        battle_config.pc_auto_counter_type = 1;
        battle_config.monster_auto_counter_type = 1;
        battle_config.agi_penaly_type = 0;
        battle_config.agi_penaly_count = 3;
        battle_config.agi_penaly_num = 0;
        battle_config.agi_penaly_count_lv = ATK_FLEE;
        battle_config.vit_penaly_type = 0;
        battle_config.vit_penaly_count = 3;
        battle_config.vit_penaly_num = 0;
        battle_config.vit_penaly_count_lv = ATK_DEF;
        battle_config.player_defense_type = 0;
        battle_config.monster_defense_type = 0;
        battle_config.magic_defense_type = 0;
        battle_config.pc_skill_reiteration = 0;
        battle_config.monster_skill_reiteration = 0;
        battle_config.pc_skill_nofootset = 0;
        battle_config.monster_skill_nofootset = 0;
        battle_config.pc_cloak_check_type = 0;
        battle_config.monster_cloak_check_type = 0;
        battle_config.gvg_short_damage_rate = 100;
        battle_config.gvg_long_damage_rate = 100;
        battle_config.gvg_magic_damage_rate = 100;
        battle_config.gvg_misc_damage_rate = 100;
        battle_config.gvg_eliminate_time = 7000;
        battle_config.mob_changetarget_byskill = 0;
        battle_config.pc_attack_direction_change = 1;
        battle_config.monster_attack_direction_change = 1;
        battle_config.pc_undead_nofreeze = 0;
        battle_config.pc_land_skill_limit = 1;
        battle_config.monster_land_skill_limit = 1;
        battle_config.party_skill_penaly = 1;
        battle_config.monster_class_change_full_recover = 0;
        battle_config.produce_item_name_input = 1;
        battle_config.produce_potion_name_input = 1;
        battle_config.making_arrow_name_input = 1;
        battle_config.holywater_name_input = 1;
        battle_config.display_delay_skill_fail = 1;
        battle_config.chat_warpportal = 0;
        battle_config.mob_warpportal = 0;
        battle_config.dead_branch_active = 0;
        battle_config.show_steal_in_same_party = 0;
        battle_config.enable_upper_class = 0;
        battle_config.pc_attack_attr_none = 0;
        battle_config.mob_attack_attr_none = 1;
        battle_config.mob_ghostring_fix = 0;
        battle_config.gx_allhit = 0;
        battle_config.gx_cardfix = 0;
        battle_config.gx_dupele = 1;
        battle_config.gx_disptype = 1;
        battle_config.player_skill_partner_check = 1;
        battle_config.hide_GM_session = 0;
        battle_config.unit_movement_type = 0;
        battle_config.invite_request_check = 1;
        battle_config.skill_removetrap_type = 0;
        battle_config.disp_experience = 0;
        battle_config.item_rate_common = 100;
        battle_config.item_rate_equip = 100;
        battle_config.item_rate_card = 100;
        battle_config.item_rate_heal = 100; // Added by Valaris
        battle_config.item_rate_use = 100;  // End
        battle_config.item_drop_common_min = 1; // Added by TyrNemesis^
        battle_config.item_drop_common_max = 10000;
        battle_config.item_drop_equip_min = 1;
        battle_config.item_drop_equip_max = 10000;
        battle_config.item_drop_card_min = 1;
        battle_config.item_drop_card_max = 10000;
        battle_config.item_drop_mvp_min = 1;
        battle_config.item_drop_mvp_max = 10000;    // End Addition
        battle_config.item_drop_heal_min = 1;   // Added by Valaris
        battle_config.item_drop_heal_max = 10000;
        battle_config.item_drop_use_min = 1;
        battle_config.item_drop_use_max = 10000;    // End
        battle_config.prevent_logout = 1;   // Added by RoVeRT
        battle_config.maximum_level = 255;  // Added by Valaris
        battle_config.drops_by_luk = 0; // [Valaris]
        battle_config.equipment_breaking = 0;   // [Valaris]
        battle_config.equipment_break_rate = 100;   // [Valaris]
        battle_config.pk_mode = 0;  // [Valaris]
        battle_config.multi_level_up = 0;   // [Valaris]
        battle_config.backstab_bow_penalty = 0; // Akaru
        battle_config.night_at_start = 0;   // added by [Yor]
        battle_config.day_duration = 2 * 60 * 60 * 1000;    // added by [Yor] (2 hours)
        battle_config.night_duration = 30 * 60 * 1000;  // added by [Yor] (30 minutes)
        battle_config.show_mob_hp = 0;  // [Valaris]
        battle_config.hack_info_GM_level = 60;  // added by [Yor] (default: 60, GM level)
        battle_config.any_warp_GM_min_level = 20;   // added by [Yor]
        battle_config.packet_ver_flag = 63; // added by [Yor]
        battle_config.min_hair_style = 0;
        battle_config.max_hair_style = 20;
        battle_config.min_hair_color = 0;
        battle_config.max_hair_color = 9;
        battle_config.min_cloth_color = 0;
        battle_config.max_cloth_color = 4;

        battle_config.castrate_dex_scale = 150;

        battle_config.area_size = 14;

        battle_config.chat_lame_penalty = 2;
        battle_config.chat_spam_threshold = 10;
        battle_config.chat_spam_flood = 10;
        battle_config.chat_spam_ban = 1;
        battle_config.chat_spam_warn = 8;
        battle_config.chat_maxline = 255;

        battle_config.trade_spam_threshold = 10;
        battle_config.trade_spam_flood = 10;
        battle_config.trade_spam_ban = 0;
        battle_config.trade_spam_warn = 8;

        battle_config.sit_spam_threshold = 1;
        battle_config.sit_spam_flood = 15;
        battle_config.sit_spam_ban = 0;
        battle_config.sit_spam_warn = 3;
    }

    fp = fopen_ (cfgName, "r");
    if (fp == NULL)
    {
        printf ("file not found: %s\n", cfgName);
        return 1;
    }
    while (fgets (line, 1020, fp))
    {
        const struct
        {
            char str[128];
            int *val;
        } data[] =
        {
            {
            "warp_point_debug", &battle_config.warp_point_debug},
            {
            "enemy_critical", &battle_config.enemy_critical},
            {
            "enemy_critical_rate", &battle_config.enemy_critical_rate},
            {
            "enemy_str", &battle_config.enemy_str},
            {
            "enemy_perfect_flee", &battle_config.enemy_perfect_flee},
            {
            "casting_rate", &battle_config.cast_rate},
            {
            "delay_rate", &battle_config.delay_rate},
            {
            "delay_dependon_dex", &battle_config.delay_dependon_dex},
            {
            "skill_delay_attack_enable",
                    &battle_config.sdelay_attack_enable},
            {
            "left_cardfix_to_right", &battle_config.left_cardfix_to_right},
            {
            "player_skill_add_range", &battle_config.pc_skill_add_range},
            {
            "skill_out_range_consume",
                    &battle_config.skill_out_range_consume},
            {
            "monster_skill_add_range", &battle_config.mob_skill_add_range},
            {
            "player_damage_delay", &battle_config.pc_damage_delay},
            {
            "player_damage_delay_rate",
                    &battle_config.pc_damage_delay_rate},
            {
            "defunit_not_enemy", &battle_config.defnotenemy},
            {
            "random_monster_checklv",
                    &battle_config.random_monster_checklv},
            {
            "attribute_recover", &battle_config.attr_recover},
            {
            "flooritem_lifetime", &battle_config.flooritem_lifetime},
            {
            "item_auto_get", &battle_config.item_auto_get},
            {
            "drop_pickup_safety_zone",
                    &battle_config.drop_pickup_safety_zone},
            {
            "item_first_get_time", &battle_config.item_first_get_time},
            {
            "item_second_get_time", &battle_config.item_second_get_time},
            {
            "item_third_get_time", &battle_config.item_third_get_time},
            {
            "mvp_item_first_get_time",
                    &battle_config.mvp_item_first_get_time},
            {
            "mvp_item_second_get_time",
                    &battle_config.mvp_item_second_get_time},
            {
            "mvp_item_third_get_time",
                    &battle_config.mvp_item_third_get_time},
            {
            "item_rate", &battle_config.item_rate},
            {
            "drop_rate0item", &battle_config.drop_rate0item},
            {
            "base_exp_rate", &battle_config.base_exp_rate},
            {
            "job_exp_rate", &battle_config.job_exp_rate},
            {
            "pvp_exp", &battle_config.pvp_exp},
            {
            "gtb_pvp_only", &battle_config.gtb_pvp_only},
            {
            "guild_max_castles", &battle_config.guild_max_castles},
            {
            "death_penalty_type", &battle_config.death_penalty_type},
            {
            "death_penalty_base", &battle_config.death_penalty_base},
            {
            "death_penalty_job", &battle_config.death_penalty_job},
            {
            "zeny_penalty", &battle_config.zeny_penalty},
            {
            "restart_hp_rate", &battle_config.restart_hp_rate},
            {
            "restart_sp_rate", &battle_config.restart_sp_rate},
            {
            "mvp_hp_rate", &battle_config.mvp_hp_rate},
            {
            "mvp_item_rate", &battle_config.mvp_item_rate},
            {
            "mvp_exp_rate", &battle_config.mvp_exp_rate},
            {
            "monster_hp_rate", &battle_config.monster_hp_rate},
            {
            "monster_max_aspd", &battle_config.monster_max_aspd},
            {
            "atcommand_gm_only", &battle_config.atc_gmonly},
            {
            "atcommand_spawn_quantity_limit",
                    &battle_config.atc_spawn_quantity_limit},
            {
            "gm_all_skill", &battle_config.gm_allskill},
            {
            "gm_all_skill_add_abra", &battle_config.gm_allskill_addabra},
            {
            "gm_all_equipment", &battle_config.gm_allequip},
            {
            "gm_skill_unconditional", &battle_config.gm_skilluncond},
            {
            "player_skillfree", &battle_config.skillfree},
            {
            "player_skillup_limit", &battle_config.skillup_limit},
            {
            "weapon_produce_rate", &battle_config.wp_rate},
            {
            "potion_produce_rate", &battle_config.pp_rate},
            {
            "monster_active_enable", &battle_config.monster_active_enable},
            {
            "monster_damage_delay_rate",
                    &battle_config.monster_damage_delay_rate},
            {
            "monster_loot_type", &battle_config.monster_loot_type},
            {
            "mob_skill_use", &battle_config.mob_skill_use},
            {
            "mob_count_rate", &battle_config.mob_count_rate},
            {
            "quest_skill_learn", &battle_config.quest_skill_learn},
            {
            "quest_skill_reset", &battle_config.quest_skill_reset},
            {
            "basic_skill_check", &battle_config.basic_skill_check},
            {
            "guild_emperium_check", &battle_config.guild_emperium_check},
            {
            "guild_exp_limit", &battle_config.guild_exp_limit},
            {
            "player_invincible_time", &battle_config.pc_invincible_time},
            {
            "skill_min_damage", &battle_config.skill_min_damage},
            {
            "finger_offensive_type", &battle_config.finger_offensive_type},
            {
            "heal_exp", &battle_config.heal_exp},
            {
            "resurrection_exp", &battle_config.resurrection_exp},
            {
            "shop_exp", &battle_config.shop_exp},
            {
            "combo_delay_rate", &battle_config.combo_delay_rate},
            {
            "item_check", &battle_config.item_check},
            {
            "wedding_modifydisplay", &battle_config.wedding_modifydisplay},
            {
            "natural_healhp_interval",
                    &battle_config.natural_healhp_interval},
            {
            "natural_healsp_interval",
                    &battle_config.natural_healsp_interval},
            {
            "natural_heal_skill_interval",
                    &battle_config.natural_heal_skill_interval},
            {
            "natural_heal_weight_rate",
                    &battle_config.natural_heal_weight_rate},
            {
            "itemheal_regeneration_factor",
                    &battle_config.itemheal_regeneration_factor},
            {
            "item_name_override_grffile",
                    &battle_config.item_name_override_grffile},
            {
            "arrow_decrement", &battle_config.arrow_decrement},
            {
            "max_aspd", &battle_config.max_aspd},
            {
            "max_hp", &battle_config.max_hp},
            {
            "max_sp", &battle_config.max_sp},
            {
            "max_lv", &battle_config.max_lv},
            {
            "max_parameter", &battle_config.max_parameter},
            {
            "max_cart_weight", &battle_config.max_cart_weight},
            {
            "player_skill_log", &battle_config.pc_skill_log},
            {
            "monster_skill_log", &battle_config.mob_skill_log},
            {
            "battle_log", &battle_config.battle_log},
            {
            "save_log", &battle_config.save_log},
            {
            "error_log", &battle_config.error_log},
            {
            "etc_log", &battle_config.etc_log},
            {
            "save_clothcolor", &battle_config.save_clothcolor},
            {
            "undead_detect_type", &battle_config.undead_detect_type},
            {
            "player_auto_counter_type",
                    &battle_config.pc_auto_counter_type},
            {
            "monster_auto_counter_type",
                    &battle_config.monster_auto_counter_type},
            {
            "agi_penaly_type", &battle_config.agi_penaly_type},
            {
            "agi_penaly_count", &battle_config.agi_penaly_count},
            {
            "agi_penaly_num", &battle_config.agi_penaly_num},
            {
            "agi_penaly_count_lv", &battle_config.agi_penaly_count_lv},
            {
            "vit_penaly_type", &battle_config.vit_penaly_type},
            {
            "vit_penaly_count", &battle_config.vit_penaly_count},
            {
            "vit_penaly_num", &battle_config.vit_penaly_num},
            {
            "vit_penaly_count_lv", &battle_config.vit_penaly_count_lv},
            {
            "player_defense_type", &battle_config.player_defense_type},
            {
            "monster_defense_type", &battle_config.monster_defense_type},
            {
            "magic_defense_type", &battle_config.magic_defense_type},
            {
            "player_skill_reiteration",
                    &battle_config.pc_skill_reiteration},
            {
            "monster_skill_reiteration",
                    &battle_config.monster_skill_reiteration},
            {
            "player_skill_nofootset", &battle_config.pc_skill_nofootset},
            {
            "monster_skill_nofootset",
                    &battle_config.monster_skill_nofootset},
            {
            "player_cloak_check_type", &battle_config.pc_cloak_check_type},
            {
            "monster_cloak_check_type",
                    &battle_config.monster_cloak_check_type},
            {
            "gvg_short_attack_damage_rate",
                    &battle_config.gvg_short_damage_rate},
            {
            "gvg_long_attack_damage_rate",
                    &battle_config.gvg_long_damage_rate},
            {
            "gvg_magic_attack_damage_rate",
                    &battle_config.gvg_magic_damage_rate},
            {
            "gvg_misc_attack_damage_rate",
                    &battle_config.gvg_misc_damage_rate},
            {
            "gvg_eliminate_time", &battle_config.gvg_eliminate_time},
            {
            "mob_changetarget_byskill",
                    &battle_config.mob_changetarget_byskill},
            {
            "player_attack_direction_change",
                    &battle_config.pc_attack_direction_change},
            {
            "monster_attack_direction_change",
                    &battle_config.monster_attack_direction_change},
            {
            "player_land_skill_limit", &battle_config.pc_land_skill_limit},
            {
            "monster_land_skill_limit",
                    &battle_config.monster_land_skill_limit},
            {
            "party_skill_penaly", &battle_config.party_skill_penaly},
            {
            "monster_class_change_full_recover",
                    &battle_config.monster_class_change_full_recover},
            {
            "produce_item_name_input",
                    &battle_config.produce_item_name_input},
            {
            "produce_potion_name_input",
                    &battle_config.produce_potion_name_input},
            {
            "making_arrow_name_input",
                    &battle_config.making_arrow_name_input},
            {
            "holywater_name_input", &battle_config.holywater_name_input},
            {
            "display_delay_skill_fail",
                    &battle_config.display_delay_skill_fail},
            {
            "chat_warpportal", &battle_config.chat_warpportal},
            {
            "mob_warpportal", &battle_config.mob_warpportal},
            {
            "dead_branch_active", &battle_config.dead_branch_active},
            {
            "show_steal_in_same_party",
                    &battle_config.show_steal_in_same_party},
            {
            "enable_upper_class", &battle_config.enable_upper_class},
            {
            "mob_attack_attr_none", &battle_config.mob_attack_attr_none},
            {
            "mob_ghostring_fix", &battle_config.mob_ghostring_fix},
            {
            "pc_attack_attr_none", &battle_config.pc_attack_attr_none},
            {
            "gx_allhit", &battle_config.gx_allhit},
            {
            "gx_cardfix", &battle_config.gx_cardfix},
            {
            "gx_dupele", &battle_config.gx_dupele},
            {
            "gx_disptype", &battle_config.gx_disptype},
            {
            "player_skill_partner_check",
                    &battle_config.player_skill_partner_check},
            {
            "hide_GM_session", &battle_config.hide_GM_session},
            {
            "unit_movement_type", &battle_config.unit_movement_type},
            {
            "invite_request_check", &battle_config.invite_request_check},
            {
            "skill_removetrap_type", &battle_config.skill_removetrap_type},
            {
            "disp_experience", &battle_config.disp_experience},
            {
            "castle_defense_rate", &battle_config.castle_defense_rate},
            {
            "riding_weight", &battle_config.riding_weight},
            {
            "item_rate_common", &battle_config.item_rate_common},   // Added by RoVeRT
            {
            "item_rate_equip", &battle_config.item_rate_equip},
            {
            "item_rate_card", &battle_config.item_rate_card},   // End Addition
            {
            "item_rate_heal", &battle_config.item_rate_heal},   // Added by Valaris
            {
            "item_rate_use", &battle_config.item_rate_use}, // End
            {
            "item_drop_common_min", &battle_config.item_drop_common_min},   // Added by TyrNemesis^
            {
            "item_drop_common_max", &battle_config.item_drop_common_max},
            {
            "item_drop_equip_min", &battle_config.item_drop_equip_min},
            {
            "item_drop_equip_max", &battle_config.item_drop_equip_max},
            {
            "item_drop_card_min", &battle_config.item_drop_card_min},
            {
            "item_drop_card_max", &battle_config.item_drop_card_max},
            {
            "item_drop_mvp_min", &battle_config.item_drop_mvp_min},
            {
            "item_drop_mvp_max", &battle_config.item_drop_mvp_max}, // End Addition
            {
            "prevent_logout", &battle_config.prevent_logout},   // Added by RoVeRT
            {
            "alchemist_summon_reward", &battle_config.alchemist_summon_reward}, // [Valaris]
            {
            "maximum_level", &battle_config.maximum_level}, // [Valaris]
            {
            "drops_by_luk", &battle_config.drops_by_luk},   // [Valaris]
            {
            "monsters_ignore_gm", &battle_config.monsters_ignore_gm},   // [Valaris]
            {
            "equipment_breaking", &battle_config.equipment_breaking},   // [Valaris]
            {
            "equipment_break_rate", &battle_config.equipment_break_rate},   // [Valaris]
            {
            "pk_mode", &battle_config.pk_mode}, // [Valaris]
            {
            "multi_level_up", &battle_config.multi_level_up},   // [Valaris]
            {
            "backstab_bow_penalty", &battle_config.backstab_bow_penalty},
            {
            "night_at_start", &battle_config.night_at_start},   // added by [Yor]
            {
            "day_duration", &battle_config.day_duration},   // added by [Yor]
            {
            "night_duration", &battle_config.night_duration},   // added by [Yor]
            {
            "show_mob_hp", &battle_config.show_mob_hp}, // [Valaris]
            {
            "hack_info_GM_level", &battle_config.hack_info_GM_level},   // added by [Yor]
            {
            "any_warp_GM_min_level", &battle_config.any_warp_GM_min_level}, // added by [Yor]
            {
            "packet_ver_flag", &battle_config.packet_ver_flag}, // added by [Yor]
            {
            "min_hair_style", &battle_config.min_hair_style},   // added by [MouseJstr]
            {
            "max_hair_style", &battle_config.max_hair_style},   // added by [MouseJstr]
            {
            "min_hair_color", &battle_config.min_hair_color},   // added by [MouseJstr]
            {
            "max_hair_color", &battle_config.max_hair_color},   // added by [MouseJstr]
            {
            "min_cloth_color", &battle_config.min_cloth_color}, // added by [MouseJstr]
            {
            "max_cloth_color", &battle_config.max_cloth_color}, // added by [MouseJstr]
            {
            "castrate_dex_scale", &battle_config.castrate_dex_scale},   // added by [MouseJstr]
            {
            "area_size", &battle_config.area_size}, // added by [MouseJstr]
            {
            "muting_players", &battle_config.muting_players},   // added by [Apple]
            {
            "chat_lame_penalty", &battle_config.chat_lame_penalty},
            {
            "chat_spam_threshold", &battle_config.chat_spam_threshold},
            {
            "chat_spam_flood", &battle_config.chat_spam_flood},
            {
            "chat_spam_ban", &battle_config.chat_spam_ban},
            {
            "chat_spam_warn", &battle_config.chat_spam_warn},
            {
            "chat_maxline", &battle_config.chat_maxline},
            {
            "trade_spam_threshold", &battle_config.trade_spam_threshold},
            {
            "trade_spam_flood", &battle_config.trade_spam_flood},
            {
            "trade_spam_ban", &battle_config.trade_spam_ban},
            {
            "trade_spam_warn", &battle_config.trade_spam_warn},
            {
            "sit_spam_threshold", &battle_config.sit_spam_threshold},
            {
            "sit_spam_flood", &battle_config.sit_spam_flood},
            {
            "sit_spam_ban", &battle_config.sit_spam_ban},
            {
            "sit_spam_warn", &battle_config.sit_spam_warn}
        };

        if (line[0] == '/' && line[1] == '/')
            continue;
        if (sscanf (line, "%[^:]:%s", w1, w2) != 2)
            continue;
        for (i = 0; i < sizeof (data) / (sizeof (data[0])); i++)
            if (strcmpi (w1, data[i].str) == 0)
                *data[i].val = battle_config_switch (w2);

        if (strcmpi (w1, "import") == 0)
            battle_config_read (w2);
    }
    fclose_ (fp);

    if (--count == 0)
    {
        if (battle_config.flooritem_lifetime < 1000)
            battle_config.flooritem_lifetime = LIFETIME_FLOORITEM * 1000;
        if (battle_config.restart_hp_rate < 0)
            battle_config.restart_hp_rate = 0;
        else if (battle_config.restart_hp_rate > 100)
            battle_config.restart_hp_rate = 100;
        if (battle_config.restart_sp_rate < 0)
            battle_config.restart_sp_rate = 0;
        else if (battle_config.restart_sp_rate > 100)
            battle_config.restart_sp_rate = 100;
        if (battle_config.natural_healhp_interval < NATURAL_HEAL_INTERVAL)
            battle_config.natural_healhp_interval = NATURAL_HEAL_INTERVAL;
        if (battle_config.natural_healsp_interval < NATURAL_HEAL_INTERVAL)
            battle_config.natural_healsp_interval = NATURAL_HEAL_INTERVAL;
        if (battle_config.natural_heal_skill_interval < NATURAL_HEAL_INTERVAL)
            battle_config.natural_heal_skill_interval = NATURAL_HEAL_INTERVAL;
        if (battle_config.natural_heal_weight_rate < 50)
            battle_config.natural_heal_weight_rate = 50;
        if (battle_config.natural_heal_weight_rate > 101)
            battle_config.natural_heal_weight_rate = 101;
        battle_config.monster_max_aspd =
            2000 - battle_config.monster_max_aspd * 10;
        if (battle_config.monster_max_aspd < 10)
            battle_config.monster_max_aspd = 10;
        if (battle_config.monster_max_aspd > 1000)
            battle_config.monster_max_aspd = 1000;
        battle_config.max_aspd = 2000 - battle_config.max_aspd * 10;
        if (battle_config.max_aspd < 10)
            battle_config.max_aspd = 10;
        if (battle_config.max_aspd > 1000)
            battle_config.max_aspd = 1000;
        if (battle_config.max_hp > 1000000)
            battle_config.max_hp = 1000000;
        if (battle_config.max_hp < 100)
            battle_config.max_hp = 100;
        if (battle_config.max_sp > 1000000)
            battle_config.max_sp = 1000000;
        if (battle_config.max_sp < 100)
            battle_config.max_sp = 100;
        if (battle_config.max_parameter < 10)
            battle_config.max_parameter = 10;
        if (battle_config.max_parameter > 10000)
            battle_config.max_parameter = 10000;
        if (battle_config.max_cart_weight > 1000000)
            battle_config.max_cart_weight = 1000000;
        if (battle_config.max_cart_weight < 100)
            battle_config.max_cart_weight = 100;
        battle_config.max_cart_weight *= 10;

        if (battle_config.agi_penaly_count < 2)
            battle_config.agi_penaly_count = 2;
        if (battle_config.vit_penaly_count < 2)
            battle_config.vit_penaly_count = 2;

        if (battle_config.guild_exp_limit > 99)
            battle_config.guild_exp_limit = 99;
        if (battle_config.guild_exp_limit < 0)
            battle_config.guild_exp_limit = 0;

        if (battle_config.castle_defense_rate < 0)
            battle_config.castle_defense_rate = 0;
        if (battle_config.castle_defense_rate > 100)
            battle_config.castle_defense_rate = 100;
        if (battle_config.item_drop_common_min < 1) // Added by TyrNemesis^
            battle_config.item_drop_common_min = 1;
        if (battle_config.item_drop_common_max > 10000)
            battle_config.item_drop_common_max = 10000;
        if (battle_config.item_drop_equip_min < 1)
            battle_config.item_drop_equip_min = 1;
        if (battle_config.item_drop_equip_max > 10000)
            battle_config.item_drop_equip_max = 10000;
        if (battle_config.item_drop_card_min < 1)
            battle_config.item_drop_card_min = 1;
        if (battle_config.item_drop_card_max > 10000)
            battle_config.item_drop_card_max = 10000;
        if (battle_config.item_drop_mvp_min < 1)
            battle_config.item_drop_mvp_min = 1;
        if (battle_config.item_drop_mvp_max > 10000)
            battle_config.item_drop_mvp_max = 10000;    // End Addition

        if (battle_config.night_at_start < 0)   // added by [Yor]
            battle_config.night_at_start = 0;
        else if (battle_config.night_at_start > 1)  // added by [Yor]
            battle_config.night_at_start = 1;
        if (battle_config.day_duration < 0) // added by [Yor]
            battle_config.day_duration = 0;
        if (battle_config.night_duration < 0)   // added by [Yor]
            battle_config.night_duration = 0;

        if (battle_config.hack_info_GM_level < 0)   // added by [Yor]
            battle_config.hack_info_GM_level = 0;
        else if (battle_config.hack_info_GM_level > 100)
            battle_config.hack_info_GM_level = 100;

        if (battle_config.any_warp_GM_min_level < 0)    // added by [Yor]
            battle_config.any_warp_GM_min_level = 0;
        else if (battle_config.any_warp_GM_min_level > 100)
            battle_config.any_warp_GM_min_level = 100;

        if (battle_config.chat_spam_ban < 0)
            battle_config.chat_spam_ban = 0;
        else if (battle_config.chat_spam_ban > 32767)
            battle_config.chat_spam_ban = 32767;

        if (battle_config.chat_spam_flood < 0)
            battle_config.chat_spam_flood = 0;
        else if (battle_config.chat_spam_flood > 32767)
            battle_config.chat_spam_flood = 32767;

        if (battle_config.chat_spam_warn < 0)
            battle_config.chat_spam_warn = 0;
        else if (battle_config.chat_spam_warn > 32767)
            battle_config.chat_spam_warn = 32767;

        if (battle_config.chat_spam_threshold < 0)
            battle_config.chat_spam_threshold = 0;
        else if (battle_config.chat_spam_threshold > 32767)
            battle_config.chat_spam_threshold = 32767;

        if (battle_config.chat_maxline < 1)
            battle_config.chat_maxline = 1;
        else if (battle_config.chat_maxline > 512)
            battle_config.chat_maxline = 512;

        if (battle_config.trade_spam_ban < 0)
            battle_config.trade_spam_ban = 0;
        else if (battle_config.trade_spam_ban > 32767)
            battle_config.trade_spam_ban = 32767;

        if (battle_config.trade_spam_flood < 0)
            battle_config.trade_spam_flood = 0;
        else if (battle_config.trade_spam_flood > 32767)
            battle_config.trade_spam_flood = 32767;

        if (battle_config.trade_spam_warn < 0)
            battle_config.trade_spam_warn = 0;
        else if (battle_config.trade_spam_warn > 32767)
            battle_config.trade_spam_warn = 32767;

        if (battle_config.trade_spam_threshold < 0)
            battle_config.trade_spam_threshold = 0;
        else if (battle_config.trade_spam_threshold > 32767)
            battle_config.trade_spam_threshold = 32767;

        if (battle_config.sit_spam_ban < 0)
            battle_config.sit_spam_ban = 0;
        else if (battle_config.sit_spam_ban > 32767)
            battle_config.sit_spam_ban = 32767;

        if (battle_config.sit_spam_flood < 0)
            battle_config.sit_spam_flood = 0;
        else if (battle_config.sit_spam_flood > 32767)
            battle_config.sit_spam_flood = 32767;

        if (battle_config.sit_spam_warn < 0)
            battle_config.sit_spam_warn = 0;
        else if (battle_config.sit_spam_warn > 32767)
            battle_config.sit_spam_warn = 32767;

        if (battle_config.sit_spam_threshold < 0)
            battle_config.sit_spam_threshold = 0;
        else if (battle_config.sit_spam_threshold > 32767)
            battle_config.sit_spam_threshold = 32767;

        // at least 1 client must be accepted
        if ((battle_config.packet_ver_flag & 63) == 0)  // added by [Yor]
            battle_config.packet_ver_flag = 63; // accept all clients

        add_timer_func_list (battle_delay_damage_sub,
                             "battle_delay_damage_sub");
    }

    return 0;
}