summaryrefslogblamecommitdiff
path: root/src/map/atcommand.cpp
blob: 55596b3aed61a678ca9b1286f1e52cc3cb8713a1 (plain) (tree)
1
2
3
4
5
6
7
8
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
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

                        
                


                  

                                 



                                 


                          
                             
                                 

                                        
                            
                               
                               
                               
                              
                               
                                
 
                     
                    
                   




                     
                    
                 

                     
                      
                  
                    
 

                        









               

                    
                 
              

                                                                               
 

                                                                                                         
      

  







                                              
                                      

















                                                                               
                               
 
                       





















                                                                           

 
 








































                                                                                            
      
                             
 
                                                              
 
                                      



                                    


                                                   
                                                
                   
                                    

                                                   
 
 
               
 
                            
 
                
                    
 
                                   
 


                                         
 
                                                      

                                      
                                
                                 
 
                                                
                                 
 
                   
                           
 
                                                             
 


                              
                           
     
                            

 
                                                              
                                   
 
                           
 
                                 
                     
 



                                    
                                             
 








                                                                                                          

              
                                                              
                                  
                                        

                             
     







                                                                                      
 
     
         

                                               
             


                                             
                                               















                                                                                                        

             
 
                    
     

 
                                     
 
                            
     

                                                           
                  
     
                   

 
      
                                                         
 
                    
 
                                         
             
                                        
        
                       

 
      
                                                     
 
                                       

 
                                          
 
                             
                      
     
                                                                          

                 
 
                 
                            
     

                   
                                             
                     
                                                        

                      
                                        




                                  
                                
                                      

                                                        
     
 
             

 


                                  












                                                                               




























                                                                                                     
                                       

















                                                                                                
                                       


                      
 

                                                                 
                        
 
                  
                       
 
                                             
                           
            
 
                
                                          
                                               
 
                                               
                                               
 
                  
                                         
                                       

                  
                                         
                                       

                  
                                   
                                       
 
                                               
                                    
 
                      

 

                                                                    
                        
 

                       
                     
 
                                                        
                           

               
                                
               
                                
 

                                                              
     
                                          

                                                        
                                                     
             

                                                           
                                                                         
                 
                                           
                                                                                   
                                      
                 
                                                           
                                                                         
                 
                                           
                                                                                               
                                      
                 
                                                                                  
                 

                                                                                            


                    
                                                              
                                       



                 
                                                                     
                                   



             
                                                                                                           
                              



         
                                                        
                           

     
                      

 

                                                                
                        
 
                     
                     
 

                                                                
     
                               
                                                                         
                           
     
 
               
                                
               
                                
 
                                             
     

                                                   
                                                                 
         
                                   
                                                                       
                              
         
                                             
                                                                 
         
                                   
                                                                                
                              
         
                                                                       
                                               

            
                                                      
                               



         
                                                             
                           
     
 
                      

 

                                                                 
                        
 

                                 
 

                                                                                            
                                        
                                                        
                                             

                                                
                                                    
                                   
                                                           
                                        


        
                                                        
                           
     
 
                      

 

                                                                
                        
 
                       
 
                                     
     
                               
                                                                                           
                           
     
 

                                                              
     
                                                     
                                                                 
         
                                   
                                                                                     
                              
         
                                             
                                                                 
         
                                   
                                                                                
                              
         
                                                                                         
                                                            
                                        


        
                                                        
                           
     
 
                      

 

                                                                
                        
 
                     

                                          
 
               
                                
               
                                
                                             
     
                                               
                                                                 
         
                                   
                                                                              
                              
         
                                             
                                                                 
         
                                   
                                                                                
                              
         
                                                                  
                                                          
                                        


        
                                                             
                           
     
 
                      

 

                                                               
                        
 
              
                              

                                       

              
                           
                                    
     

                        
                                                                                                                                       
                                       
         
                                         

                                               
                                                               
                                              

                                                        

                                                                         

                                                    
                                   
                                        


                                                                        
                                                                           
                        

                                                                
                                                                    
                                                          
                                                    






                            
                                                    
                        
                                                   

        
                                                               
                                        

     
                      

 

                                                                    
                        
 
              
                              

                    

                                       

              
                           
                                    
     

                        
                                                                                                                                       
                                       
         
                                         

                                               
                                                               
                                              

                                                        

                                                                         

                                                    
                                                             

                                                                                 
                                        


                                                                        
                                                    






                            
                                                    
                        
                                                   

        
                                                               
                                        

     
                      

 

                                                                  
                        
 
              
                              
                      
 
     

                                    

                                             
                              


              
                           
                                    
     

                        
                                                                                                                                       
                                       
         
                                         

                                               
                                                               
                                              

                                                        
                                          
                 
                                   
                                        


                                                                        
                                                                           
                        

                                                                
                                                                    
                                                          
                                                    





                            
                                                               
                                  
                                    
 
                      

 

                                                                       
                        
 
              
                              

                    
                      
     

                                    

                                             
                              


              
                           
                                    
     

                        
                                                                                                                                       
                                       
         
                                         

                                               
                                                               
                                              

                                                        
                                          
                 
                                                             

                                                                                 
                                        

                                                                            
                        

                                                                    
                                                    





                            
                   
                   
                                                                          
                        
                                                                         

        
                                                                                  
     
                                    
 
                      

 

                                                                 
                        
 
              
                              

                    

                                       

              
                           
                                    
     

                        
                                                                                                                                       
                                       
         
                                         



                                                   
                                                                   
                                                  

                                                            

                                                                             

                                                        
                                       


                                                                        
                                                                           
                                                        


                                                                      
                                               
                                                         

                                                                 
                                                                                     


                                                     
                                                        







                                
                                                
                        
                                               

        
                                                           
                                        

     
                      

 

                                                                
                
 
                                                          


                                                                   
 
                      

 

                                                                
                
 
                                                                 
                                        
                                                             
     
                               
                                                                                     
                          
     
                                         
                                                             
     
                               
                                                                                         
                          
     
 
                                                                      
                                                              
                                                         
 
                      

 

                                                                 
                        
 
                 
     
                                   
                                                                       

                                                               
                                        
                           
     
 
                                                                      



                                                           
                                   
                                         
                                                  


        
                                   
                                                                             

                                                               
                                        
                           
     
 
                      

 

                                                                   
                
 
                         
 
                               
     
                                                  
                           
     
 
                                                                

                                     
                                                  
                           
     
 
                            
 
                      

 

                                                                  
                        
 




                                                                     
                           


                      
                               
 
                          

                                                
 
                      

 

                                                                
                
 
                                               
     
                                           
                                                   


        
                                          
                                                  
     
                          
 
                      

 

                                                               
                
 

                                                    
 
                      

 

                                                                
                        
 
                       
 
                                     
                           
 

                                                              
     
                                          

                                                    

                                                         


            
                                                                                                           
                              



         
                                                        
                           
     
 
                      

 

                                                                 
                
 

                                      
                    

                                                                                                 

                                  
                             
                                                                    
 
                      

 

                                                          
                        
 
                 
                           
 
                             
 
                      

 

                                                                
                        
 
                       
 
                                            
 






                                               

                                                                                           
                                                   

                                                                                 
                                   

                                                                                           
                                                   

                                                                                 

                                   
 

                              
                                                                                                                


                           
                            
                               
                                                         
            
                                                              


        
                                                                              
                           
     
 
                      

 

                                                                
                        
 
                       
                            
                                       
                     
 
                                                               
     
                               
                                                                                              
                           
     
 



                    
                                                             
                                                                     




                                    



                                                 




                                               
                                    

                                      
                            
                                                             
                                    
                                             
         
                                                 


        
                                                            
                           
     
 
                      

 

                                                                     
                
 
          
 


                                          
                                                           
                                                                 
     
                                                                    
 
                      

 

                                                                  
                
 
                     
 
                      

 

                                                                       
                        
 
                 
 
                                            
     
                               
                                                                                        
                           




                                                                 
         
                                                                       



                                                                                                                 



                                                                            


                                               

                                                          
                               
                                                      




                                       
                                                                      
                               
         

                                                                                        







                                                         
                                                   

                                                  
                                       

                                               

                                                       

     
                      
 
 
                                                  
                                              

                                                                      
                        
 
                             
 
                                            
                           
 
                   




                                             
                                                                      
                               
         

                                                                          

                                                    

                                              
                                        
                                              
                             
                               
                                                     




                                      
                                                                     
                               
         

                                                                    

                                             

                                              




                                            
                                                  

                                                   

                                                      

     
                      

 

                                                              
                        
 
                 
                           
 
                    

                                                                                          
                                                                    
                          

        
                                                       
 
                      

 

                                                                  
                
 
                              

                                                           
                                                                          
                           
     
 
                           
     
                               



                                        
                                                                                                                                           
                                           
             
                                            
                 
                                              


                 
                                             


        
                                                       
                           
     
 
                      

 

                                                                 
                
 
                              

                                                           
                                                                          
                           
     
 
                                                     
     
                               
                                        
         

                            
                                                                                                                                           
                                           
             
                                                                 
                 
                                                                                        
                                                                                            





                                             
                                            


        
                                                      
                           
     
 
                      

 

                                                                 
                        
 
                                                        
 
                                                                                  
                           
 



                                                                         
         


                                                                
                                                           


         
                           
 
                      

 

                                                               
                        
 
                        
 
                                        
                           
 

                                                                         
         
                                                                
                                                           


         
                           
 
                      

 

                                                                      
                        
 
                       
 
                                       
                           
 

                                                                     
         
                                                      
                                                           


         
                           
 
                      

 

                                                                      
                        
 
                       
 
                                       
                           
 

                                                                     
         
                                                            
                                                           


         
                           
 
                      

 

                                                                 
                        
 
                    





                      
 
                                                                     
                           

                                                    

                                                                         
                                                      

                    
                           
 



                                                                                                                                                         


                                                                 

                              

                                                              

              
                             

                                                     




                                 

                                                                       
                       
                                                                    


                       
                                                                   

                       
                                                                                           





                                  
                                                             

            
                                                                 
                           
                                            


         
                                                               
                           

     
                      

 
      
                                                                           
                                        
 
                      
     

                                    

                                             
                              
     
 




                                                                 
 
                                                    

 

                                                                       
                        
 
                                                  
 
                      

 
      
                                                       
 
                    
 
                                        
                                          
                                 

 

                                                                       
                
 
                                               
                                                               



                                       
 
                      

 

                                                                        
                        
 
                                                  
 
                      

 

                                                               
                
 
          
 

                             
                                   
                                                             
                                                            




                                                                   
                                        
     
 
                      

 

                                                               
                        
 

                         
 
                                                     
                           
 
                                       
 
                      

 

                                                                       
                        
 
                                
 
                                                
                           
 
                                                       

                                                                   
                                  

                                                                    

                             
                                                    
     
                                                   
                                               
                                                                    

        
                           
 
                      

 

                                                                      
                        
 
                               
 
                                                
                           
 
                                                     

                                                                  
                                 

                                                                   

                            
                                                  
     
                                                 
                                              
                                                                   

        
                           
 
                      

 

                                                                
                        
 
                       
 
                                              
                           
 
                                      

                                                             
                            

                                                            




                                    
                                        
                                                            

        
                           
 
                      

 
                   
                                                                 
                        
 
                             
 
                                 
                      
                           
 
                                               

                                                                                                      
                                                

                                                                                  

                      
                                            
     


                                                 

                                                 

        
                           
 
                      

 

                                                                     
                        
 
                                    
 
                                 



                                            
                           
     
                                                   

                                                                                                          
                                                    

                                                                                      

                          
                                                
         


                                                     
                                 


                    
 

                                      
                                                      
        
                           
 
                      

 

                                                                  
                        
 
                       
 
                                     
                           
 

                                                              
     
                                          

                                                      
                                                   
                                                                     
             
                                       
                                                                                       
                                  
             
                                                       
                                                                     
             
                                       
                                                                                           
                                  
             
                                                                                     
                                                                  
                                            


            
                                                                                                           
                              



         
                                                        
                           

     
                      

 

                                                                  
                        
 
                       
 
                                     
                           
 

                                                              

                                                
                           

                                                                                                     

                                         
                                    
                                                      


        
                                                        
                           
     
 
                      

 

                                                                        
                        
 
                       
 
                                     
                           
 

                                                              
     
                       
                                                              
                                        
                                                                        
                                        
                                                                                     
                                        
                                                        
                                        
                                                               
                                        
                                                        
                                        
                                                               
                                        
                                                                        
                                        
                                                                        
                                        
                                                                        
                                        
                                                                        
                                        
                                                                        
                                        
                                                                        
                                        
                                                            
                                        


        
                                                        
                           

     
                       

 

                                                                            
                
 
              
 
              
                                    
     

                        
                                                                                                                                       
                                       
         
                            
                                   
                                                                    
                

                              
                           
                               
                                                                                                
                                                                 
                                            

                                                            
                                            








                                                                                                         

                                                


                    
 
                   
                                                    
                        
                                                   

        
                                                               
                                        
     
 
                      

 

                                                                            
                        
 




                                                          
                           
 

                                                              
     
                                          

                                                                


                                        
 
                                     

                                                                    


            
                                                                                                           
                              



         
                                                        
                           

     
                      

 

                                                                           
                        
 
                       
 
                                     
                           
 
     

                                                                                  
                                                                                  
     
 
                      

 

                                                                      
                        
 
                       
 
                                     
                           
 
     

                                                                                  
                                                                                  
     
 
                      

 

                                                                    
                        
 

                        
 

                                            
                           
 
     

                                                                        
                                                                                  

     
                      

 

                                                                        
                        
 
                       
 
                                     
                           
 

                                                      

                                                                                  
                                                                                  
     
 
                      

 

                                                                      
                        
 
                       
 
                                     
                           
 

                                                      

                                                                                  
                                                                                  
     
 
                      

 

                                                                          
                        
 

                       
                     
 

                                                       
                           
 

                                                              
     
                                          



                                                                       
             
                                                          
                                   


                
                                                    
                                                                         
                 
                                           
                                                                                     
                                      
                 

                                                                              



             
                                                                                                           
                              



         
                                                        
                           

     
                      

 

                                                                
                
 
                                    
     

                        
                                                                                                                                       
                 
                                           
                                             

                                                       

                                                                                      

         
                                                   
 
                      

 

                                                                   
                
 
                                    
     

                        
                                                                                                                                       
                 
                                                                      
                                             

                                                       

                                                                                      

         
                                                   
 
                      

 
      
                                                       
 
                                              


                                          
                        

                                      
                                 
                                                             
     

 

                                                              
                
 
                                    
     

                        
                                                                                                                                       
                                   
     
                                                       
 
                      

 

                                                                    
                
 
                                    
     

                        
                                                                                                                                       
                 
                                                            
                                       
     
                                                       
 
                      

 

                                                                               
                        
 
                       
                     
 
                                            
                      
                           
 

                                                              
     
                                          

                                                                    


                                                                            
                 
                                                                                           



                                                                                                                            






                                                                


                                                          

                                                                           
                                          
                                                                          




                                                  
                                                                                          
                                       
                 

                                                                                                   







                                                                    
                                                              

                                                          

                                                  


                                                          

                                                                           
             
                                                                            
                                                                  


            
                                                                                                           
                              



         
                                                        
                           

     
                      

 

                                                                              
                        
 
                       
                                  
 
                                            
                      
                           
 

                                                              
     
                                          


                                                                   




                                                         
                                                                                          
                                       



                                                                

                                                         
                                                   
                                                         
                                        
                                          
                                                                         




                                                 
                                                                                         
                                       



                                                        

                                                         




                                                       
                                                             

                                                           

                                                                          



             
                                                                                                           
                              



         
                                                        
                           

     
                      

 

                                                                
                        
 
                       
 
                                     
                           
 

                                                              
     

                                                       
                                       

            
                                                                                                           
                              



         
                                                        
                           
     
 
                      

 

                                                                   
                
 
                                    
     

                        
                                                                                                                                       
                 
                                                                  

                                                       
                                                                  
                                           

         
 
                                                             
 
                      

 

                                                                      
                        
 
                     
 
                                     
                           
 
                                                                      
     
                                            
         
                                                 
             

                                                                       


                
                                                                              
                                   



             
                                                                                               
                               



         
                                                                    
                           
     
 
                      

 

                                                                       
                        
 

                       
 
                                                
                           
 
                                                                      
     
                                            
         

                                                                      
             
                                                        
                 

                                                                                  


                    
                                                                                         
                                       



                 
                                                                
                                   



             
                                                                                               
                               



         
                                                                    
                           

     
                      
 
 

                                                                     
                        
 
                     
 
                                     
                           
 
                                                          
     
                                            
         
                                                

                                                  
                                                                    

                                                                         


                
                                                                            
                                   



             
                                                                                               
                               



         
                                                                    
                           
     
 
                      

 

                                                                      
                        
 

                       
 
                                                
                           
 
                                                          
     
                                            
         

                                                                      
             
                                                       

                                                         
                                                                           

                                                                                    


                    
                                                                                          
                                       



                 
                                                                
                                   



             
                                                                                               
                               



         
                                                                    
                           

     
                      

 

                                                              
                        
 
                    
 
                                            
                           
 
                            
 
                      

 

                                                                
                
 
                                    
     

                        
                                                                                                                                       
                                       

                                                                  
                                           

         
                            
 
                
 
                      

 

                                                                 
                        
 
                       
                 
                           
 
                                                    
                           
 
                                                                                      
                                    


                               
                                             
                                                   

                    
                                                                    
                                            

         
                                                        
                                    
 
                      

 

                                                                       
                        
 
                       
 
                                     
                           
 

                                                              
     
                                          

                                                                     
                                 
                                       
                                                             
                                            


            
                                                                                                           
                              



         
                                                        
                           
     
 
                      

 

                                                                       
                        
 
                       
 
                                     
                           
 

                                                              
     
                                          

                                                                     
                                 
                                       

                                                 
                                            


            
                                                                                                           
                              



         
                                                        
                           
     
 
                      

 

                                                                     
                        
 
                       
 
                                     
                           
 

                                                              
     
                                          

                                                                        

                                 



                                                                         
                                       
                                                                       
                                            


            
                                                                                                           
                              



         
                                                        
                           
     
 
                      

 

                                                                     
                        
 
                       
 
                                     
                           
 

                                                              
     
                                          

                                                                        
                  



                                         


                                                      



                                        


                                                     


                                    
                                               





                                                   

                                                                  
                                                                            




                                   

                               

                              
                                        

                               
                                        

                                     


                                    



                                                                         
 
                                                                 
                                            


            
                                                                                                           
                              



         
                                                        
                           

     
                      

 

                                                                  
                        
 

                                                             
 
                                                                             
                           
 

                                                              




                                                                             
             


                                                                       
                                                               


             
                               


        
                                                        
                           

     
                      

 

                                                                    
                        
 
                       

                        
 
                                            
                      
                           
 

                                                              
     
                                                            

                                                                      
                                     

                                                                       
                                
                                                         

                                                        
                                                     
                                                                                   

            
                               


        
                                                        
                           

     
                      

 

                                                                    
                        
 
                       

                         
 
                                            
                      
                           
 

                                                              
     
                                                              

                                                                       
                                      

                                                                        
                                 
                                                           

                                                          
                                                      
                                                                                    

            
                               


        
                                                        
                           

     
                      

 

                                                                 
                        
 
                       
                           
 
                                                         
                           
 

                                                              

                                             

                                                                 
                                

                                                                



                                           
                                               
                                                                            

            
                               


        
                                                        
                           
     
 
                      

 

                                                                     
                
 
              
 
                                           
                                                             
     
                               
                                                                               
                          
     
 
              
                                    
     

                        
                                                                                                                                       
                 

                                                                
                                             

                                                      
                                                       
                                                                     

                        
                                                                                         

         
 
                                                        

              
                                   

                                                                                                              
                                        
     
 
                      

 

                                                                       
                        
 
                         
                    
              
 
                                                      
                           
 
                                           
                                                             
     
                               
                                                                               
                          

     

                                                                      
                                                          

                  
                                        
         

                            
                                                                                                                                           
                                          


                                                                    
                                                           
                                                                         

                            
                                                                                             

             
                                                                                                   
                                        

                  


                                                                                                                  
                                            



         
                                                                                             
                           

     
                      

 

                                                                     
                
 

                                                       
 
                      

 

                                                                    
                
 

                                                          
 
                      

 

                                                                      
                
 

                                                        
 
                      

 

                                                                     
                
 

                     
 
                          
 
                                                 
 
                      

 

                                                                   
                
 
                       
 
                                                                                         
 
                      

 

                                                                   
                        
 
                                 
                     
                                 
                 
 
                                                    
 

                             
 

                                
 

                                                  
                           
 
                                                      
                                                         
                                    
                                                          
                                    
                                                         
                                    
                                                       
                                                             

                                                          
                                    
                                            
                                                       
                                    
                                     
                                                     
                                    
                                        
                                                        
                                    
                                       
                                                       
                                    
                                     
                                                     
                                    
                                         
                                                         
                                    
                                                 
                                                                 
                                    
                                             
                                                            
                                    






                                                              
                                                                  
                                            
             

                                
                                                                                                                                               
                                              
                                                   
                 
                                       

                                                                             
                                                    



                  
                                                               
                                               
             
                                  

                                
                                
                                            
                              
                                 
                                                 
                              
                                
                                           
                              
                                 
                                                 
                              
                                
                                            
                              
                                 
                                                 
                              
                                
                                           
                              
                                 
                                                 
                              
     
                           
                                            
                              
      
                            
                                              

                              
                                   
                                                                                     

                                                                           
                                                

                  

                                                 
                                   
                                                                                                 
                               

     
                      

 

                                                                    
                        
 
                         
 
                                       
                           
 
                    

                                                                      
                                                          



                                        
                                                                                     
                                            



                                       
                                                                           
                                            



         
                                                                                             
                           
     
 
                      

 

                                                                  
                        
 
                    
 
                                                
                           
 
                                     
     

                                                


        
                                                           
                           
     
 
                      

 

                                                                   
                        
 
                    
 
                                                
                           
 
                                     
     

                                                 


        
                                                           
                           
     
 
                      

 

                                                                   
                
 

                                   
                                                       
                                  
 
                      

 

                                                                       
                        
 

                       
                                                     

                                
                                                                        
                           

                
                                                             
                                                                     



                                    

                                                                  
         
                                              

                                                        
                                                                    




                                                                      
                                                               
                                

                                                                            
                     
                                               

                                                          
                                                           
 
                                        
                                                                                         
                        
                                                                                                                        
                                                    


                    
                                                                                 
                                       



                 
                                                                                                               
                                  



             
                                                            
                               



         
                                                            
                           

     
                      

 

                                                                  
                        
 
                 
                           
 
                                                                    
                            
 
                      

 

                                                                       
                        
 
                 
                           
 
                                                                    
 
                                  
 
                      

 

                                                                 
                        
 

                              
 
                                                                  
                           
 
                                    
     

                                                                                                   
     
                                      
     
                                                                                  
                           
     
                                        
     
                                                                    
                           
     
                                       
     
                                                                                     
                           


        

                                                                                       
     
 
                      

 

                                                                  
                        
 
                           
 
                                                     
                           

                  
                                           
                                                            


        
                                        
         

                            
                                                                                                                                           
                                           
             
                                                      
                                                                           


             
 
                      

 

                                                                               
                        
 
                                                   
                                       
                       
 
                                     
                           
 

                                                              
     
                                          

                                                          





                                                         
                                                                            





                                                                          
                                                   

                                                                   
                                                        
                     


                                                                  
                     
                                                  
                                                       
                                                          
                                                     
                                                           
                                                      
                                                       
                                                                                    
                                                       
                                                                                    
                                                      
                                                                                                     
                                                       
                                                      
                                                 
                                                      
                                                            
                                                                                           
                                                       
                                                                                          
                                                     
                                                                                                         
                                                           
                                                                                            
                                                     
                                                                                                           
                                                           
                                                                                                                       
                                                               
                                            
                                             

                        
                                             
 
                                   
                                                       
                                                                           




                                                                   

                                                                   
                        
                                                                   

                                                                   

                                                                   
                                                    
 
                                    





                                                               
                                                             


                                                                         



                                                            


                                                              
                                    
                                                         



                                                              


                             
                                
                     
                                                


                                                                  



                           
                                                                         

                
                                           

                                                                   
                                                



             
                                                                                                           
                              



         
                                                        
                           

     
                      

 

                                                                                  
                        

                         
                                                   
                                       
                       
 
                                     
                           
 

                                                              
     
                                          

                                                          
                                                                            






                                                    
                                                                             




                                                                     


                                                                               
                                                            
                         
                                       
                                                     
                                                                            






                                                               
                                                                    


                                                                       
                                                        
 
                                        





                                                             
                                                         


                                                                            



                                                                


                                                                  
                                        
                                                             



                                                                  


                                 
                                    
                         
                                                


                                                                      



                               
                                           
                                                                            

                    


                                                                       
                                                    



                 
                                                                       
                                  



             
                                                                                                           
                              



         
                                                        
                           

     
                      

 

                                                                               
                        
 
                                                   
                                       
                       
 
                                     
                           
 

                                                              
     
                                          

                                                          





                                                    
                                                                             




                                                                     
                                                   

                                                                        
                                                        
                     
 
                                   
                                                     






                                                                        
                        




                                                                  
                                                    
 
                                    





                                                          
                                                             

                                                                          



                                                            


                                                              
                                    
                                                         



                                                              


                             
                                
                     


                                                                  



                           
                                       
                                                                     

                
                                                                                      
                                         
                                                



             
                                                                                                           
                              



         
                                                        
                           

     
                      

 

                                                                  
                
 
                                                         
 
                                 
                                                     
        
                                                         
 
                      

 

                                                                   




                                     
                           


                                                              
                           













                                                                     
                      

 

                                                                    
                
 
                                                             
 
                                   
                                                         
        
                                                     
 
                      

 

                                                                     
                        
 
                       
 
                                     
                           
 

                                                              
                           
 
                                                                   
 
                                      
                                                              
        
                                                                    
 
                      

 

                                                             
                        
 
                      
                     
                              
 
                                             
                           
 
                                
                   
                           
 
                             

                 
                             
 
                      

 

                                                                   
                        
 

                    
 
                                                         
                           
 


                                                                            
 

                                                              


                           
 
                                                         
                                    
 
                      

 

                                                                   
                        
 
                    
                 
 
                                         
                           
 

                                                           
                           
 
                                       
                                                        
 
                      
 
 

                                                                
                
 
          



                                           

                                                       
                                                               

         
                      
 
 

                                                                    
                        
 
                       
 
                                     
                           

                                                              
                           
                                           


                                              

                                                          
                                                                     

         
 

                                                                
                                                             
 
                      
 
 

                                                                    
                
 
          
 
                                

                       
                                        
         

                           
                                                                    


                                  
                                       
                                                                 
                                   





                                           

                                                       
                                                                      

         
                             
 
                                          
                      
 
 

                                                                        
                        
 
                       
 
                                     
                           

                                                              
                           
 
                                        
     

                                                                
                               
                                                                
                                                            
                          
     
                                           


                                              

                                                          
                                                                         

         
                                
 
                                  
                                                                      
                                  
                                                        
                                                           
 
                                          
 
                      
 
 

                                                             
                
 
                  
                
                                         
                           
 
                            
                                     
                      
 
 

                                                             
                
 
                  
                
                                         
                           
 
                            
                                     
                      

 

                                                               
                
 
                  
                
                                           
                           
 
                              
                                     
                      

 

                                                            
                
 
                  
                
                                        
                           
 
                           
                                     
 
                      

 

                                                               
                
 
                  
                
                                           
                           
 
                              
                                     
                      
 
 

                                                               
                        
 
                 



                   
                            
 
                                          
                           
 
                                           
                                        
                    
                           
 

                                      
 
                                                                                      
                                              
           
     
                                  
                                     
                                                                    
                                                               

                                                           
                                 
     
 
                      

 

                                                                  
                        
 

                
 
                                                      
     
                                                                      
                           

     


                                                   
         
                               
                                                               
                              
         
     
 
                                                   




                                                                 
                        
 
               
                  
 
                                        
                                     
     
                                                                  
                           

     

                                                         
                           
 
                                                      
 
                      

 

                                                              
                        
 
                       
 
                                     
                           


                                                              
     
                                             
                          
     
                       

 

                              

                        
 





                                 




                                                                        
      
                                            
 





                  
  
 

                                                                   
                        
 
                       
 
                                     
                           
 

                                                              
     
                                

                                                       
                                     
 
                                                    
         
                                         



                                               
                                           
                                             
         
 
                          
     
 

                                                    

 
      
                                                                   
 
                                   

 

                                                                  
                        
 

                       
              
 
                                                          
     
                               
                                                                                                                                       
                           
     
 
                                            
                            
                                    

        
                                                    
         
                                                   
             
                                              



                      
 
                                         
     
                               
                                                                                                                     
                           

     

                                                              
     


                                            
            
                                                 
 
                                   
                          
     
 

                                                    
 
 

                                                         
                
 
                      
                                       

 

                                                            
                        
 




                                         
                      
 
 

                                                                  
                
 
                           
                      

 

                                                                
                
 
                           
                      

 
      
                                                                        

                                                                           
 
                                     
 
                                               
 
              
                                
 
               
                            
 

                    
                                
                   
                                
     
 
                                                 
                                                             
     
                               
                                                                                 
                          
     
                                         
                                                             
     
                               
                                                                            
                          
     
                                                                                        
                                                                 
                                    
 
                                    
 
                      

 

                                                                                                 
 
                                                                                       

 

                                                                                                   
 
                                                                                      
 
 

                                                               
                        
 
                                       
                          
 
                                                                      

                                                 
 
                      
 
 
 

                                                                       
                        
 
                       
 
                                     
                           
 

                                                              
     
                                            

                                                            
 
                                

                                                                  
                                     

                                            
                                                   
                                               
                                   
                                                        
                                         
         
 

                                                           
                                     
 

                                                    
                                                                   
                                                                   
 

                    

                                                         
                                             

             
 

        
     
                                                        

                           
 
                      

 

                                                                        
                        
 

                       
 
                                             
     
                                                                           
                           
     
 

                                                              
     

                                                          
            
                                                              

        
                                                        
 
                      

 

                                                                          
                        
 

                       
 
                                             
                           
 

                                                              
     

                                                            
            
                                                                

        
                                                        
 
                      

 

                                                                    
                        
 


                       
 
                                                     
                           
 

                                                              
     

                                       

        
                                                        
 
                      
 
 

                                                                
                        
 
                       
 
                                     
                           
 

                                                              
     
                                                        
                           

     
                                    



                                                            
                                    
     

                        
                                                                                                            
                                       
         
                                                        
                                      
             
                                           
                                                        
                                                            
                                                  
                                                



             
                                           
                      
 
 

                                                                    
                
 
                                    
     

                        
                                                                                                                                       
                 

                                                                      
                                             

                                                       

                                                                                      

         
                                                   
 



























































































































































































































































































































































































































































                                                                                     
#include "atcommand.hpp"

#include <cmath>
#include <cstring>
#include <ctime>

#include "../strings/mstring.hpp"
#include "../strings/fstring.hpp"
#include "../strings/zstring.hpp"
#include "../strings/xstring.hpp"
#include "../strings/vstring.hpp"

#include "../io/read.hpp"
#include "../io/write.hpp"

#include "../common/core.hpp"
#include "../common/cxxstdio.hpp"
#include "../common/extract.hpp"
#include "../common/human_time_diff.hpp"
#include "../common/mmo.hpp"
#include "../common/nullpo.hpp"
#include "../common/random.hpp"
#include "../common/socket.hpp"
#include "../common/timer.hpp"
#include "../common/utils2.hpp"
#include "../common/version.hpp"

#include "battle.hpp"
#include "chrif.hpp"
#include "clif.hpp"
#include "intif.hpp"
#include "itemdb.hpp"
#include "map.hpp"
#include "mob.hpp"
#include "npc.hpp"
#include "party.hpp"
#include "pc.hpp"
#include "script.hpp"
#include "skill.hpp"
#include "storage.hpp"
#include "tmw.hpp"
#include "trade.hpp"

#include "../poison.hpp"


enum class ATCE
{
    OKAY,
    USAGE,
    EXIST,
    RANGE,
    PERM,
};

struct AtCommandInfo
{
    ZString args;
    int level;
    ATCE (*proc)(const int fd, dumb_ptr<map_session_data> sd, ZString message);
    ZString help;

    AtCommandInfo(ZString a, int l, ATCE (*p)(const int, dumb_ptr<map_session_data>, ZString), ZString h)
    : args(a), level(l), proc(p), help(h)
    {}
};


// TODO What we really want is an ArrayMap ...
// This is defined at the end of the file.
extern
Map<XString, AtCommandInfo> atcommand_info;


static
AtCommandInfo *atcommand(XString cmd);

// These @commands are used within other @commands.
static
ATCE atcommand_character_baselevel(const int fd, dumb_ptr<map_session_data> sd,
        ZString message);
static
ATCE atcommand_skill_learn(const int fd, dumb_ptr<map_session_data>,
        ZString message);
static
ATCE atcommand_charwarp(const int fd, dumb_ptr<map_session_data> sd,
        ZString message);
static
ATCE atcommand_charstreset(const int fd, dumb_ptr<map_session_data> sd,
        ZString message);


void atcommand_config_write(ZString cfgName)
{
    io::WriteFile out(cfgName);

    if (!out.is_open())
    {
        FPRINTF(stderr, "Failed to write atcommand config: %s\n", cfgName);
        return;
    }

    FPRINTF(out, "// Generated by %s\n", CURRENT_VERSION_STRING);
    for (const auto& pair : atcommand_info)
    {
        // This XString is really a ZString, but not declared as one
        // in order to allow non-heterogenous lookup by XString.
        const char *cmd = &*pair.first.begin();
        const AtCommandInfo& info = pair.second;

        FPRINTF(out,
                "\n"
                "// %s\n"
                "// Usage: @%s %s\n"
                "%s: %d\n",
                info.help,
                cmd, info.args,
                cmd, info.level);
    }
}


// If your last arg is not a ZString, you probably wanted extract()
// but not always ...
static
bool asplit(ZString raw, ZString *last)
{
    *last = raw;
    return true;
}

// but this case is just so common and useful. In fact, is the previous ever used otherwise?
static
bool asplit(ZString raw, CharName *last)
{
    if (raw.size() < 4 || raw.size() > 23)
        return false;
    *last = stringish<CharName>(raw);
    return true;
}

// huh.
static
bool asplit(ZString raw, NpcName *last)
{
    if (!raw || raw.size() > 23)
        return false;
    *last = stringish<NpcName>(raw);
    return true;
}

// This differs from extract() in that it does not consume extra spaces.
template<class F, class... R, typename=typename std::enable_if<sizeof...(R) != 0>::type>
bool asplit(ZString raw, F *first_arg, R *... rest_args)
{
    ZString::iterator it = std::find(raw.begin(), raw.end(), ' ');
    XString frist = raw.xislice_h(it);
    while (*it == ' ')
        ++it;
    ZString rest = raw.xislice_t(it);
    return extract(frist, first_arg) && asplit(rest, rest_args...);
}

static
io::AppendFile *get_gm_log();

void log_atcommand(dumb_ptr<map_session_data> sd, ZString cmd)
{
    io::AppendFile *fp = get_gm_log();
    if (!fp)
        return;
    timestamp_seconds_buffer tmpstr;
    stamp_time(tmpstr);
    MapName map = (sd->bl_m
            ? sd->bl_m->name_
            : stringish<MapName>("undefined.gat"));
    FPRINTF(*fp, "[%s] %s(%d,%d) %s(%d) : %s\n",
            tmpstr,
            map, sd->bl_x, sd->bl_y,
            sd->status.name, sd->status.account_id,
            cmd);
}

FString gm_log;

io::AppendFile *get_gm_log()
{
    if (!gm_log)
        return NULL;

    struct tm ctime = TimeT::now();

    int year = ctime.tm_year + 1900;
    int month = ctime.tm_mon + 1;
    int logfile_nr = (year * 12) + month;

    static std::unique_ptr<io::AppendFile> gm_logfile;
    static int last_logfile_nr = 0;
    if (logfile_nr == last_logfile_nr)
        return gm_logfile.get();
    last_logfile_nr = logfile_nr;

    FString fullname = STRPRINTF("%s.%04d-%02d",
            gm_log, year, month);

    if (gm_logfile)
        gm_logfile.reset();

    gm_logfile = make_unique<io::AppendFile>(fullname, true);

    if (!gm_logfile)
    {
        perror("GM log file");
        gm_log = FString();
    }
    return gm_logfile.get();
}

bool is_atcommand(const int fd, dumb_ptr<map_session_data> sd,
        ZString message, int gmlvl)
{
    nullpo_retr(false, sd);

    if (!message.startswith('@'))
        return false;

    XString command;
    ZString arg;
    asplit(message, &command, &arg);

    AtCommandInfo *info = atcommand(command);

    if (!gmlvl)
        gmlvl = pc_isGM(sd);
    if (battle_config.atcommand_gm_only != 0 && !gmlvl)
    {
        FString output = STRPRINTF("GM command is level 0, but this server disables level 0 commands: %s",
                FString(command));
        clif_displaymessage(fd, output);
        return true;
    }
    if (!info)
    {
        FString output = STRPRINTF("GM command not found: %s",
                FString(command));
        clif_displaymessage(fd, output);
        return true;
        // don't show in chat
    }
    if (info->level > gmlvl)
    {
        FString output = STRPRINTF("GM command is level %d, but you are level %d: %s",
                info->level, gmlvl,
                FString(command));
        clif_displaymessage(fd, output);
        return true;
    }

    {
        {
            ATCE err = info->proc(fd, sd, arg);
            switch (err)
            {
            case ATCE::OKAY:
                // Don't log level 0 commands
                if (info->level)
                    log_atcommand(sd, message);
                break;
            case ATCE::USAGE:
                clif_displaymessage(fd, "Command failed: usage error");
                clif_displaymessage(fd, STRPRINTF("Usage: %s %s", FString(command), info->args));
                break;
            case ATCE::EXIST:
                clif_displaymessage(fd, "Command failed: something does not exist (or already exists)");
                break;
            case ATCE::RANGE:
                clif_displaymessage(fd, "Command failed: value out of range");
                break;
            case ATCE::PERM:
                clif_displaymessage(fd, "Command failed: permission denied");
                break;
            default:
                abort();
            }
        }

        return true;
    }
}

AtCommandInfo *atcommand(XString cmd)
{
    if (cmd.startswith('@'))
    {
        XString command = cmd.xslice_t(1);
        AtCommandInfo *it = atcommand_info.search(command);
        return it;
    }
    return nullptr;
}

static
void atkillmonster_sub(dumb_ptr<block_list> bl, int flag)
{
    nullpo_retv(bl);

    dumb_ptr<mob_data> md = bl->is_mob();
    if (flag)
        mob_damage(NULL, md, md->hp, 2);
    else
        mob_delete(md);
}

static
AtCommandInfo *get_atcommandinfo_byname(XString name)
{
    return atcommand_info.search(name);
}

int atcommand_config_read(ZString cfgName)
{
    io::ReadFile in(cfgName);
    if (!in.is_open())
    {
        PRINTF("At commands configuration file not found: %s\n", cfgName);
        return 1;
    }

    FString line;
    while (in.getline(line))
    {
        XString w1;
        ZString w2;
        if (!split_key_value(line, &w1, &w2))
            continue;
        AtCommandInfo *p = get_atcommandinfo_byname(w1);
        if (p != NULL)
        {
            p->level = atoi(w2.c_str());
            if (p->level > 100)
                p->level = 100;
            else if (p->level < 0)
                p->level = 0;
        }
        else if (w1 == "import")
            atcommand_config_read(w2);
        else
            PRINTF("%s: bad line: %s\n", cfgName, line);
    }

    return 0;
}

/// @ command processing functions

static
void atc_do_help(const int fd, const char *cmd, const AtCommandInfo& info)
{
    auto msg = STRPRINTF("\u2007\u2007%d: @%s %s", info.level, cmd, info.args);
    // manually padding because *space*
    size_t ll = 1;
    if (info.level >= 10)
        ++ll;
    if (info.level >= 100)
        ++ll;
    clif_displaymessage(fd, msg.xslice_t((ll - 1) * 3));
}

static
ATCE atcommand_help(const int fd, dumb_ptr<map_session_data>,
        ZString message)
{
    if (!message)
    {
        clif_displaymessage(fd, "There is too much help to display it all at once");
        clif_displaymessage(fd, "Try @help <@command> or @help <category> or @help <level[-level]>");
        clif_displaymessage(fd, "Right now the only category is 'all'");
        return ATCE::OKAY;
    }

    if (message.startswith('@'))
    {
        ZString cmd = message.xslice_t(1);
        const AtCommandInfo *info = atcommand_info.search(cmd);
        if (!info)
            return ATCE::EXIST;
        clif_displaymessage(fd, STRPRINTF("Usage: @%s %s", cmd, info->args));
        clif_displaymessage(fd, info->help);
        return ATCE::OKAY;
    }

    if (message == "all")
    {
        clif_displaymessage(fd, "Synopses of GM commands in category 'all':");
        for (const auto& pair : atcommand_info)
        {
            const char *cmd = &*pair.first.begin();
            const AtCommandInfo& info = pair.second;
            atc_do_help(fd, cmd, info);
        }
        return ATCE::OKAY;
    }

    int low = 0, high;
    if (extract(message, &high))
        ++high;
    else if (!extract(message, record<'-'>(&low, &high)))
        return ATCE::USAGE;

    if (low < 0 || high > 100 || low >= high)
        return ATCE::RANGE;
    clif_displaymessage(fd, STRPRINTF("Synopses of GM commands in level [%d, %d):", low, high));
    for (const auto& pair : atcommand_info)
    {
        const char *cmd = &*pair.first.begin();
        const AtCommandInfo& info = pair.second;
        if (low <= info.level && info.level < high)
            atc_do_help(fd, cmd, info);
    }
    return ATCE::OKAY;
}

static
ATCE atcommand_setup(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    int level = 1;
    CharName character;

    if (!asplit(message, &level, &character))
        return ATCE::USAGE;
    level--;

    FString buf;
    buf = STRPRINTF("-255 %s", character);
    atcommand_character_baselevel(fd, sd, buf);

    buf = STRPRINTF("%d %s", level, character);
    atcommand_character_baselevel(fd, sd, buf);

    // Emote skill
    buf = STRPRINTF("1 1 %s", character);
    atcommand_skill_learn(fd, sd, buf);

    // Trade skill
    buf = STRPRINTF("2 1 %s", character);
    atcommand_skill_learn(fd, sd, buf);

    // Party skill
    STRPRINTF("2 2 %s", character);
    atcommand_skill_learn(fd, sd, buf);

    STRPRINTF("018-1.gat 24 98 %s", character);
    atcommand_charwarp(fd, sd, buf);

    return ATCE::OKAY;
}

//static
ATCE atcommand_charwarp(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    MapName map_name;
    CharName character;
    int x = 0, y = 0;

    if (!asplit(message, &map_name, &x, &y, &character))
        return ATCE::USAGE;

    if (x <= 0)
        x = random_::in(1, 399);
    if (y <= 0)
        y = random_::in(1, 399);

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd)
    {
        if (pc_isGM(sd) >= pc_isGM(pl_sd))
        {
            // you can rura+ only lower or same GM level
            if (x > 0 && x < 800 && y > 0 && y < 800)
            {
                map_local *m = map_mapname2mapid(map_name);
                if (m != nullptr && m->flag.nowarpto
                    && battle_config.any_warp_GM_min_level > pc_isGM(sd))
                {
                    clif_displaymessage(fd,
                            "You are not authorised to warp someone to this map.");
                    return ATCE::PERM;
                }
                if (pl_sd->bl_m && pl_sd->bl_m->flag.nowarp
                    && battle_config.any_warp_GM_min_level > pc_isGM(sd))
                {
                    clif_displaymessage(fd,
                            "You are not authorised to warp this player from its actual map.");
                    return ATCE::PERM;
                }
                if (pc_setpos(pl_sd, map_name, x, y, BeingRemoveWhy::WARPED) == 0)
                {
                    clif_displaymessage(pl_sd->fd, "Warped.");
                    clif_displaymessage(fd, "Player warped (message sends to player too).");
                }
                else
                {
                    clif_displaymessage(fd, "Map not found.");
                    return ATCE::EXIST;
                }
            }
            else
            {
                clif_displaymessage(fd, "Coordinates out of range.");
                return ATCE::RANGE;
            }
        }
        else
        {
            clif_displaymessage(fd, "Your GM level don't authorise you to do this action on this player.");
            return ATCE::PERM;
        }
    }
    else
    {
        clif_displaymessage(fd, "Character not found.");
        return ATCE::EXIST;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_warp(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    MapName map_name;
    int x = 0, y = 0;

    if (!message
        || !extract(message, record<' ', 1>(&map_name, &x, &y)))
    {
        clif_displaymessage(fd,
                "Please, enter a map (usage: @warp <mapname> <x> <y>).");
        return ATCE::USAGE;
    }

    if (x <= 0)
        x = random_::in(1, 399);
    if (y <= 0)
        y = random_::in(1, 399);

    if (x > 0 && x < 800 && y > 0 && y < 800)
    {
        map_local *m = map_mapname2mapid(map_name);
        if (m != nullptr && m->flag.nowarpto
            && battle_config.any_warp_GM_min_level > pc_isGM(sd))
        {
            clif_displaymessage(fd,
                    "You are not authorised to warp you to this map.");
            return ATCE::PERM;
        }
        if (sd->bl_m && sd->bl_m->flag.nowarp
            && battle_config.any_warp_GM_min_level > pc_isGM(sd))
        {
            clif_displaymessage(fd,
                    "You are not authorised to warp you from your actual map.");
            return ATCE::PERM;
        }
        if (pc_setpos(sd, map_name, x, y, BeingRemoveWhy::WARPED) == 0)
            clif_displaymessage(fd, "Warped.");
        else
        {
            clif_displaymessage(fd, "Map not found.");
            return ATCE::EXIST;
        }
    }
    else
    {
        clif_displaymessage(fd, "Coordinates out of range.");
        return ATCE::RANGE;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_where(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    CharName character;
    extract(message, &character);

    dumb_ptr<map_session_data> pl_sd = character.to__actual() ? map_nick2sd(character) : sd;
    if (pl_sd != NULL &&
        !((battle_config.hide_GM_session
           || bool(pl_sd->status.option & Option::HIDE))
          && (pc_isGM(pl_sd) > pc_isGM(sd))))
    {
        // you can look only lower or same level
        FString output = STRPRINTF("%s: %s (%d,%d)",
                pl_sd->status.name,
                pl_sd->mapname_, pl_sd->bl_x, pl_sd->bl_y);
        clif_displaymessage(fd, output);
    }
    else
    {
        clif_displaymessage(fd, "Character not found.");
        return ATCE::EXIST;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_goto(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    CharName character;

    if (!asplit(message, &character))
    {
        clif_displaymessage(fd,
                "Please, enter a player name (usage: @jumpto/@warpto/@goto <char name>).");
        return ATCE::USAGE;
    }

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd != NULL)
    {
        if (pl_sd->bl_m && pl_sd->bl_m->flag.nowarpto
            && battle_config.any_warp_GM_min_level > pc_isGM(sd))
        {
            clif_displaymessage(fd,
                    "You are not authorised to warp you to the map of this player.");
            return ATCE::PERM;
        }
        if (sd->bl_m && sd->bl_m->flag.nowarp
            && battle_config.any_warp_GM_min_level > pc_isGM(sd))
        {
            clif_displaymessage(fd,
                    "You are not authorised to warp you from your actual map.");
            return ATCE::PERM;
        }
        pc_setpos(sd, pl_sd->mapname_, pl_sd->bl_x, pl_sd->bl_y, BeingRemoveWhy::WARPED);
        FString output = STRPRINTF("Jump to %s", character);
        clif_displaymessage(fd, output);
    }
    else
    {
        clif_displaymessage(fd, "Character not found.");
        return ATCE::EXIST;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_jump(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    int x = 0, y = 0;
    // may fail
    extract(message, record<' '>(&x, &y));

    if (x <= 0)
        x = random_::in(1, 399);
    if (y <= 0)
        y = random_::in(1, 399);
    if (x > 0 && x < 800 && y > 0 && y < 800)
    {
        if (sd->bl_m && sd->bl_m->flag.nowarpto
            && battle_config.any_warp_GM_min_level > pc_isGM(sd))
        {
            clif_displaymessage(fd,
                    "You are not authorised to warp you to your actual map.");
            return ATCE::PERM;
        }
        if (sd->bl_m && sd->bl_m->flag.nowarp
            && battle_config.any_warp_GM_min_level > pc_isGM(sd))
        {
            clif_displaymessage(fd,
                    "You are not authorised to warp you from your actual map.");
            return ATCE::PERM;
        }
        pc_setpos(sd, sd->mapname_, x, y, BeingRemoveWhy::WARPED);
        FString output = STRPRINTF("Jump to %d %d", x, y);
        clif_displaymessage(fd, output);
    }
    else
    {
        clif_displaymessage(fd, "Coordinates out of range.");
        return ATCE::RANGE;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_who(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    int count;
    int pl_GM_level, GM_level;
    VString<23> match_text = message;
    match_text = match_text.to_lower();

    count = 0;
    GM_level = pc_isGM(sd);
    for (int i = 0; i < fd_max; i++)
    {
        if (!session[i])
            continue;
        dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(session[i]->session_data.get()));
        if (pl_sd && pl_sd->state.auth)
        {
            pl_GM_level = pc_isGM(pl_sd);
            if (!
                ((battle_config.hide_GM_session
                  || bool(pl_sd->status.option & Option::HIDE))
                 && (pl_GM_level > GM_level)))
            {
                // you can look only lower or same level
                VString<23> player_name = pl_sd->status.name.to__lower();
                if (player_name.contains_seq(match_text))
                {
                    // search with no case sensitive
                    FString output;
                    if (pl_GM_level > 0)
                        output = STRPRINTF(
                                "Name: %s (GM:%d) | Location: %s %d %d",
                                pl_sd->status.name, pl_GM_level,
                                pl_sd->mapname_, pl_sd->bl_x, pl_sd->bl_y);
                    else
                        output = STRPRINTF(
                                "Name: %s | Location: %s %d %d",
                                pl_sd->status.name, pl_sd->mapname_,
                                pl_sd->bl_x, pl_sd->bl_y);
                    clif_displaymessage(fd, output);
                    count++;
                }
            }
        }
    }

    if (count == 0)
        clif_displaymessage(fd, "No player found.");
    else if (count == 1)
        clif_displaymessage(fd, "1 player found.");
    else
    {
        FString output = STRPRINTF("%d players found.", count);
        clif_displaymessage(fd, output);
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_whogroup(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    int count;
    int pl_GM_level, GM_level;
    struct party *p;

    VString<23> match_text = message;
    match_text = match_text.to_lower();

    count = 0;
    GM_level = pc_isGM(sd);
    for (int i = 0; i < fd_max; i++)
    {
        if (!session[i])
            continue;
        dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(session[i]->session_data.get()));
        if (pl_sd && pl_sd->state.auth)
        {
            pl_GM_level = pc_isGM(pl_sd);
            if (!
                ((battle_config.hide_GM_session
                  || bool(pl_sd->status.option & Option::HIDE))
                 && (pl_GM_level > GM_level)))
            {
                // you can look only lower or same level
                VString<23> player_name = pl_sd->status.name.to__lower();
                if (player_name.contains_seq(match_text))
                {
                    // search with no case sensitive
                    p = party_search(pl_sd->status.party_id);
                    PartyName temp0 = p ? p->name : stringish<PartyName>("None");
                    FString output;
                    if (pl_GM_level > 0)
                        output = STRPRINTF(
                                "Name: %s (GM:%d) | Party: '%s'",
                                pl_sd->status.name, pl_GM_level, temp0);
                    clif_displaymessage(fd, output);
                    count++;
                }
            }
        }
    }

    if (count == 0)
        clif_displaymessage(fd, "No player found.");
    else if (count == 1)
        clif_displaymessage(fd, "1 player found.");
    else
    {
        FString output = STRPRINTF("%d players found.", count);
        clif_displaymessage(fd, output);
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_whomap(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    int count;
    int pl_GM_level, GM_level;
    map_local *map_id;

    {
        MapName map_name;
        extract(message, &map_name);
        map_id = map_mapname2mapid(map_name);
        if (map_id == nullptr)
            map_id = sd->bl_m;
    }

    count = 0;
    GM_level = pc_isGM(sd);
    for (int i = 0; i < fd_max; i++)
    {
        if (!session[i])
            continue;
        dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(session[i]->session_data.get()));
        if (pl_sd && pl_sd->state.auth)
        {
            pl_GM_level = pc_isGM(pl_sd);
            if (!
                ((battle_config.hide_GM_session
                  || bool(pl_sd->status.option & Option::HIDE))
                 && (pl_GM_level > GM_level)))
            {
                // you can look only lower or same level
                if (pl_sd->bl_m == map_id)
                {
                    FString output;
                    if (pl_GM_level > 0)
                        output = STRPRINTF(
                                "Name: %s (GM:%d) | Location: %s %d %d",
                                pl_sd->status.name, pl_GM_level,
                                pl_sd->mapname_, pl_sd->bl_x, pl_sd->bl_y);
                    else
                        output = STRPRINTF(
                                "Name: %s | Location: %s %d %d",
                                pl_sd->status.name, pl_sd->mapname_,
                                pl_sd->bl_x, pl_sd->bl_y);
                    clif_displaymessage(fd, output);
                    count++;
                }
            }
        }
    }

    FString output = STRPRINTF("%d players found in map '%s'.",
            count, map_id->name_);
    clif_displaymessage(fd, output);

    return ATCE::OKAY;
}

static
ATCE atcommand_whomapgroup(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    int count;
    int pl_GM_level, GM_level;
    struct party *p;

    map_local *map_id;
    {
        MapName map_name;
        extract(message, &map_name);
        map_id = map_mapname2mapid(map_name);
        if (map_id == nullptr)
            map_id = sd->bl_m;
    }

    count = 0;
    GM_level = pc_isGM(sd);
    for (int i = 0; i < fd_max; i++)
    {
        if (!session[i])
            continue;
        dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(session[i]->session_data.get()));
        if (pl_sd && pl_sd->state.auth)
        {
            pl_GM_level = pc_isGM(pl_sd);
            if (!
                ((battle_config.hide_GM_session
                  || bool(pl_sd->status.option & Option::HIDE))
                 && (pl_GM_level > GM_level)))
            {
                // you can look only lower or same level
                if (pl_sd->bl_m == map_id)
                {
                    p = party_search(pl_sd->status.party_id);
                    PartyName temp0 = p ? p->name : stringish<PartyName>("None");
                    FString output;
                    if (pl_GM_level > 0)
                        output = STRPRINTF("Name: %s (GM:%d) | Party: '%s'",
                                pl_sd->status.name, pl_GM_level, temp0);
                    else
                        output = STRPRINTF("Name: %s | Party: '%s'",
                                pl_sd->status.name, temp0);
                    clif_displaymessage(fd, output);
                    count++;
                }
            }
        }
    }

    FString output;
    if (count == 0)
        output = STRPRINTF("No player found in map '%s'.", map_id->name_);
    else if (count == 1)
        output = STRPRINTF("1 player found in map '%s'.", map_id->name_);
    else
    {
        output = STRPRINTF("%d players found in map '%s'.", count, map_id->name_);
    }
    clif_displaymessage(fd, output);

    return ATCE::OKAY;
}

static
ATCE atcommand_whogm(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    int count;
    int pl_GM_level, GM_level;
    struct party *p;

    VString<23> match_text = message;
    match_text = match_text.to_lower();

    count = 0;
    GM_level = pc_isGM(sd);
    for (int i = 0; i < fd_max; i++)
    {
        if (!session[i])
            continue;
        dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(session[i]->session_data.get()));
        if (pl_sd && pl_sd->state.auth)
        {
            pl_GM_level = pc_isGM(pl_sd);
            if (pl_GM_level > 0)
            {
                if (!
                    ((battle_config.hide_GM_session
                      || bool(pl_sd->status.option & Option::HIDE))
                     && (pl_GM_level > GM_level)))
                {
                    // you can look only lower or same level
                    VString<23> player_name = pl_sd->status.name.to__lower();
                    if (player_name.contains_seq(match_text))
                    {
                        // search with no case sensitive
                        FString output;
                        output = STRPRINTF(
                                "Name: %s (GM:%d) | Location: %s %d %d",
                                pl_sd->status.name, pl_GM_level,
                                pl_sd->mapname_, pl_sd->bl_x, pl_sd->bl_y);
                        clif_displaymessage(fd, output);
                        output = STRPRINTF(
                                "       BLvl: %d | Job: %s (Lvl: %d)",
                                pl_sd->status.base_level,
                                "Novice/Human",
                                pl_sd->status.job_level);
                        clif_displaymessage(fd, output);
                        p = party_search(pl_sd->status.party_id);
                        PartyName temp0 = p ? p->name : stringish<PartyName>("None");
                        output = STRPRINTF(
                                "       Party: '%s'",
                                temp0);
                        clif_displaymessage(fd, output);
                        count++;
                    }
                }
            }
        }
    }

    if (count == 0)
        clif_displaymessage(fd, "No GM found.");
    else if (count == 1)
        clif_displaymessage(fd, "1 GM found.");
    else
    {
        FString output = STRPRINTF("%d GMs found.", count);
        clif_displaymessage(fd, output);
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_save(const int fd, dumb_ptr<map_session_data> sd,
        ZString)
{
    pc_setsavepoint(sd, sd->mapname_, sd->bl_x, sd->bl_y);
    pc_makesavestatus(sd);
    chrif_save(sd);
    clif_displaymessage(fd, "Character data respawn point saved.");

    return ATCE::OKAY;
}

static
ATCE atcommand_load(const int fd, dumb_ptr<map_session_data> sd,
        ZString)
{
    map_local *m = map_mapname2mapid(sd->status.save_point.map_);
    if (m != nullptr && m->flag.nowarpto
        && battle_config.any_warp_GM_min_level > pc_isGM(sd))
    {
        clif_displaymessage(fd,
                             "You are not authorised to warp you to your save map.");
        return ATCE::PERM;
    }
    if (sd->bl_m && sd->bl_m->flag.nowarp
        && battle_config.any_warp_GM_min_level > pc_isGM(sd))
    {
        clif_displaymessage(fd,
                             "You are not authorised to warp you from your actual map.");
        return ATCE::PERM;
    }

    pc_setpos(sd, sd->status.save_point.map_, sd->status.save_point.x,
               sd->status.save_point.y, BeingRemoveWhy::GONE);
    clif_displaymessage(fd, "Warping to respawn point.");

    return ATCE::OKAY;
}

static
ATCE atcommand_speed(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    if (!message)
    {
        FString output = STRPRINTF(
                "Please, enter a speed value (usage: @speed <%d-%d>).",
                static_cast<uint32_t>(MIN_WALK_SPEED.count()),
                static_cast<uint32_t>(MAX_WALK_SPEED.count()));
        clif_displaymessage(fd, output);
        return ATCE::USAGE;
    }

    interval_t speed = static_cast<interval_t>(atoi(message.c_str()));
    if (speed >= MIN_WALK_SPEED && speed <= MAX_WALK_SPEED)
    {
        sd->speed = speed;
        //sd->walktimer = x;
        //この文を追加 by れ
        clif_updatestatus(sd, SP::SPEED);
        clif_displaymessage(fd, "Speed changed.");
    }
    else
    {
        FString output = STRPRINTF(
                "Please, enter a valid speed value (usage: @speed <%d-%d>).",
                static_cast<uint32_t>(MIN_WALK_SPEED.count()),
                static_cast<uint32_t>(MAX_WALK_SPEED.count()));
        clif_displaymessage(fd, output);
        return ATCE::RANGE;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_storage(const int fd, dumb_ptr<map_session_data> sd,
        ZString)
{
    struct storage *stor;

    if (sd->state.storage_open)
    {
        clif_displaymessage(fd, "msg_table[250]");
        return ATCE::EXIST;
    }

    if ((stor = account2storage2(sd->status.account_id)) != NULL
        && stor->storage_status == 1)
    {
        clif_displaymessage(fd, "msg_table[250]");
        return ATCE::EXIST;
    }

    storage_storageopen(sd);

    return ATCE::OKAY;
}

static
ATCE atcommand_option(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    Opt1 param1 = Opt1::ZERO;
    Opt2 param2 = Opt2::ZERO;
    Option param3 = Option::ZERO;

    if (!extract(message, record<',', 1>(&param1, &param2, &param3)))
        return ATCE::USAGE;

    sd->opt1 = param1;
    sd->opt2 = param2;
    sd->status.option = param3;

    clif_changeoption(sd);
    pc_calcstatus(sd, 0);
    clif_displaymessage(fd, "Options changed.");

    return ATCE::OKAY;
}

static
ATCE atcommand_hide(const int fd, dumb_ptr<map_session_data> sd,
        ZString)
{
    if (bool(sd->status.option & Option::HIDE))
    {
        sd->status.option &= ~Option::HIDE;
        clif_displaymessage(fd, "Invisible: Off.");
    }
    else
    {
        sd->status.option |= Option::HIDE;
        clif_displaymessage(fd, "Invisible: On.");
    }
    clif_changeoption(sd);

    return ATCE::OKAY;
}

static
ATCE atcommand_die(const int fd, dumb_ptr<map_session_data> sd,
        ZString)
{
    pc_damage(NULL, sd, sd->status.hp + 1);
    clif_displaymessage(fd, "A pity! You've died.");

    return ATCE::OKAY;
}

static
ATCE atcommand_kill(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    CharName character;

    if (!asplit(message, &character))
        return ATCE::USAGE;

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd != NULL)
    {
        if (pc_isGM(sd) >= pc_isGM(pl_sd))
        {
            // you can kill only lower or same level
            pc_damage(NULL, pl_sd, pl_sd->status.hp + 1);
            clif_displaymessage(fd, "Character killed.");
        }
        else
        {
            clif_displaymessage(fd, "Your GM level don't authorise you to do this action on this player.");
            return ATCE::PERM;
        }
    }
    else
    {
        clif_displaymessage(fd, "Character not found.");
        return ATCE::EXIST;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_alive(const int fd, dumb_ptr<map_session_data> sd,
        ZString)
{
    sd->status.hp = sd->status.max_hp;
    sd->status.sp = sd->status.max_sp;
    pc_setstand(sd);
    if (static_cast<interval_t>(battle_config.player_invincible_time) > interval_t::zero())
        pc_setinvincibletimer(sd, static_cast<interval_t>(battle_config.player_invincible_time));
    clif_updatestatus(sd, SP::HP);
    clif_updatestatus(sd, SP::SP);
    clif_resurrection(sd, 1);
    clif_displaymessage(fd, "You've been revived! It's a miracle!");

    return ATCE::OKAY;
}

static
ATCE atcommand_kami(const int, dumb_ptr<map_session_data>,
        ZString message)
{
    if (!message)
        return ATCE::USAGE;

    intif_GMmessage(message);

    return ATCE::OKAY;
}

static
ATCE atcommand_heal(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    int hp = 0, sp = 0;

    extract(message, record<' '>(&hp, &sp));

    if (hp == 0 && sp == 0)
    {
        hp = sd->status.max_hp - sd->status.hp;
        sp = sd->status.max_sp - sd->status.sp;
    }
    else
    {
        if (hp > 0 && (hp > sd->status.max_hp || hp > (sd->status.max_hp - sd->status.hp)))
            // fix positiv overflow
            hp = sd->status.max_hp - sd->status.hp;
        else if (hp < 0 && (hp < -sd->status.max_hp || hp < (1 - sd->status.hp)))
            // fix negativ overflow
            hp = 1 - sd->status.hp;
        if (sp > 0 && (sp > sd->status.max_sp || sp > (sd->status.max_sp - sd->status.sp)))
            // fix positiv overflow
            sp = sd->status.max_sp - sd->status.sp;
        else if (sp < 0 && (sp < -sd->status.max_sp || sp < (1 - sd->status.sp)))
            // fix negativ overflow
            sp = 1 - sd->status.sp;
    }

    if (hp < 0)
        // display like damage
        clif_damage(sd, sd, gettick(), interval_t::zero(), interval_t::zero(), -hp, 0, DamageType::RETURNED, 0);

    if (hp != 0 || sp != 0)
    {
        pc_heal(sd, hp, sp);
        if (hp >= 0 && sp >= 0)
            clif_displaymessage(fd, "HP, SP recovered.");
        else
            clif_displaymessage(fd, "HP or/and SP modified.");
    }
    else
    {
        clif_displaymessage(fd, "HP and SP are already with the good value.");
        return ATCE::RANGE;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_item(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    ItemName item_name;
    int number = 0, item_id;
    struct item_data *item_data = NULL;
    int get_count, i;

    if (!extract(message, record<' ', 1>(&item_name, &number)))
    {
        clif_displaymessage(fd,
                "Please, enter an item name/id (usage: @item <item name or ID> [quantity]).");
        return ATCE::USAGE;
    }

    if (number <= 0)
        number = 1;

    item_id = 0;
    if ((item_data = itemdb_searchname(item_name)) != NULL ||
        (item_data = itemdb_exists(atoi(item_name.c_str()))) != NULL)
        item_id = item_data->nameid;

    if (item_id >= 500)
    {
        get_count = number;
        if (item_data->type == ItemType::WEAPON
            || item_data->type == ItemType::ARMOR
            || item_data->type == ItemType::_7
            || item_data->type == ItemType::_8)
        {
            get_count = 1;
        }
        for (i = 0; i < number; i += get_count)
        {
            struct item item_tmp {};
            item_tmp.nameid = item_id;
            item_tmp.identify = 1;
            PickupFail flag;
            if ((flag = pc_additem(sd, &item_tmp, get_count))
                != PickupFail::OKAY)
                clif_additem(sd, 0, 0, flag);
        }
        clif_displaymessage(fd, "Item created.");
    }
    else
    {
        clif_displaymessage(fd, "Invalid item ID or name.");
        return ATCE::EXIST;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_itemreset(const int fd, dumb_ptr<map_session_data> sd,
        ZString)
{
    int i;

    for (i = 0; i < MAX_INVENTORY; i++)
    {
        if (sd->status.inventory[i].amount
            && sd->status.inventory[i].equip == EPOS::ZERO)
            pc_delitem(sd, i, sd->status.inventory[i].amount, 0);
    }
    clif_displaymessage(fd, "All of your items have been removed.");

    return ATCE::OKAY;
}

static
ATCE atcommand_itemcheck(const int, dumb_ptr<map_session_data> sd,
        ZString)
{
    pc_checkitem(sd);

    return ATCE::OKAY;
}

static
ATCE atcommand_baselevelup(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    int level, i;

    if (!extract(message, &level) || !level)
    {
        clif_displaymessage(fd,
                "Please, enter a level adjustement (usage: @blvl <number of levels>).");
        return ATCE::USAGE;
    }

    if (level > 0)
    {
        if (sd->status.base_level == battle_config.maximum_level)
        {
            clif_displaymessage(fd, "Base level can't go any higher.");
            return ATCE::RANGE;
        }
        if (level > battle_config.maximum_level || level > (battle_config.maximum_level - sd->status.base_level))
            // fix positiv overflow
            level = battle_config.maximum_level - sd->status.base_level;
        for (i = 1; i <= level; i++)
            sd->status.status_point += (sd->status.base_level + i + 14) / 4;
        sd->status.base_level += level;
        clif_updatestatus(sd, SP::BASELEVEL);
        clif_updatestatus(sd, SP::NEXTBASEEXP);
        clif_updatestatus(sd, SP::STATUSPOINT);
        pc_calcstatus(sd, 0);
        pc_heal(sd, sd->status.max_hp, sd->status.max_sp);
        clif_misceffect(sd, 0);
        clif_displaymessage(fd, "Base level raised.");
    }
    else
    {
        if (sd->status.base_level == 1)
        {
            clif_displaymessage(fd, "Base level can't go any lower.");
            return ATCE::USAGE;
        }
        if (level < -battle_config.maximum_level || level < (1 - sd->status.base_level))
            // fix negativ overflow
            level = 1 - sd->status.base_level;
        if (sd->status.status_point > 0)
        {
            for (i = 0; i > level; i--)
                sd->status.status_point -=
                    (sd->status.base_level + i + 14) / 4;
            if (sd->status.status_point < 0)
                sd->status.status_point = 0;
            clif_updatestatus(sd, SP::STATUSPOINT);
        }
        // to add: remove status points from stats
        sd->status.base_level += level;
        clif_updatestatus(sd, SP::BASELEVEL);
        clif_updatestatus(sd, SP::NEXTBASEEXP);
        pc_calcstatus(sd, 0);
        clif_displaymessage(fd, "Base level lowered.");
    }

    return ATCE::OKAY;
}

// TODO: merge this with pc_setparam(SP::JOBLEVEL)
// then fix the funny 50 and/or 10 limitation.
static
ATCE atcommand_joblevelup(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    int up_level = 50, level;

    if (!extract(message, &level) || !level)
        return ATCE::USAGE;

    up_level -= 40;

    if (level > 0)
    {
        if (sd->status.job_level == up_level)
        {
            clif_displaymessage(fd, "Job level can't go any higher.");
            return ATCE::RANGE;
        }
        if (level > up_level || level > (up_level - sd->status.job_level))
            // fix positiv overflow
            level = up_level - sd->status.job_level;
        sd->status.job_level += level;
        clif_updatestatus(sd, SP::JOBLEVEL);
        clif_updatestatus(sd, SP::NEXTJOBEXP);
        sd->status.skill_point += level;
        clif_updatestatus(sd, SP::SKILLPOINT);
        pc_calcstatus(sd, 0);
        clif_misceffect(sd, 1);
        clif_displaymessage(fd, "Job level raised.");
    }
    else
    {
        if (sd->status.job_level == 1)
        {
            clif_displaymessage(fd, "Job level can't go any lower.");
            return ATCE::RANGE;
        }
        if (level < -up_level || level < (1 - sd->status.job_level))
            // fix negativ overflow
            level = 1 - sd->status.job_level;
        sd->status.job_level += level;
        clif_updatestatus(sd, SP::JOBLEVEL);
        clif_updatestatus(sd, SP::NEXTJOBEXP);
        if (sd->status.skill_point > 0)
        {
            sd->status.skill_point += level;
            if (sd->status.skill_point < 0)
                sd->status.skill_point = 0;
            clif_updatestatus(sd, SP::SKILLPOINT);
        }
        // to add: remove status points from skills
        pc_calcstatus(sd, 0);
        clif_displaymessage(fd, "Job level lowered.");
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_gm(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    if (!message)
        return ATCE::USAGE;

    if (pc_isGM(sd))
    {
        // a GM can not use this function. only a normal player (become gm is not for gm!)
        clif_displaymessage(fd, "You already have some GM powers.");
        return ATCE::PERM;
    }
    else
        chrif_changegm(sd->status.account_id, message);

    return ATCE::OKAY;
}

static
ATCE atcommand_pvpoff(const int fd, dumb_ptr<map_session_data> sd,
        ZString)
{
    if (battle_config.pk_mode)
    {
        //disable command if server is in PK mode [Valaris]
        clif_displaymessage(fd, "This option cannot be used in PK Mode.");
        return ATCE::EXIST;
    }

    if (sd->bl_m->flag.pvp)
    {
        sd->bl_m->flag.pvp = 0;
        for (int i = 0; i < fd_max; i++)
        {
            if (!session[i])
                continue;
            dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(session[i]->session_data.get()));
            if (pl_sd && pl_sd->state.auth)
            {
                if (sd->bl_m == pl_sd->bl_m)
                {
                    pl_sd->pvp_timer.cancel();
                }
            }
        }
        clif_displaymessage(fd, "PvP: Off.");
    }
    else
    {
        clif_displaymessage(fd, "PvP is already Off.");
        return ATCE::EXIST;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_pvpon(const int fd, dumb_ptr<map_session_data> sd,
        ZString)
{
    if (battle_config.pk_mode)
    {
        //disable command if server is in PK mode [Valaris]
        clif_displaymessage(fd, "This option cannot be used in PK Mode.");
        return ATCE::EXIST;
    }

    if (!sd->bl_m->flag.pvp && !sd->bl_m->flag.nopvp)
    {
        sd->bl_m->flag.pvp = 1;
        for (int i = 0; i < fd_max; i++)
        {
            if (!session[i])
                continue;
            dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(session[i]->session_data.get()));
            if (pl_sd && pl_sd->state.auth)
            {
                if (sd->bl_m == pl_sd->bl_m && !pl_sd->pvp_timer)
                {
                    pl_sd->pvp_timer = Timer(gettick() + std::chrono::milliseconds(200),
                            std::bind(pc_calc_pvprank_timer, ph::_1, ph::_2, pl_sd->bl_id));
                    pl_sd->pvp_rank = 0;
                    pl_sd->pvp_lastusers = 0;
                    pl_sd->pvp_point = 5;
                }
            }
        }
        clif_displaymessage(fd, "PvP: On.");
    }
    else
    {
        clif_displaymessage(fd, "PvP is already On.");
        return ATCE::EXIST;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_model(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    int hair_style = 0, hair_color = 0, cloth_color = 0;

    if (!extract(message, record<' ', 1>(&hair_style, &hair_color, &cloth_color)))
        return ATCE::USAGE;

    if (hair_style >= MIN_HAIR_STYLE && hair_style <= MAX_HAIR_STYLE &&
        hair_color >= MIN_HAIR_COLOR && hair_color <= MAX_HAIR_COLOR &&
        cloth_color >= MIN_CLOTH_COLOR && cloth_color <= MAX_CLOTH_COLOR)
    {
        {
            pc_changelook(sd, LOOK::HAIR, hair_style);
            pc_changelook(sd, LOOK::HAIR_COLOR, hair_color);
            pc_changelook(sd, LOOK::CLOTHES_COLOR, cloth_color);
            clif_displaymessage(fd, "Appearence changed.");
        }
    }
    else
        return ATCE::RANGE;

    return ATCE::OKAY;
}

static
ATCE atcommand_dye(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    int cloth_color = 0;

    if (!extract(message, &cloth_color))
        return ATCE::USAGE;

    if (cloth_color >= MIN_CLOTH_COLOR && cloth_color <= MAX_CLOTH_COLOR)
    {
        {
            pc_changelook(sd, LOOK::CLOTHES_COLOR, cloth_color);
            clif_displaymessage(fd, "Appearence changed.");
        }
    }
    else
        return ATCE::RANGE;

    return ATCE::OKAY;
}

static
ATCE atcommand_hair_style(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    int hair_style = 0;

    if (!extract(message, &hair_style))
        return ATCE::USAGE;

    if (hair_style >= MIN_HAIR_STYLE && hair_style <= MAX_HAIR_STYLE)
    {
        {
            pc_changelook(sd, LOOK::HAIR, hair_style);
            clif_displaymessage(fd, "Appearence changed.");
        }
    }
    else
        return ATCE::RANGE;

    return ATCE::OKAY;
}

static
ATCE atcommand_hair_color(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    int hair_color = 0;

    if (!extract(message, &hair_color))
        return ATCE::USAGE;

    if (hair_color >= MIN_HAIR_COLOR && hair_color <= MAX_HAIR_COLOR)
    {
        {
            pc_changelook(sd, LOOK::HAIR_COLOR, hair_color);
            clif_displaymessage(fd, "Appearence changed.");
        }
    }
    else
        return ATCE::RANGE;

    return ATCE::OKAY;
}

static
ATCE atcommand_spawn(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    MobName monster;
    int mob_id;
    int number = 0;
    int x = 0, y = 0;
    int count;
    int i, j, k;
    int mx, my, range;

    if (!extract(message, record<' ', 1>(&monster, &number, &x, &y)))
        return ATCE::USAGE;

    // If monster identifier/name argument is a name
    if ((mob_id = mobdb_searchname(monster)) == 0)
        // check name first (to avoid possible name begining by a number)
        mob_id = mobdb_checkid(atoi(monster.c_str()));

    if (mob_id == 0)
        return ATCE::EXIST;

    if (number <= 0)
        number = 1;

    // If value of atcommand_spawn_quantity_limit directive is greater than or equal to 1 and quantity of monsters is greater than value of the directive
    if (battle_config.atcommand_spawn_quantity_limit >= 1
        && number > battle_config.atcommand_spawn_quantity_limit)
        number = battle_config.atcommand_spawn_quantity_limit;

    if (battle_config.etc_log)
        PRINTF("@spawn monster='%s' id=%d count=%d (%d,%d)\n",
                monster, mob_id, number, x, y);

    count = 0;
    range = sqrt(number) / 2;
    range = range * 2 + 5;
    // calculation of an odd number (+ 4 area around)
    for (i = 0; i < number; i++)
    {
        j = 0;
        k = 0;
        while (j++ < 8 && k == 0)
        {
            // try 8 times to spawn the monster (needed for close area)
            if (x <= 0)
                mx = sd->bl_x + random_::in(-range / 2, range / 2 );
            else
                mx = x;
            if (y <= 0)
                my = sd->bl_y + random_::in(-range / 2, range / 2);
            else
                my = y;
            k = mob_once_spawn(sd, MOB_THIS_MAP, mx, my, MobName(), mob_id, 1, NpcEvent());
        }
        count += (k != 0) ? 1 : 0;
    }

    if (count != 0)
        if (number == count)
            clif_displaymessage(fd, "All monster summoned!");
        else
        {
            FString output = STRPRINTF("%d monster(s) summoned!",
                    count);
            clif_displaymessage(fd, output);
        }
    else
    {
        clif_displaymessage(fd, "Invalid monster ID or name.");
        return ATCE::EXIST;
    }

    return ATCE::OKAY;
}

static
void atcommand_killmonster_sub(const int fd, dumb_ptr<map_session_data> sd,
        ZString message, const int drop)
{
    map_local *map_id;
    {
        MapName map_name;
        extract(message, &map_name);
        map_id = map_mapname2mapid(map_name);
        if (map_id == nullptr)
            map_id = sd->bl_m;
    }

    map_foreachinarea(std::bind(atkillmonster_sub, ph::_1, drop),
            map_id,
            0, 0,
            map_id->xs, map_id->ys,
            BL::MOB);

    clif_displaymessage(fd, "All monsters killed!");
}

static
ATCE atcommand_killmonster(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    atcommand_killmonster_sub(fd, sd, message, 1);

    return ATCE::OKAY;
}

static
void atlist_nearby_sub(dumb_ptr<block_list> bl, int fd)
{
    nullpo_retv(bl);

    FString buf = STRPRINTF(" - \"%s\"",
            bl->is_player()->status.name);
    clif_displaymessage(fd, buf);
}

static
ATCE atcommand_list_nearby(const int fd, dumb_ptr<map_session_data> sd,
        ZString)
{
    clif_displaymessage(fd, "Nearby players:");
    map_foreachinarea(std::bind(atlist_nearby_sub, ph::_1, fd),
            sd->bl_m,
            sd->bl_x - 1, sd->bl_y - 1,
            sd->bl_x + 1, sd->bl_x + 1,
            BL::PC);

    return ATCE::OKAY;
}

static
ATCE atcommand_killmonster2(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    atcommand_killmonster_sub(fd, sd, message, 0);

    return ATCE::OKAY;
}

static
ATCE atcommand_gat(const int fd, dumb_ptr<map_session_data> sd,
        ZString)
{
    int y;

    for (y = 2; y >= -2; y--)
    {
        FString output = STRPRINTF(
                "%s (x= %d, y= %d) %02X %02X %02X %02X %02X",
                sd->bl_m->name_, sd->bl_x - 2, sd->bl_y + y,
                map_getcell(sd->bl_m, sd->bl_x - 2, sd->bl_y + y),
                map_getcell(sd->bl_m, sd->bl_x - 1, sd->bl_y + y),
                map_getcell(sd->bl_m, sd->bl_x, sd->bl_y + y),
                map_getcell(sd->bl_m, sd->bl_x + 1, sd->bl_y + y),
                map_getcell(sd->bl_m, sd->bl_x + 2, sd->bl_y + y));
        clif_displaymessage(fd, output);
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_packet(const int, dumb_ptr<map_session_data> sd,
        ZString message)
{
    StatusChange type {};
    int flag = 0;

    if (!extract(message, record<' '>(&type, &flag)))
        return ATCE::USAGE;

    clif_status_change(sd, type, flag);

    return ATCE::OKAY;
}

static
ATCE atcommand_statuspoint(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    int point, new_status_point;

    if (!extract(message, &point) || point == 0)
        return ATCE::USAGE;

    new_status_point = sd->status.status_point + point;
    if (point > 0 && (point > 0x7FFF || new_status_point > 0x7FFF))
        // fix positiv overflow
        new_status_point = 0x7FFF;
    else if (point < 0 && (point < -0x7FFF || new_status_point < 0))
        // fix negativ overflow
        new_status_point = 0;

    if (new_status_point != sd->status.status_point)
    {
        sd->status.status_point = new_status_point;
        clif_updatestatus(sd, SP::STATUSPOINT);
        clif_displaymessage(fd, "Number of status points changed!");
    }
    else
        return ATCE::RANGE;

    return ATCE::OKAY;
}

static
ATCE atcommand_skillpoint(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    int point, new_skill_point;

    if (!extract(message, &point) || point == 0)
        return ATCE::USAGE;

    new_skill_point = sd->status.skill_point + point;
    if (point > 0 && (point > 0x7FFF || new_skill_point > 0x7FFF))
        // fix positiv overflow
        new_skill_point = 0x7FFF;
    else if (point < 0 && (point < -0x7FFF || new_skill_point < 0))
        // fix negativ overflow
        new_skill_point = 0;

    if (new_skill_point != sd->status.skill_point)
    {
        sd->status.skill_point = new_skill_point;
        clif_updatestatus(sd, SP::SKILLPOINT);
        clif_displaymessage(fd, "Number of skill points changed!");
    }
    else
        return ATCE::RANGE;

    return ATCE::OKAY;
}

static
ATCE atcommand_zeny(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    int zeny, new_zeny;

    if (!extract(message, &zeny) || zeny == 0)
        return ATCE::USAGE;

    new_zeny = sd->status.zeny + zeny;
    if (zeny > 0 && (zeny > MAX_ZENY || new_zeny > MAX_ZENY))
        // fix positiv overflow
        new_zeny = MAX_ZENY;
    else if (zeny < 0 && (zeny < -MAX_ZENY || new_zeny < 0))
        // fix negativ overflow
        new_zeny = 0;

    if (new_zeny != sd->status.zeny)
    {
        sd->status.zeny = new_zeny;
        clif_updatestatus(sd, SP::ZENY);
        clif_displaymessage(fd, "Number of zenys changed!");
    }
    else
        return ATCE::RANGE;

    return ATCE::OKAY;
}

template<ATTR attr>
ATCE atcommand_param(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    int value = 0, new_value;

    if (!extract(message, &value)
        || value == 0)
        return ATCE::USAGE;

    new_value = sd->status.attrs[attr] + value;
    if (value > 0 && (value > battle_config.max_parameter || new_value > battle_config.max_parameter))
        // fix positiv overflow
        new_value = battle_config.max_parameter;
    else if (value < 0 && (value < -battle_config.max_parameter || new_value < 1))
        // fix negativ overflow
        new_value = 1;

    if (new_value != sd->status.attrs[attr])
    {
        sd->status.attrs[attr] = new_value;
        clif_updatestatus(sd, attr_to_sp(attr));
        clif_updatestatus(sd, attr_to_usp(attr));
        pc_calcstatus(sd, 0);
        clif_displaymessage(fd, "Stat changed.");
    }
    else
        return ATCE::RANGE;

    return ATCE::OKAY;
}

static
ATCE atcommand_all_stats(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    int count, value = 0, new_value;

    if (!extract(message, &value)
        || value == 0)
        value = battle_config.max_parameter;

    count = 0;
    for (ATTR attr : ATTRs)
    {
        new_value = sd->status.attrs[attr] + value;
        if (value > 0 && (value > battle_config.max_parameter || new_value > battle_config.max_parameter))
            // fix positiv overflow
            new_value = battle_config.max_parameter;
        else if (value < 0 && (value < -battle_config.max_parameter || new_value < 1))
            // fix negativ overflow
            new_value = 1;

        if (new_value != sd->status.attrs[attr])
        {
            sd->status.attrs[attr] = new_value;
            clif_updatestatus(sd, attr_to_sp(attr));
            clif_updatestatus(sd, attr_to_usp(attr));
            pc_calcstatus(sd, 0);
            count++;
        }
    }

    if (count > 0)
        // if at least 1 stat modified
        clif_displaymessage(fd, "All stats changed!");
    else
        return ATCE::RANGE;

    return ATCE::OKAY;
}

static
ATCE atcommand_recall(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    CharName character;

    if (!asplit(message, &character))
        return ATCE::USAGE;

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd != NULL)
    {
        if (pc_isGM(sd) >= pc_isGM(pl_sd))
        {
            // you can recall only lower or same level
            if (sd->bl_m && sd->bl_m->flag.nowarpto
                && battle_config.any_warp_GM_min_level > pc_isGM(sd))
            {
                clif_displaymessage(fd,
                        "You are not authorised to warp somenone to your actual map.");
                return ATCE::PERM;
            }
            if (pl_sd->bl_m && pl_sd->bl_m->flag.nowarp
                && battle_config.any_warp_GM_min_level > pc_isGM(sd))
            {
                clif_displaymessage(fd,
                        "You are not authorised to warp this player from its actual map.");
                return ATCE::PERM;
            }
            pc_setpos(pl_sd, sd->mapname_, sd->bl_x, sd->bl_y, BeingRemoveWhy::QUIT);
            FString output = STRPRINTF("%s recalled!", character);
            clif_displaymessage(fd, output);
        }
        else
        {
            clif_displaymessage(fd, "Your GM level don't authorise you to do this action on this player.");
            return ATCE::PERM;
        }
    }
    else
    {
        clif_displaymessage(fd, "Character not found.");
        return ATCE::EXIST;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_revive(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    CharName character;

    if (!asplit(message, &character))
        return ATCE::USAGE;

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd != NULL)
    {
        pl_sd->status.hp = pl_sd->status.max_hp;
        pc_setstand(pl_sd);
        if (static_cast<interval_t>(battle_config.player_invincible_time) > interval_t::zero())
            pc_setinvincibletimer(sd, static_cast<interval_t>(battle_config.player_invincible_time));
        clif_updatestatus(pl_sd, SP::HP);
        clif_updatestatus(pl_sd, SP::SP);
        clif_resurrection(pl_sd, 1);
        clif_displaymessage(fd, "Character revived.");
    }
    else
    {
        clif_displaymessage(fd, "Character not found.");
        return ATCE::EXIST;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_character_stats(const int fd, dumb_ptr<map_session_data>,
        ZString message)
{
    CharName character;

    if (!asplit(message, &character))
        return ATCE::USAGE;

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd != NULL)
    {
        FString output;
        output = STRPRINTF("'%s' stats:", pl_sd->status.name);
        clif_displaymessage(fd, output);
        output = STRPRINTF("Base Level - %d", pl_sd->status.base_level),
        clif_displaymessage(fd, output);
        output = STRPRINTF("Job - Novice/Human (level %d)", pl_sd->status.job_level);
        clif_displaymessage(fd, output);
        output = STRPRINTF("Hp - %d", pl_sd->status.hp);
        clif_displaymessage(fd, output);
        output = STRPRINTF("MaxHp - %d", pl_sd->status.max_hp);
        clif_displaymessage(fd, output);
        output = STRPRINTF("Sp - %d", pl_sd->status.sp);
        clif_displaymessage(fd, output);
        output = STRPRINTF("MaxSp - %d", pl_sd->status.max_sp);
        clif_displaymessage(fd, output);
        output = STRPRINTF("Str - %3d", pl_sd->status.attrs[ATTR::STR]);
        clif_displaymessage(fd, output);
        output = STRPRINTF("Agi - %3d", pl_sd->status.attrs[ATTR::AGI]);
        clif_displaymessage(fd, output);
        output = STRPRINTF("Vit - %3d", pl_sd->status.attrs[ATTR::VIT]);
        clif_displaymessage(fd, output);
        output = STRPRINTF("Int - %3d", pl_sd->status.attrs[ATTR::INT]);
        clif_displaymessage(fd, output);
        output = STRPRINTF("Dex - %3d", pl_sd->status.attrs[ATTR::DEX]);
        clif_displaymessage(fd, output);
        output = STRPRINTF("Luk - %3d", pl_sd->status.attrs[ATTR::LUK]);
        clif_displaymessage(fd, output);
        output = STRPRINTF("Zeny - %d", pl_sd->status.zeny);
        clif_displaymessage(fd, output);
    }
    else
    {
        clif_displaymessage(fd, "Character not found.");
        return ATCE::EXIST;
    }

    return ATCE::USAGE;
}

static
ATCE atcommand_character_stats_all(const int fd, dumb_ptr<map_session_data>,
        ZString)
{
    int count;

    count = 0;
    for (int i = 0; i < fd_max; i++)
    {
        if (!session[i])
            continue;
        dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(session[i]->session_data.get()));
        if (pl_sd && pl_sd->state.auth)
        {
            FString gmlevel;
            if (pc_isGM(pl_sd) > 0)
                gmlevel = STRPRINTF("| GM Lvl: %d", pc_isGM(pl_sd));
            else
                gmlevel = " ";

            FString output;
            output = STRPRINTF(
                    "Name: %s | BLvl: %d | Job: Novice/Human (Lvl: %d) | HP: %d/%d | SP: %d/%d",
                    pl_sd->status.name, pl_sd->status.base_level,
                    pl_sd->status.job_level,
                    pl_sd->status.hp, pl_sd->status.max_hp,
                    pl_sd->status.sp, pl_sd->status.max_sp);
            clif_displaymessage(fd, output);
            output = STRPRINTF("STR: %d | AGI: %d | VIT: %d | INT: %d | DEX: %d | LUK: %d | Zeny: %d %s",
                     pl_sd->status.attrs[ATTR::STR],
                     pl_sd->status.attrs[ATTR::AGI],
                     pl_sd->status.attrs[ATTR::VIT],
                     pl_sd->status.attrs[ATTR::INT],
                     pl_sd->status.attrs[ATTR::DEX],
                     pl_sd->status.attrs[ATTR::LUK],
                     pl_sd->status.zeny,
                     gmlevel);
            clif_displaymessage(fd, output);
            clif_displaymessage(fd, "--------");
            count++;
        }
    }

    if (count == 0)
        clif_displaymessage(fd, "No player found.");
    else if (count == 1)
        clif_displaymessage(fd, "1 player found.");
    else
    {
        FString output = STRPRINTF("%d players found.", count);
        clif_displaymessage(fd, output);
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_character_option(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    Opt1 opt1;
    Opt2 opt2;
    Option opt3;
    CharName character;
    if (!asplit(message, &opt1, &opt2, &opt3, &character))
        return ATCE::USAGE;

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd != NULL)
    {
        if (pc_isGM(sd) >= pc_isGM(pl_sd))
        {
            // you can change option only to lower or same level
            pl_sd->opt1 = opt1;
            pl_sd->opt2 = opt2;
            pl_sd->status.option = opt3;

            clif_changeoption(pl_sd);
            pc_calcstatus(pl_sd, 0);
            clif_displaymessage(fd, "Character's options changed.");
        }
        else
        {
            clif_displaymessage(fd, "Your GM level don't authorise you to do this action on this player.");
            return ATCE::PERM;
        }
    }
    else
    {
        clif_displaymessage(fd, "Character not found.");
        return ATCE::EXIST;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_char_change_sex(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    CharName character;

    if (!asplit(message, &character))
        return ATCE::USAGE;

    {
        chrif_char_ask_name(sd->status.account_id, character, 5, HumanTimeDiff());
        // type: 5 - changesex
        clif_displaymessage(fd, "Character name sends to char-server to ask it.");
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_char_block(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    CharName character;

    if (!asplit(message, &character))
        return ATCE::USAGE;

    {
        chrif_char_ask_name(sd->status.account_id, character, 1, HumanTimeDiff());
        // type: 1 - block
        clif_displaymessage(fd, "Character name sends to char-server to ask it.");
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_char_ban(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    HumanTimeDiff modif;
    CharName character;

    if (!asplit(message, &modif, &character)
        || !modif)
        return ATCE::USAGE;

    {
        chrif_char_ask_name(sd->status.account_id, character, 2, modif);
        // type: 2 - ban
        clif_displaymessage(fd, "Character name sends to char-server to ask it.");
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_char_unblock(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    CharName character;

    if (!asplit(message, &character))
        return ATCE::USAGE;

    {
        // send answer to login server via char-server
        chrif_char_ask_name(sd->status.account_id, character, 3, HumanTimeDiff());
        // type: 3 - unblock
        clif_displaymessage(fd, "Character name sends to char-server to ask it.");
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_char_unban(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    CharName character;

    if (!asplit(message, &character))
        return ATCE::USAGE;

    {
        // send answer to login server via char-server
        chrif_char_ask_name(sd->status.account_id, character, 4, HumanTimeDiff());
        // type: 4 - unban
        clif_displaymessage(fd, "Character name sends to char-server to ask it.");
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_character_save(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    MapName map_name;
    CharName character;
    int x = 0, y = 0;

    if (!asplit(message, &map_name, &x, &y, &character)
        || x < 0 || y < 0)
        return ATCE::USAGE;

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd != NULL)
    {
        if (pc_isGM(sd) >= pc_isGM(pl_sd))
        {
            // you can change save point only to lower or same gm level
            map_local *m = map_mapname2mapid(map_name);
            if (m == nullptr)
            {
                clif_displaymessage(fd, "Map not found.");
                return ATCE::EXIST;
            }
            else
            {
                if (m != nullptr && m->flag.nowarpto
                    && battle_config.any_warp_GM_min_level > pc_isGM(sd))
                {
                    clif_displaymessage(fd,
                            "You are not authorised to set this map as a save map.");
                    return ATCE::PERM;
                }
                pc_setsavepoint(pl_sd, map_name, x, y);
                clif_displaymessage(fd, "Character's respawn point changed.");
            }
        }
        else
        {
            clif_displaymessage(fd, "Your GM level don't authorise you to do this action on this player.");
            return ATCE::PERM;
        }
    }
    else
    {
        clif_displaymessage(fd, "Character not found.");
        return ATCE::EXIST;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_doom(const int fd, dumb_ptr<map_session_data> sd,
        ZString)
{
    for (int i = 0; i < fd_max; i++)
    {
        if (!session[i])
            continue;
        dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(session[i]->session_data.get()));
        if (pl_sd
            && pl_sd->state.auth && i != fd
            && pc_isGM(sd) >= pc_isGM(pl_sd))
        {
            // you can doom only lower or same gm level
            pc_damage(NULL, pl_sd, pl_sd->status.hp + 1);
            clif_displaymessage(pl_sd->fd, "The holy messenger has given judgement.");
        }
    }
    clif_displaymessage(fd, "Judgement was made.");

    return ATCE::OKAY;
}

static
ATCE atcommand_doommap(const int fd, dumb_ptr<map_session_data> sd,
        ZString)
{
    for (int i = 0; i < fd_max; i++)
    {
        if (!session[i])
            continue;
        dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(session[i]->session_data.get()));
        if (pl_sd
            && pl_sd->state.auth && i != fd && sd->bl_m == pl_sd->bl_m
            && pc_isGM(sd) >= pc_isGM(pl_sd))
        {
            // you can doom only lower or same gm level
            pc_damage(NULL, pl_sd, pl_sd->status.hp + 1);
            clif_displaymessage(pl_sd->fd, "The holy messenger has given judgement.");
        }
    }
    clif_displaymessage(fd, "Judgement was made.");

    return ATCE::OKAY;
}

static
void atcommand_raise_sub(dumb_ptr<map_session_data> sd)
{
    if (sd && sd->state.auth && pc_isdead(sd))
    {
        sd->status.hp = sd->status.max_hp;
        sd->status.sp = sd->status.max_sp;
        pc_setstand(sd);
        clif_updatestatus(sd, SP::HP);
        clif_updatestatus(sd, SP::SP);
        clif_resurrection(sd, 1);
        clif_displaymessage(sd->fd, "Mercy has been shown.");
    }
}

static
ATCE atcommand_raise(const int fd, dumb_ptr<map_session_data>,
        ZString)
{
    for (int i = 0; i < fd_max; i++)
    {
        if (!session[i])
            continue;
        dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(session[i]->session_data.get()));
        atcommand_raise_sub(pl_sd);
    }
    clif_displaymessage(fd, "Mercy has been granted.");

    return ATCE::OKAY;
}

static
ATCE atcommand_raisemap(const int fd, dumb_ptr<map_session_data> sd,
        ZString)
{
    for (int i = 0; i < fd_max; i++)
    {
        if (!session[i])
            continue;
        dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(session[i]->session_data.get()));
        if (pl_sd
            && pl_sd->state.auth && sd->bl_m == pl_sd->bl_m)
            atcommand_raise_sub(pl_sd);
    }
    clif_displaymessage(fd, "Mercy has been granted.");

    return ATCE::OKAY;
}

//static
ATCE atcommand_character_baselevel(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    CharName character;
    int level = 0, i;

    if (!asplit(message, &level, &character)
        || level == 0)
        return ATCE::USAGE;

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd != NULL)
    {
        if (pc_isGM(sd) >= pc_isGM(pl_sd))
        {
            // you can change base level only lower or same gm level
            if (level > 0)
            {
                if (pl_sd->status.base_level == battle_config.maximum_level)
                {
                    clif_displaymessage(fd, "Character's base level can't go any higher.");
                    return ATCE::RANGE;
                }
                if (level > battle_config.maximum_level || level > (battle_config.maximum_level - pl_sd->status.base_level))
                    // fix positiv overflow
                    level =
                        battle_config.maximum_level -
                        pl_sd->status.base_level;
                for (i = 1; i <= level; i++)
                    pl_sd->status.status_point +=
                        (pl_sd->status.base_level + i + 14) / 4;
                pl_sd->status.base_level += level;
                clif_updatestatus(pl_sd, SP::BASELEVEL);
                clif_updatestatus(pl_sd, SP::NEXTBASEEXP);
                clif_updatestatus(pl_sd, SP::STATUSPOINT);
                pc_calcstatus(pl_sd, 0);
                pc_heal(pl_sd, pl_sd->status.max_hp, pl_sd->status.max_sp);
                clif_misceffect(pl_sd, 0);
                clif_displaymessage(fd, "Character's base level raised.");
            }
            else
            {
                if (pl_sd->status.base_level == 1)
                {
                    clif_displaymessage(fd, "Character's base level can't go any lower.");
                    return ATCE::RANGE;
                }
                if (level < -battle_config.maximum_level || level < (1 - pl_sd->status.base_level))
                    // fix negativ overflow
                    level = 1 - pl_sd->status.base_level;
                if (pl_sd->status.status_point > 0)
                {
                    for (i = 0; i > level; i--)
                        pl_sd->status.status_point -=
                            (pl_sd->status.base_level + i + 14) / 4;
                    if (pl_sd->status.status_point < 0)
                        pl_sd->status.status_point = 0;
                    clif_updatestatus(pl_sd, SP::STATUSPOINT);
                }
                // to add: remove status points from stats
                pl_sd->status.base_level += level;
                pl_sd->status.base_exp = 0;
                clif_updatestatus(pl_sd, SP::BASELEVEL);
                clif_updatestatus(pl_sd, SP::NEXTBASEEXP);
                clif_updatestatus(pl_sd, SP::BASEEXP);
                pc_calcstatus(pl_sd, 0);
                clif_displaymessage(fd, "Character's base level lowered.");
            }
            // Reset their stat points to prevent extra points from stacking
            atcommand_charstreset(fd, sd, character.to__actual());
        }
        else
        {
            clif_displaymessage(fd, "Your GM level don't authorise you to do this action on this player.");
            return ATCE::PERM;
        }
    }
    else
    {
        clif_displaymessage(fd, "Character not found.");
        return ATCE::EXIST;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_character_joblevel(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    CharName character;
    int max_level = 50, level = 0;

    if (!asplit(message, &level, &character)
        || level == 0)
        return ATCE::USAGE;

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd != NULL)
    {
        if (pc_isGM(sd) >= pc_isGM(pl_sd))
        {
            // you can change job level only lower or same gm level
            max_level -= 40;

            if (level > 0)
            {
                if (pl_sd->status.job_level == max_level)
                {
                    clif_displaymessage(fd, "Character's job level can't go any higher.");
                    return ATCE::RANGE;
                }
                if (pl_sd->status.job_level + level > max_level)
                    level = max_level - pl_sd->status.job_level;
                pl_sd->status.job_level += level;
                clif_updatestatus(pl_sd, SP::JOBLEVEL);
                clif_updatestatus(pl_sd, SP::NEXTJOBEXP);
                pl_sd->status.skill_point += level;
                clif_updatestatus(pl_sd, SP::SKILLPOINT);
                pc_calcstatus(pl_sd, 0);
                clif_misceffect(pl_sd, 1);
                clif_displaymessage(fd, "character's job level raised.");
            }
            else
            {
                if (pl_sd->status.job_level == 1)
                {
                    clif_displaymessage(fd, "Character's job level can't go any lower.");
                    return ATCE::RANGE;
                }
                if (pl_sd->status.job_level + level < 1)
                    level = 1 - pl_sd->status.job_level;
                pl_sd->status.job_level += level;
                clif_updatestatus(pl_sd, SP::JOBLEVEL);
                clif_updatestatus(pl_sd, SP::NEXTJOBEXP);
                if (pl_sd->status.skill_point > 0)
                {
                    pl_sd->status.skill_point += level;
                    if (pl_sd->status.skill_point < 0)
                        pl_sd->status.skill_point = 0;
                    clif_updatestatus(pl_sd, SP::SKILLPOINT);
                }
                // to add: remove status points from skills
                pc_calcstatus(pl_sd, 0);
                clif_displaymessage(fd, "Character's job level lowered.");
            }
        }
        else
        {
            clif_displaymessage(fd, "Your GM level don't authorise you to do this action on this player.");
            return ATCE::PERM;
        }
    }
    else
    {
        clif_displaymessage(fd, "Character not found.");
        return ATCE::EXIST;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_kick(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    CharName character;

    if (!asplit(message, &character))
        return ATCE::USAGE;

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd != NULL)
    {
        if (pc_isGM(sd) >= pc_isGM(pl_sd))
            // you can kick only lower or same gm level
            clif_GM_kick(sd, pl_sd, 1);
        else
        {
            clif_displaymessage(fd, "Your GM level don't authorise you to do this action on this player.");
            return ATCE::PERM;
        }
    }
    else
    {
        clif_displaymessage(fd, "Character not found.");
        return ATCE::EXIST;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_kickall(const int fd, dumb_ptr<map_session_data> sd,
        ZString)
{
    for (int i = 0; i < fd_max; i++)
    {
        if (!session[i])
            continue;
        dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(session[i]->session_data.get()));
        if (pl_sd
            && pl_sd->state.auth && pc_isGM(sd) >= pc_isGM(pl_sd))
        {
            // you can kick only lower or same gm level
            if (sd->status.account_id != pl_sd->status.account_id)
                clif_GM_kick(sd, pl_sd, 0);
        }
    }

    clif_displaymessage(fd, "All players have been kicked!");

    return ATCE::OKAY;
}

static
ATCE atcommand_questskill(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    SkillID skill_id;

    if (!extract(message, &skill_id))
        return ATCE::USAGE;

    if (/*skill_id >= SkillID() &&*/ skill_id < SkillID::MAX_SKILL_DB)
    {
        if (skill_get_inf2(skill_id) & 0x01)
        {
            if (pc_checkskill(sd, skill_id) == 0)
            {
                pc_skill(sd, skill_id, 1, 0);
                clif_displaymessage(fd, "You have learned the skill.");
            }
            else
            {
                clif_displaymessage(fd, "You already have this quest skill.");
                return ATCE::EXIST;
            }
        }
        else
        {
            clif_displaymessage(fd, "This skill number doesn't exist or isn't a quest skill.");
            return ATCE::RANGE;
        }
    }
    else
    {
        clif_displaymessage(fd, "This skill number doesn't exist.");
        return ATCE::RANGE;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_charquestskill(const int fd, dumb_ptr<map_session_data>,
        ZString message)
{
    CharName character;
    SkillID skill_id;

    if (!asplit(message, &skill_id, &character))
        return ATCE::USAGE;

    if (/*skill_id >= SkillID() &&*/ skill_id < SkillID::MAX_SKILL_DB)
    {
        if (skill_get_inf2(skill_id) & 0x01)
        {
            dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
            if (pl_sd != NULL)
            {
                if (pc_checkskill(pl_sd, skill_id) == 0)
                {
                    pc_skill(pl_sd, skill_id, 1, 0);
                    clif_displaymessage(fd, "This player has learned the skill.");
                }
                else
                {
                    clif_displaymessage(fd, "This player already has this quest skill.");
                    return ATCE::EXIST;
                }
            }
            else
            {
                clif_displaymessage(fd, "Character not found.");
                return ATCE::EXIST;
            }
        }
        else
        {
            clif_displaymessage(fd, "This skill number doesn't exist or isn't a quest skill.");
            return ATCE::RANGE;
        }
    }
    else
    {
        clif_displaymessage(fd, "This skill number doesn't exist.");
        return ATCE::RANGE;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_lostskill(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    SkillID skill_id;

    if (!extract(message, &skill_id))
        return ATCE::USAGE;

    if (/*skill_id >= SkillID() &&*/ skill_id < MAX_SKILL)
    {
        if (skill_get_inf2(skill_id) & 0x01)
        {
            if (pc_checkskill(sd, skill_id) > 0)
            {
                sd->status.skill[skill_id].lv = 0;
                sd->status.skill[skill_id].flags = SkillFlags::ZERO;
                clif_skillinfoblock(sd);
                clif_displaymessage(fd, "You have forgotten the skill.");
            }
            else
            {
                clif_displaymessage(fd, "You don't have this quest skill.");
                return ATCE::EXIST;
            }
        }
        else
        {
            clif_displaymessage(fd, "This skill number doesn't exist or isn't a quest skill.");
            return ATCE::RANGE;
        }
    }
    else
    {
        clif_displaymessage(fd, "This skill number doesn't exist.");
        return ATCE::RANGE;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_charlostskill(const int fd, dumb_ptr<map_session_data>,
        ZString message)
{
    CharName character;
    SkillID skill_id;

    if (!asplit(message, &skill_id, &character))
        return ATCE::USAGE;

    if (/*skill_id >= SkillID() &&*/ skill_id < MAX_SKILL)
    {
        if (skill_get_inf2(skill_id) & 0x01)
        {
            dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
            if (pl_sd != NULL)
            {
                if (pc_checkskill(pl_sd, skill_id) > 0)
                {
                    pl_sd->status.skill[skill_id].lv = 0;
                    pl_sd->status.skill[skill_id].flags = SkillFlags::ZERO;
                    clif_skillinfoblock(pl_sd);
                    clif_displaymessage(fd, "This player has forgotten the skill.");
                }
                else
                {
                    clif_displaymessage(fd, "This player doesn't have this quest skill.");
                    return ATCE::EXIST;
                }
            }
            else
            {
                clif_displaymessage(fd, "Character not found.");
                return ATCE::EXIST;
            }
        }
        else
        {
            clif_displaymessage(fd, "This skill number doesn't exist or isn't a quest skill.");
            return ATCE::RANGE;
        }
    }
    else
    {
        clif_displaymessage(fd, "This skill number doesn't exist.");
        return ATCE::RANGE;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_party(const int, dumb_ptr<map_session_data> sd,
        ZString message)
{
    PartyName party;

    if (!extract(message, &party) || !party)
        return ATCE::USAGE;

    party_create(sd, party);

    return ATCE::OKAY;
}

static
ATCE atcommand_mapexit(const int, dumb_ptr<map_session_data> sd,
        ZString)
{
    for (int i = 0; i < fd_max; i++)
    {
        if (!session[i])
            continue;
        dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(session[i]->session_data.get()));
        if (pl_sd && pl_sd->state.auth)
        {
            if (sd->status.account_id != pl_sd->status.account_id)
                clif_GM_kick(sd, pl_sd, 0);
        }
    }
    clif_GM_kick(sd, sd, 0);

    runflag = 0;

    return ATCE::OKAY;
}

static
ATCE atcommand_idsearch(const int fd, dumb_ptr<map_session_data>,
        ZString message)
{
    ItemName item_name;
    int i, match;
    struct item_data *item;

    if (!extract(message, &item_name) || !item_name)
        return ATCE::USAGE;

    FString output = STRPRINTF("The reference result of '%s' (name: id):", item_name);
    clif_displaymessage(fd, output);
    match = 0;
    for (i = 0; i < 20000; i++)
    {
        if ((item = itemdb_exists(i)) != NULL
            && item->jname.contains_seq(item_name))
        {
            match++;
            output = STRPRINTF("%s: %d", item->jname, item->nameid);
            clif_displaymessage(fd, output);
        }
    }
    output = STRPRINTF("It is %d affair above.", match);
    clif_displaymessage(fd, output);

    return ATCE::OKAY;
}

static
ATCE atcommand_charskreset(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    CharName character;

    if (!asplit(message, &character))
        return ATCE::USAGE;

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd != NULL)
    {
        if (pc_isGM(sd) >= pc_isGM(pl_sd))
        {
            // you can reset skill points only lower or same gm level
            pc_resetskill(pl_sd);
            FString output = STRPRINTF(
                    "'%s' skill points reseted!", character);
            clif_displaymessage(fd, output);
        }
        else
        {
            clif_displaymessage(fd, "Your GM level don't authorise you to do this action on this player.");
            return ATCE::PERM;
        }
    }
    else
    {
        clif_displaymessage(fd, "Character not found.");
        return ATCE::EXIST;
    }

    return ATCE::OKAY;
}

//static
ATCE atcommand_charstreset(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    CharName character;

    if (!asplit(message, &character))
        return ATCE::USAGE;

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd != NULL)
    {
        if (pc_isGM(sd) >= pc_isGM(pl_sd))
        {
            // you can reset stats points only lower or same gm level
            pc_resetstate(pl_sd);
            FString output = STRPRINTF(
                    "'%s' stats points reseted!",
                    character);
            clif_displaymessage(fd, output);
        }
        else
        {
            clif_displaymessage(fd, "Your GM level don't authorise you to do this action on this player.");
            return ATCE::PERM;
        }
    }
    else
    {
        clif_displaymessage(fd, "Character not found.");
        return ATCE::EXIST;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_charreset(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    CharName character;

    if (!asplit(message, &character))
        return ATCE::USAGE;

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd != NULL)
    {
        if (pc_isGM(sd) >= pc_isGM(pl_sd))
        {
            // you can reset a character only for lower or same GM level
            pc_resetstate(pl_sd);
            pc_resetskill(pl_sd);
            pc_setglobalreg(pl_sd, stringish<VarName>("MAGIC_FLAGS"), 0);
            // [Fate] Reset magic quest variables
            pc_setglobalreg(pl_sd, stringish<VarName>("MAGIC_EXP"), 0);
            // [Fate] Reset magic experience
            FString output = STRPRINTF(
                    "'%s' skill and stats points reseted!", character);
            clif_displaymessage(fd, output);
        }
        else
        {
            clif_displaymessage(fd, "Your GM level don't authorise you to do this action on this player.");
            return ATCE::PERM;
        }
    }
    else
    {
        clif_displaymessage(fd, "Character not found.");
        return ATCE::EXIST;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_char_wipe(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    CharName character;

    if (!asplit(message, &character))
        return ATCE::USAGE;

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd != NULL)
    {
        if (pc_isGM(sd) >= pc_isGM(pl_sd))
        {
            // you can reset a character only for lower or same GM level
            int i;

            // Reset base level
            pl_sd->status.base_level = 1;
            pl_sd->status.base_exp = 0;
            clif_updatestatus(pl_sd, SP::BASELEVEL);
            clif_updatestatus(pl_sd, SP::NEXTBASEEXP);
            clif_updatestatus(pl_sd, SP::BASEEXP);

            // Reset job level
            pl_sd->status.job_level = 1;
            pl_sd->status.job_exp = 0;
            clif_updatestatus(pl_sd, SP::JOBLEVEL);
            clif_updatestatus(pl_sd, SP::NEXTJOBEXP);
            clif_updatestatus(pl_sd, SP::JOBEXP);

            // Zeny to 50
            pl_sd->status.zeny = 50;
            clif_updatestatus(pl_sd, SP::ZENY);

            // Clear inventory
            for (i = 0; i < MAX_INVENTORY; i++)
            {
                if (sd->status.inventory[i].amount)
                {
                    if (bool(sd->status.inventory[i].equip))
                        pc_unequipitem(pl_sd, i, CalcStatus::NOW);
                    pc_delitem(pl_sd, i, sd->status.inventory[i].amount, 0);
                }
            }

            // Give knife and shirt
            struct item item;
            item.nameid = 1201;
            // knife
            item.identify = 1;
            item.broken = 0;
            pc_additem(pl_sd, &item, 1);
            item.nameid = 1202;
            // shirt
            pc_additem(pl_sd, &item, 1);

            // Reset stats and skills
            pc_calcstatus(pl_sd, 0);
            pc_resetstate(pl_sd);
            pc_resetskill(pl_sd);
            pc_setglobalreg(pl_sd, stringish<VarName>("MAGIC_FLAGS"), 0);
            // [Fate] Reset magic quest variables
            pc_setglobalreg(pl_sd, stringish<VarName>("MAGIC_EXP"), 0);
            // [Fate] Reset magic experience

            FString output = STRPRINTF("%s:  wiped.", character);
            clif_displaymessage(fd, output);
        }
        else
        {
            clif_displaymessage(fd, "Your GM level don't authorise you to do this action on this player.");
            return ATCE::PERM;
        }
    }
    else
    {
        clif_displaymessage(fd, "Character not found.");
        return ATCE::EXIST;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_charmodel(const int fd, dumb_ptr<map_session_data>,
        ZString message)
{
    unsigned hair_style = 0, hair_color = 0, cloth_color = 0;
    CharName character;

    if (!asplit(message, &hair_style, &hair_color, &cloth_color, &character))
        return ATCE::USAGE;

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd != NULL)
    {
        if (hair_style >= MIN_HAIR_STYLE && hair_style <= MAX_HAIR_STYLE &&
            hair_color >= MIN_HAIR_COLOR && hair_color <= MAX_HAIR_COLOR &&
            cloth_color >= MIN_CLOTH_COLOR && cloth_color <= MAX_CLOTH_COLOR)
        {
            {
                pc_changelook(pl_sd, LOOK::HAIR, hair_style);
                pc_changelook(pl_sd, LOOK::HAIR_COLOR, hair_color);
                pc_changelook(pl_sd, LOOK::CLOTHES_COLOR, cloth_color);
                clif_displaymessage(fd, "Appearence changed.");
            }
        }
        else
            return ATCE::RANGE;
    }
    else
    {
        clif_displaymessage(fd, "Character not found.");
        return ATCE::EXIST;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_charskpoint(const int fd, dumb_ptr<map_session_data>,
        ZString message)
{
    CharName character;
    int new_skill_point;
    int point = 0;

    if (!asplit(message, &point, &character)
        || point == 0)
        return ATCE::USAGE;

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd != NULL)
    {
        new_skill_point = pl_sd->status.skill_point + point;
        if (point > 0 && (point > 0x7FFF || new_skill_point > 0x7FFF))
            // fix positiv overflow
            new_skill_point = 0x7FFF;
        else if (point < 0 && (point < -0x7FFF || new_skill_point < 0))
            // fix negativ overflow
            new_skill_point = 0;
        if (new_skill_point != pl_sd->status.skill_point)
        {
            pl_sd->status.skill_point = new_skill_point;
            clif_updatestatus(pl_sd, SP::SKILLPOINT);
            clif_displaymessage(fd, "Character's number of skill points changed!");
        }
        else
            return ATCE::RANGE;
    }
    else
    {
        clif_displaymessage(fd, "Character not found.");
        return ATCE::EXIST;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_charstpoint(const int fd, dumb_ptr<map_session_data>,
        ZString message)
{
    CharName character;
    int new_status_point;
    int point = 0;

    if (!asplit(message, &point, &character)
        || point == 0)
        return ATCE::USAGE;

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd != NULL)
    {
        new_status_point = pl_sd->status.status_point + point;
        if (point > 0 && (point > 0x7FFF || new_status_point > 0x7FFF))
            // fix positiv overflow
            new_status_point = 0x7FFF;
        else if (point < 0 && (point < -0x7FFF || new_status_point < 0))
            // fix negativ overflow
            new_status_point = 0;
        if (new_status_point != pl_sd->status.status_point)
        {
            pl_sd->status.status_point = new_status_point;
            clif_updatestatus(pl_sd, SP::STATUSPOINT);
            clif_displaymessage(fd, "Character's number of status points changed!");
        }
        else
            return ATCE::RANGE;
    }
    else
    {
        clif_displaymessage(fd, "Character not found.");
        return ATCE::EXIST;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_charzeny(const int fd, dumb_ptr<map_session_data>,
        ZString message)
{
    CharName character;
    int zeny = 0, new_zeny;

    if (!asplit(message, &zeny, &character) || zeny == 0)
        return ATCE::USAGE;

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd != NULL)
    {
        new_zeny = pl_sd->status.zeny + zeny;
        if (zeny > 0 && (zeny > MAX_ZENY || new_zeny > MAX_ZENY))
            // fix positiv overflow
            new_zeny = MAX_ZENY;
        else if (zeny < 0 && (zeny < -MAX_ZENY || new_zeny < 0))
            // fix negativ overflow
            new_zeny = 0;
        if (new_zeny != pl_sd->status.zeny)
        {
            pl_sd->status.zeny = new_zeny;
            clif_updatestatus(pl_sd, SP::ZENY);
            clif_displaymessage(fd, "Character's number of zenys changed!");
        }
        else
            return ATCE::RANGE;
    }
    else
    {
        clif_displaymessage(fd, "Character not found.");
        return ATCE::EXIST;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_recallall(const int fd, dumb_ptr<map_session_data> sd,
        ZString)
{
    int count;

    if (sd->bl_m && sd->bl_m->flag.nowarpto
        && battle_config.any_warp_GM_min_level > pc_isGM(sd))
    {
        clif_displaymessage(fd,
                "You are not authorised to warp somenone to your actual map.");
        return ATCE::PERM;
    }

    count = 0;
    for (int i = 0; i < fd_max; i++)
    {
        if (!session[i])
            continue;
        dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(session[i]->session_data.get()));
        if (pl_sd
            && pl_sd->state.auth
            && sd->status.account_id != pl_sd->status.account_id
            && pc_isGM(sd) >= pc_isGM(pl_sd))
        {
            // you can recall only lower or same level
            if (pl_sd->bl_m && pl_sd->bl_m->flag.nowarp
                && battle_config.any_warp_GM_min_level > pc_isGM(sd))
                count++;
            else
                pc_setpos(pl_sd, sd->mapname_, sd->bl_x, sd->bl_y, BeingRemoveWhy::QUIT);
        }
    }

    clif_displaymessage(fd, "All characters recalled!");
    if (count)
    {
        FString output = STRPRINTF(
                "Because you are not authorised to warp from some maps, %d player(s) have not been recalled.",
                count);
        clif_displaymessage(fd, output);
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_partyrecall(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    PartyName party_name;
    struct party *p;
    int count;

    if (!extract(message, &party_name) || !party_name)
        return ATCE::USAGE;

    if (sd->bl_m && sd->bl_m->flag.nowarpto
        && battle_config.any_warp_GM_min_level > pc_isGM(sd))
    {
        clif_displaymessage(fd,
                "You are not authorised to warp somenone to your actual map.");
        return ATCE::PERM;
    }

    if ((p = party_searchname(party_name)) != NULL ||
            // name first to avoid error when name begin with a number
        (p = party_search(atoi(message.c_str()))) != NULL)
    {
        count = 0;
        for (int i = 0; i < fd_max; i++)
        {
            if (!session[i])
                continue;
            dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(session[i]->session_data.get()));
            if (pl_sd && pl_sd->state.auth
                && sd->status.account_id != pl_sd->status.account_id
                && pl_sd->status.party_id == p->party_id)
            {
                if (pl_sd->bl_m && pl_sd->bl_m->flag.nowarp
                    && battle_config.any_warp_GM_min_level > pc_isGM(sd))
                    count++;
                else
                    pc_setpos(pl_sd, sd->mapname_, sd->bl_x, sd->bl_y, BeingRemoveWhy::QUIT);
            }
        }
        FString output = STRPRINTF("All online characters of the %s party are near you.", p->name);
        clif_displaymessage(fd, output);
        if (count)
        {
            output = STRPRINTF(
                    "Because you are not authorised to warp from some maps, %d player(s) have not been recalled.",
                    count);
            clif_displaymessage(fd, output);
        }
    }
    else
    {
        clif_displaymessage(fd, "Incorrect name or ID, or no one from the party is online.");
        return ATCE::EXIST;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_reloaditemdb(const int fd, dumb_ptr<map_session_data>,
        ZString)
{
    itemdb_reload();
    clif_displaymessage(fd, "Item database reloaded.");

    return ATCE::OKAY;
}

static
ATCE atcommand_reloadmobdb(const int fd, dumb_ptr<map_session_data>,
        ZString)
{
    mob_reload();
    clif_displaymessage(fd, "Monster database reloaded.");

    return ATCE::OKAY;
}

static
ATCE atcommand_reloadskilldb(const int fd, dumb_ptr<map_session_data>,
        ZString)
{
    skill_reload();
    clif_displaymessage(fd, "Skill database reloaded.");

    return ATCE::OKAY;
}

static
ATCE atcommand_reloadscript(const int fd, dumb_ptr<map_session_data>,
        ZString)
{
    do_init_npc();
    do_init_script();

    npc_event_do_oninit();

    clif_displaymessage(fd, "Scripts reloaded.");

    return ATCE::OKAY;
}

static
ATCE atcommand_reloadgmdb(const int fd, dumb_ptr<map_session_data>,
        ZString)
{
    chrif_reloadGMdb();

    clif_displaymessage(fd, "Login-server asked to reload GM accounts and their level.");

    return ATCE::OKAY;
}

static
ATCE atcommand_mapinfo(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    dumb_ptr<npc_data> nd = NULL;
    MapName map_name;
    const char *direction = NULL;
    int list = 0;

    extract(message, record<' '>(&list, &map_name));

    if (list < 0 || list > 2)
        return ATCE::USAGE;

    if (!map_name)
        map_name = sd->mapname_;

    map_local *m_id = map_mapname2mapid(map_name);
    if (m_id != nullptr)
        return ATCE::EXIST;

    clif_displaymessage(fd, "------ Map Info ------");
    FString output = STRPRINTF("Map Name: %s", map_name);
    clif_displaymessage(fd, output);
    output = STRPRINTF("Players In Map: %d", m_id->users);
    clif_displaymessage(fd, output);
    output = STRPRINTF("NPCs In Map: %d", m_id->npc_num);
    clif_displaymessage(fd, output);
    clif_displaymessage(fd, "------ Map Flags ------");
    output = STRPRINTF("Player vs Player: %s | No Party: %s",
             (m_id->flag.pvp) ? "True" : "False",
             (m_id->flag.pvp_noparty) ? "True" : "False");
    clif_displaymessage(fd, output);
    output = STRPRINTF("No Dead Branch: %s",
             (m_id->flag.nobranch) ? "True" : "False");
    clif_displaymessage(fd, output);
    output = STRPRINTF("No Memo: %s",
             (m_id->flag.nomemo) ? "True" : "False");
    clif_displaymessage(fd, output);
    output = STRPRINTF("No Penalty: %s",
             (m_id->flag.nopenalty) ? "True" : "False");
    clif_displaymessage(fd, output);
    output = STRPRINTF("No Return: %s",
             (m_id->flag.noreturn) ? "True" : "False");
    clif_displaymessage(fd, output);
    output = STRPRINTF("No Save: %s",
             (m_id->flag.nosave) ? "True" : "False");
    clif_displaymessage(fd, output);
    output = STRPRINTF("No Teleport: %s",
             (m_id->flag.noteleport) ? "True" : "False");
    clif_displaymessage(fd, output);
    output = STRPRINTF("No Monster Teleport: %s",
             (m_id->flag.monster_noteleport) ? "True" : "False");
    clif_displaymessage(fd, output);
    output = STRPRINTF("No Zeny Penalty: %s",
             (m_id->flag.nozenypenalty) ? "True" : "False");
    clif_displaymessage(fd, output);

    switch (list)
    {
        case 0:
            // Do nothing. It's list 0, no additional display.
            break;
        case 1:
            clif_displaymessage(fd, "----- Players in Map -----");
            for (int i = 0; i < fd_max; i++)
            {
                if (!session[i])
                    continue;
                dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(session[i]->session_data.get()));
                if (pl_sd && pl_sd->state.auth
                    && pl_sd->mapname_ == map_name)
                {
                    output = STRPRINTF(
                            "Player '%s' (session #%d) | Location: %d,%d",
                            pl_sd->status.name, i, pl_sd->bl_x, pl_sd->bl_y);
                    clif_displaymessage(fd, output);
                }
            }
            break;
        case 2:
            clif_displaymessage(fd, "----- NPCs in Map -----");
            for (int i = 0; i < m_id->npc_num;)
            {
                nd = m_id->npc[i];
                switch (nd->dir)
                {
                    case DIR::S:
                        direction = "North";
                        break;
                    case DIR::SW:
                        direction = "North West";
                        break;
                    case DIR::W:
                        direction = "West";
                        break;
                    case DIR::NW:
                        direction = "South West";
                        break;
                    case DIR::N:
                        direction = "South";
                        break;
                    case DIR::NE:
                        direction = "South East";
                        break;
                    case DIR::E:
                        direction = "East";
                        break;
                    case DIR::SE:
                        direction = "North East";
                        break;
#if 0
                    case 9:
                        direction = "North";
                        break;
#endif
                    default:
                        direction = "Unknown";
                        break;
                }
                output = STRPRINTF(
                         "NPC %d: %s | Direction: %s | Sprite: %d | Location: %d %d",
                         ++i, nd->name, direction, nd->npc_class, nd->bl_x,
                         nd->bl_y);
                clif_displaymessage(fd, output);
            }
            break;
        default:
            // normally impossible to arrive here
            clif_displaymessage(fd,
                    "Please, enter at least a valid list number (usage: @mapinfo <0-2> [map]).");
            return ATCE::USAGE;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_partyspy(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    PartyName party_name;

    if (!extract(message, &party_name))
        return ATCE::USAGE;

    struct party *p;
    if ((p = party_searchname(party_name)) != NULL ||
            // name first to avoid error when name begin with a number
        (p = party_search(atoi(message.c_str()))) != NULL)
    {
        if (sd->partyspy == p->party_id)
        {
            sd->partyspy = 0;
            FString output = STRPRINTF("No longer spying on the %s party.", p->name);
            clif_displaymessage(fd, output);
        }
        else
        {
            sd->partyspy = p->party_id;
            FString output = STRPRINTF("Spying on the %s party.", p->name);
            clif_displaymessage(fd, output);
        }
    }
    else
    {
        clif_displaymessage(fd, "Incorrect name or ID, or no one from the party is online.");
        return ATCE::EXIST;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_enablenpc(const int fd, dumb_ptr<map_session_data>,
        ZString message)
{
    NpcName NPCname;

    if (!extract(message, &NPCname) || !NPCname)
        return ATCE::USAGE;

    if (npc_name2id(NPCname) != NULL)
    {
        npc_enable(NPCname, 1);
        clif_displaymessage(fd, "Npc Enabled.");
    }
    else
    {
        clif_displaymessage(fd, "This NPC doesn't exist.");
        return ATCE::EXIST;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_disablenpc(const int fd, dumb_ptr<map_session_data>,
        ZString message)
{
    NpcName NPCname;

    if (!extract(message, &NPCname) || !NPCname)
        return ATCE::USAGE;

    if (npc_name2id(NPCname) != NULL)
    {
        npc_enable(NPCname, 0);
        clif_displaymessage(fd, "Npc Disabled.");
    }
    else
    {
        clif_displaymessage(fd, "This NPC doesn't exist.");
        return ATCE::EXIST;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_servertime(const int fd, dumb_ptr<map_session_data>,
        ZString)
{
    timestamp_seconds_buffer tsbuf;
    stamp_time(tsbuf);
    FString temp = STRPRINTF("Server time: %s", tsbuf);
    clif_displaymessage(fd, temp);

    return ATCE::OKAY;
}

static
ATCE atcommand_chardelitem(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    CharName character;
    ItemName item_name;
    int i, number = 0, item_id, item_position, count;
    struct item_data *item_data;

    if (!asplit(message, &item_name, &number, &character) || number < 1)
        return ATCE::USAGE;

    item_id = 0;
    if ((item_data = itemdb_searchname(item_name)) != NULL ||
        (item_data = itemdb_exists(atoi(item_name.c_str()))) != NULL)
        item_id = item_data->nameid;

    if (item_id > 500)
    {
        dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
        if (pl_sd != NULL)
        {
            if (pc_isGM(sd) >= pc_isGM(pl_sd))
            {
                // you can kill only lower or same level
                item_position = pc_search_inventory(pl_sd, item_id);
                if (item_position >= 0)
                {
                    count = 0;
                    for (i = 0; i < number && item_position >= 0; i++)
                    {
                        pc_delitem(pl_sd, item_position, 1, 0);
                        count++;
                        item_position = pc_search_inventory(pl_sd, item_id);
                        // for next loop
                    }
                    FString output = STRPRINTF(
                            "%d item(s) removed by a GM.",
                            count);
                    clif_displaymessage(pl_sd->fd, output);

                    if (number == count)
                        output = STRPRINTF("%d item(s) removed from the player.", count);
                    else
                        output = STRPRINTF("%d item(s) removed. Player had only %d on %d items.", count, count, number);
                    clif_displaymessage(fd, output);
                }
                else
                {
                    clif_displaymessage(fd, "Character does not have the item.");
                    return ATCE::EXIST;
                }
            }
            else
            {
                clif_displaymessage(fd, "Your GM level don't authorise you to do this action on this player.");
                return ATCE::PERM;
            }
        }
        else
        {
            clif_displaymessage(fd, "Character not found.");
            return ATCE::EXIST;
        }
    }
    else
    {
        clif_displaymessage(fd, "Invalid item ID or name.");
        return ATCE::RANGE;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_broadcast(const int, dumb_ptr<map_session_data> sd,
        ZString message)
{
    if (!message)
        return ATCE::USAGE;

    FString output = STRPRINTF("%s : %s", sd->status.name, message);
    intif_GMmessage(output);

    return ATCE::OKAY;
}

static
ATCE atcommand_localbroadcast(const int, dumb_ptr<map_session_data> sd,
        ZString message)
{
    if (!message)
        return ATCE::USAGE;

    FString output = STRPRINTF("%s : %s", sd->status.name, message);

    clif_GMmessage(sd, output, 1);

    return ATCE::OKAY;
}

static
ATCE atcommand_email(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    AccountEmail actual_email;
    AccountEmail new_email;

    if (!extract(message, record<' '>(&actual_email, &new_email)))
        return ATCE::USAGE;

    if (!e_mail_check(actual_email))
    {
        clif_displaymessage(fd, "Invalid actual email. If you have default e-mail, type a@a.com.");
        return ATCE::RANGE;
    }
    else if (!e_mail_check(new_email))
    {
        clif_displaymessage(fd, "Invalid new email. Please enter a real e-mail.");
        return ATCE::RANGE;
    }
    else if (new_email == DEFAULT_EMAIL)
    {
        clif_displaymessage(fd, "New email must be a real e-mail.");
        return ATCE::RANGE;
    }
    else if (actual_email == new_email)
    {
        clif_displaymessage(fd, "New email must be different of the actual e-mail.");
        return ATCE::RANGE;
    }
    else
    {
        chrif_changeemail(sd->status.account_id, actual_email, new_email);
        clif_displaymessage(fd, "Information sended to login-server via char-server.");
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_effect(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    int type = 0, flag = 0;

    if (!extract(message, record<' '>(&type, &flag)))
        return ATCE::USAGE;
    if (flag <= 0)
    {
        clif_specialeffect(sd, type, flag);
        clif_displaymessage(fd, "Your Effect Has Changed.");
    }
    else
    {
        for (int i = 0; i < fd_max; i++)
        {
            if (!session[i])
                continue;
            dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(session[i]->session_data.get()));
            if (pl_sd && pl_sd->state.auth)
            {
                clif_specialeffect(pl_sd, type, flag);
                clif_displaymessage(pl_sd->fd, "Your Effect Has Changed.");
            }
        }
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_character_item_list(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    struct item_data *item_data = NULL, *item_temp;
    int i, j, count, counter, counter2;
    CharName character;

    if (!asplit(message, &character))
        return ATCE::USAGE;

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd != NULL)
    {
        if (pc_isGM(sd) >= pc_isGM(pl_sd))
        {
            // you can look items only lower or same level
            counter = 0;
            count = 0;
            for (i = 0; i < MAX_INVENTORY; i++)
            {
                if (pl_sd->status.inventory[i].nameid > 0
                    && (item_data =
                        itemdb_search(pl_sd->status.inventory[i].nameid)) !=
                    NULL)
                {
                    counter = counter + pl_sd->status.inventory[i].amount;
                    count++;
                    if (count == 1)
                    {
                        FString output = STRPRINTF(
                                "------ Items list of '%s' ------",
                                pl_sd->status.name);
                        clif_displaymessage(fd, output);
                    }
                    EPOS equip = pl_sd->status.inventory[i].equip;
                    MString equipstr;
                    if (bool(equip))
                    {
                        equipstr += "| equiped: ";
                        if (bool(equip & EPOS::GLOVES))
                            equipstr += "robe/gargment, ";
                        if (bool(equip & EPOS::CAPE))
                            equipstr += "left accessory, ";
                        if (bool(equip & EPOS::MISC1))
                            equipstr += "body/armor, ";
                        if ((equip & (EPOS::WEAPON | EPOS::SHIELD)) == EPOS::WEAPON)
                            equipstr += "right hand, ";
                        if ((equip & (EPOS::WEAPON | EPOS::SHIELD)) == EPOS::SHIELD)
                            equipstr += "left hand, ";
                        if ((equip & (EPOS::WEAPON | EPOS::SHIELD)) == (EPOS::WEAPON | EPOS::SHIELD))
                            equipstr += "both hands, ";
                        if (bool(equip & EPOS::SHOES))
                            equipstr += "feet, ";
                        if (bool(equip & EPOS::MISC2))
                            equipstr += "right accessory, ";
                        if ((equip & (EPOS::TORSO | EPOS::HAT | EPOS::LEGS)) == EPOS::LEGS)
                            equipstr += "lower head, ";
                        if ((equip & (EPOS::TORSO | EPOS::HAT | EPOS::LEGS)) == EPOS::HAT)
                            equipstr += "top head, ";
                        if ((equip & (EPOS::TORSO | EPOS::HAT | EPOS::LEGS)) == (EPOS::HAT | EPOS::LEGS))
                            equipstr += "lower/top head, ";
                        if ((equip & (EPOS::TORSO | EPOS::HAT | EPOS::LEGS)) == EPOS::TORSO)
                            equipstr += "mid head, ";
                        if ((equip & (EPOS::TORSO | EPOS::HAT | EPOS::LEGS)) == (EPOS::TORSO | EPOS::LEGS))
                            equipstr += "lower/mid head, ";
                        if ((equip & (EPOS::TORSO | EPOS::HAT | EPOS::LEGS)) == (EPOS::TORSO | EPOS::HAT | EPOS::LEGS))
                            equipstr += "lower/mid/top head, ";
                        // remove final ', '
                        equipstr.pop_back(2);
                    }
                    else
                        equipstr = MString();

                    FString output;
                    if (sd->status.inventory[i].refine)
                        output = STRPRINTF("%d %s %+d (%s %+d, id: %d) %s",
                                 pl_sd->status.inventory[i].amount,
                                 item_data->name,
                                 pl_sd->status.inventory[i].refine,
                                 item_data->jname,
                                 pl_sd->status.inventory[i].refine,
                                 pl_sd->status.inventory[i].nameid,
                                 FString(equipstr));
                    else
                        output = STRPRINTF("%d %s (%s, id: %d) %s",
                                 pl_sd->status.inventory[i].amount,
                                 item_data->name, item_data->jname,
                                 pl_sd->status.inventory[i].nameid,
                                 FString(equipstr));
                    clif_displaymessage(fd, output);

                    MString voutput;
                    counter2 = 0;
                    for (j = 0; j < item_data->slot; j++)
                    {
                        if (pl_sd->status.inventory[i].card[j])
                        {
                            if ((item_temp =
                                 itemdb_search(pl_sd->status.
                                                inventory[i].card[j])) !=
                                NULL)
                            {
                                if (!voutput)
                                    voutput += STRPRINTF(
                                            " -> (card(s): "
                                            "#%d %s (%s), ",
                                            ++counter2,
                                            item_temp->name,
                                            item_temp->jname);
                                else
                                    voutput += STRPRINTF(
                                            "#%d %s (%s), ",
                                            ++counter2,
                                            item_temp->name,
                                            item_temp->jname);
                            }
                        }
                    }
                    if (voutput)
                    {
                        // replace trailing ", "
                        voutput.pop_back();
                        voutput.back() = ')';
                        clif_displaymessage(fd, FString(voutput));
                    }
                }
            }
            if (count == 0)
                clif_displaymessage(fd, "No item found on this player.");
            else
            {
                FString output = STRPRINTF(
                        "%d item(s) found in %d kind(s) of items.",
                        counter, count);
                clif_displaymessage(fd, output);
            }
        }
        else
        {
            clif_displaymessage(fd, "Your GM level don't authorise you to do this action on this player.");
            return ATCE::PERM;
        }
    }
    else
    {
        clif_displaymessage(fd, "Character not found.");
        return ATCE::EXIST;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_character_storage_list(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    struct storage *stor;
    struct item_data *item_data = NULL, *item_temp;
    int i, j, count, counter, counter2;
    CharName character;

    if (!asplit(message, &character))
        return ATCE::USAGE;

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd != NULL)
    {
        if (pc_isGM(sd) >= pc_isGM(pl_sd))
        {
            // you can look items only lower or same level
            if ((stor = account2storage2(pl_sd->status.account_id)) != NULL)
            {
                counter = 0;
                count = 0;
                for (i = 0; i < MAX_STORAGE; i++)
                {
                    if (stor->storage_[i].nameid > 0
                        && (item_data =
                            itemdb_search(stor->storage_[i].nameid)) != NULL)
                    {
                        counter = counter + stor->storage_[i].amount;
                        count++;
                        if (count == 1)
                        {
                            FString output = STRPRINTF(
                                    "------ Storage items list of '%s' ------",
                                    pl_sd->status.name);
                            clif_displaymessage(fd, output);
                        }
                        FString output;
                        if (stor->storage_[i].refine)
                            output = STRPRINTF("%d %s %+d (%s %+d, id: %d)",
                                     stor->storage_[i].amount,
                                     item_data->name,
                                     stor->storage_[i].refine,
                                     item_data->jname,
                                     stor->storage_[i].refine,
                                     stor->storage_[i].nameid);
                        else
                            output = STRPRINTF("%d %s (%s, id: %d)",
                                     stor->storage_[i].amount,
                                     item_data->name, item_data->jname,
                                     stor->storage_[i].nameid);
                        clif_displaymessage(fd, output);

                        MString voutput;
                        counter2 = 0;
                        for (j = 0; j < item_data->slot; j++)
                        {
                            if (stor->storage_[i].card[j])
                            {
                                if ((item_temp =
                                     itemdb_search(stor->
                                                    storage_[i].card[j])) !=
                                    NULL)
                                {
                                    if (!voutput)
                                        voutput += STRPRINTF(
                                                " -> (card(s): "
                                                "#%d %s (%s), ",
                                                ++counter2,
                                                item_temp->name,
                                                item_temp->jname);
                                    else
                                        voutput += STRPRINTF(
                                                "#%d %s (%s), ",
                                                ++counter2,
                                                item_temp->name,
                                                item_temp->jname);
                                }
                            }
                        }
                        if (voutput)
                        {
                            // replace last ", "
                            voutput.pop_back();
                            voutput.back() = ')';
                            clif_displaymessage(fd, FString(voutput));
                        }
                    }
                }
                if (count == 0)
                    clif_displaymessage(fd,
                            "No item found in the storage of this player.");
                else
                {
                    FString output = STRPRINTF(
                            "%d item(s) found in %d kind(s) of items.",
                            counter, count);
                    clif_displaymessage(fd, output);
                }
            }
            else
            {
                clif_displaymessage(fd, "This player has no storage.");
                return ATCE::OKAY;
            }
        }
        else
        {
            clif_displaymessage(fd, "Your GM level don't authorise you to do this action on this player.");
            return ATCE::PERM;
        }
    }
    else
    {
        clif_displaymessage(fd, "Character not found.");
        return ATCE::EXIST;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_character_cart_list(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    struct item_data *item_data = NULL, *item_temp;
    int i, j, count, counter, counter2;
    CharName character;

    if (!asplit(message, &character))
        return ATCE::USAGE;

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd != NULL)
    {
        if (pc_isGM(sd) >= pc_isGM(pl_sd))
        {
            // you can look items only lower or same level
            counter = 0;
            count = 0;
            for (i = 0; i < MAX_CART; i++)
            {
                if (pl_sd->status.cart[i].nameid > 0
                    && (item_data =
                        itemdb_search(pl_sd->status.cart[i].nameid)) != NULL)
                {
                    counter = counter + pl_sd->status.cart[i].amount;
                    count++;
                    if (count == 1)
                    {
                        FString output = STRPRINTF(
                                "------ Cart items list of '%s' ------",
                                pl_sd->status.name);
                        clif_displaymessage(fd, output);
                    }

                    FString output;
                    if (pl_sd->status.cart[i].refine)
                        output = STRPRINTF("%d %s %+d (%s %+d, id: %d)",
                                pl_sd->status.cart[i].amount,
                                item_data->name,
                                pl_sd->status.cart[i].refine,
                                item_data->jname,
                                pl_sd->status.cart[i].refine,
                                pl_sd->status.cart[i].nameid);
                    else

                        output = STRPRINTF("%d %s (%s, id: %d)",
                                pl_sd->status.cart[i].amount,
                                item_data->name, item_data->jname,
                                pl_sd->status.cart[i].nameid);
                    clif_displaymessage(fd, output);

                    MString voutput;
                    counter2 = 0;
                    for (j = 0; j < item_data->slot; j++)
                    {
                        if (pl_sd->status.cart[i].card[j])
                        {
                            if ((item_temp =
                                 itemdb_search(pl_sd->status.
                                                cart[i].card[j])) != NULL)
                            {
                                if (!voutput)
                                    voutput += STRPRINTF(
                                            " -> (card(s): "
                                            "#%d %s (%s), ",
                                            ++counter2,
                                            item_temp->name,
                                            item_temp->jname);
                                else
                                    voutput += STRPRINTF(
                                            "#%d %s (%s), ",
                                            ++counter2,
                                            item_temp->name,
                                            item_temp->jname);
                            }
                        }
                    }
                    if (voutput)
                    {
                        voutput.pop_back();
                        voutput.back() = '0';
                        clif_displaymessage(fd, FString(voutput));
                    }
                }
            }
            if (count == 0)
                clif_displaymessage(fd,
                        "No item found in the cart of this player.");
            else
            {
                FString output = STRPRINTF("%d item(s) found in %d kind(s) of items.",
                         counter, count);
                clif_displaymessage(fd, output);
            }
        }
        else
        {
            clif_displaymessage(fd, "Your GM level don't authorise you to do this action on this player.");
            return ATCE::PERM;
        }
    }
    else
    {
        clif_displaymessage(fd, "Character not found.");
        return ATCE::EXIST;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_killer(const int fd, dumb_ptr<map_session_data> sd,
        ZString)
{
    sd->special_state.killer = !sd->special_state.killer;

    if (sd->special_state.killer)
        clif_displaymessage(fd, "You be a killa...");
    else
        clif_displaymessage(fd, "You gonna be own3d...");

    return ATCE::OKAY;
}

static
ATCE atcommand_charkiller(const int fd, dumb_ptr<map_session_data>,
        ZString message)
{
    CharName character;

    if (!asplit(message, &character))
        return ATCE::USAGE;

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd == NULL)
        return ATCE::EXIST;

    pl_sd->special_state.killer = !pl_sd->special_state.killer;

    if (pl_sd->special_state.killer)
    {
        clif_displaymessage(fd, "The player is now a killer");
        clif_displaymessage(pl_sd->fd, "You are now a killer");
    }
    else
    {
        clif_displaymessage(fd, "The player is no longer a killer");
        clif_displaymessage(pl_sd->fd, "You are no longer a killer");
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_killable(const int fd, dumb_ptr<map_session_data> sd,
        ZString)
{
    sd->special_state.killable = !sd->special_state.killable;

    if (sd->special_state.killable)
        clif_displaymessage(fd, "You gonna be own3d...");
    else
        clif_displaymessage(fd, "You be a killa...");

    return ATCE::OKAY;
}

static
ATCE atcommand_charkillable(const int fd, dumb_ptr<map_session_data>,
        ZString message)
{
    CharName character;

    if (!asplit(message, &character))
        return ATCE::USAGE;

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd == NULL)
        return ATCE::EXIST;

    pl_sd->special_state.killable = !pl_sd->special_state.killable;

    if (pl_sd->special_state.killable)
        clif_displaymessage(fd, "The player is now killable");
    else
        clif_displaymessage(fd, "The player is no longer killable");

    return ATCE::OKAY;
}

static
ATCE atcommand_npcmove(const int, dumb_ptr<map_session_data>,
        ZString message)
{
    NpcName character;
    int x = 0, y = 0;
    dumb_ptr<npc_data> nd = 0;

    if (!asplit(message, &x, &y, &character))
        return ATCE::USAGE;

    nd = npc_name2id(character);
    if (nd == NULL)
        return ATCE::EXIST;

    npc_enable(character, 0);
    nd->bl_x = x;
    nd->bl_y = y;
    npc_enable(character, 1);

    return ATCE::OKAY;
}

static
ATCE atcommand_addwarp(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    MapName mapname;
    int x, y;

    if (!extract(message, record<' '>(&mapname, &x, &y)))
        return ATCE::USAGE;

    FString w1 = STRPRINTF("%s,%d,%d", sd->mapname_, sd->bl_x, sd->bl_y);
    FString w3 = STRPRINTF("%s%d%d%d%d", mapname, sd->bl_x, sd->bl_y, x, y);
    FString w4 = STRPRINTF("1,1,%s.gat,%d,%d", mapname, x, y);

    NpcName w3name = stringish<NpcName>(w3);
    int ret = npc_parse_warp(w1, ZString("warp"), w3name, w4);
    if (ret)
        // warp failed
        return ATCE::RANGE;

    FString output = STRPRINTF("New warp NPC => %s", w3);
    clif_displaymessage(fd, output);

    return ATCE::OKAY;
}

static
ATCE atcommand_chareffect(const int fd, dumb_ptr<map_session_data>,
        ZString message)
{
    CharName target;
    int type = 0;

    if (!asplit(message, &type, &target))
        return ATCE::USAGE;

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(target);
    if (pl_sd == NULL)
        return ATCE::EXIST;

    clif_specialeffect(pl_sd, type, 0);
    clif_displaymessage(fd, "Your Effect Has Changed.");

    return ATCE::OKAY;
}

static
ATCE atcommand_dropall(const int, dumb_ptr<map_session_data> sd,
        ZString)
{
    int i;
    for (i = 0; i < MAX_INVENTORY; i++)
    {
        if (sd->status.inventory[i].amount)
        {
            if (bool(sd->status.inventory[i].equip))
                pc_unequipitem(sd, i, CalcStatus::NOW);
            pc_dropitem(sd, i, sd->status.inventory[i].amount);
        }
    }
    return ATCE::OKAY;
}

static
ATCE atcommand_chardropall(const int fd, dumb_ptr<map_session_data>,
        ZString message)
{
    CharName character;

    if (!asplit(message, &character))
        return ATCE::USAGE;
    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd == NULL)
        return ATCE::EXIST;
    for (int i = 0; i < MAX_INVENTORY; i++)
    {
        if (pl_sd->status.inventory[i].amount)
        {
            if (bool(pl_sd->status.inventory[i].equip))
                pc_unequipitem(pl_sd, i, CalcStatus::NOW);
            pc_dropitem(pl_sd, i, pl_sd->status.inventory[i].amount);
        }
    }

    clif_displaymessage(pl_sd->fd, "Ever play 52 card pickup?");
    clif_displaymessage(fd, "It is done");
    //clif_displaymessage(fd, "It is offical.. your a jerk");

    return ATCE::OKAY;
}

static
ATCE atcommand_storeall(const int fd, dumb_ptr<map_session_data> sd,
        ZString)
{
    int i;

    if (!sd->state.storage_open)
    {
        //Open storage.
        switch (storage_storageopen(sd))
        {
            case 2:
                //Try again
                clif_displaymessage(fd, "run this command again..");
                return ATCE::OKAY;
            case 1:
                //Failure
                clif_displaymessage(fd,
                        "You can't open the storage currently.");
                return ATCE::EXIST;
        }
    }
    for (i = 0; i < MAX_INVENTORY; i++)
    {
        if (sd->status.inventory[i].amount)
        {
            if (bool(sd->status.inventory[i].equip))
                pc_unequipitem(sd, i, CalcStatus::NOW);
            storage_storageadd(sd, i, sd->status.inventory[i].amount);
        }
    }
    storage_storageclose(sd);

    clif_displaymessage(fd, "It is done");
    return ATCE::OKAY;
}

static
ATCE atcommand_charstoreall(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    CharName character;

    if (!asplit(message, &character))
        return ATCE::USAGE;
    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd == NULL)
        return ATCE::EXIST;

    if (storage_storageopen(pl_sd) == 1)
    {
        // TODO figure out what the hell this is talking about,
        // and especially why it's different from the other one.
        clif_displaymessage(fd,
                "Had to open the characters storage window...");
        clif_displaymessage(fd, "run this command again..");
        return ATCE::OKAY;
    }
    for (int i = 0; i < MAX_INVENTORY; i++)
    {
        if (pl_sd->status.inventory[i].amount)
        {
            if (bool(pl_sd->status.inventory[i].equip))
                pc_unequipitem(pl_sd, i, CalcStatus::NOW);
            storage_storageadd(pl_sd, i, sd->status.inventory[i].amount);
        }
    }
    storage_storageclose(pl_sd);

    clif_displaymessage(pl_sd->fd,
            "Everything you own has been put away for safe keeping.");
    clif_displaymessage(pl_sd->fd,
            "go to the nearest kafka to retrieve it..");
    clif_displaymessage(pl_sd->fd, "   -- the management");

    clif_displaymessage(fd, "It is done");

    return ATCE::OKAY;
}

static
ATCE atcommand_rain(const int, dumb_ptr<map_session_data> sd,
        ZString)
{
    int effno = 0;
    effno = 161;
    if (effno < 0 || sd->bl_m->flag.rain)
        return ATCE::EXIST;

    sd->bl_m->flag.rain = 1;
    clif_specialeffect(sd, effno, 2);
    return ATCE::OKAY;
}

static
ATCE atcommand_snow(const int, dumb_ptr<map_session_data> sd,
        ZString)
{
    int effno = 0;
    effno = 162;
    if (effno < 0 || sd->bl_m->flag.snow)
        return ATCE::EXIST;

    sd->bl_m->flag.snow = 1;
    clif_specialeffect(sd, effno, 2);
    return ATCE::OKAY;
}

static
ATCE atcommand_sakura(const int, dumb_ptr<map_session_data> sd,
        ZString)
{
    int effno = 0;
    effno = 163;
    if (effno < 0 || sd->bl_m->flag.sakura)
        return ATCE::EXIST;

    sd->bl_m->flag.sakura = 1;
    clif_specialeffect(sd, effno, 2);
    return ATCE::OKAY;
}

static
ATCE atcommand_fog(const int, dumb_ptr<map_session_data> sd,
        ZString)
{
    int effno = 0;
    effno = 233;
    if (effno < 0 || sd->bl_m->flag.fog)
        return ATCE::EXIST;

    sd->bl_m->flag.fog = 1;
    clif_specialeffect(sd, effno, 2);

    return ATCE::OKAY;
}

static
ATCE atcommand_leaves(const int, dumb_ptr<map_session_data> sd,
        ZString)
{
    int effno = 0;
    effno = 333;
    if (effno < 0 || sd->bl_m->flag.leaves)
        return ATCE::EXIST;

    sd->bl_m->flag.leaves = 1;
    clif_specialeffect(sd, effno, 2);
    return ATCE::OKAY;
}

static
ATCE atcommand_summon(const int, dumb_ptr<map_session_data> sd,
        ZString message)
{
    MobName name;
    int mob_id = 0;
    int x = 0;
    int y = 0;
    int id = 0;
    tick_t tick = gettick();

    if (!extract(message, &name) || !name)
        return ATCE::USAGE;

    if ((mob_id = atoi(name.c_str())) == 0)
        mob_id = mobdb_searchname(name);
    if (mob_id == 0)
        return ATCE::EXIST;

    x = sd->bl_x + random_::in(-5, 4);
    y = sd->bl_y + random_::in(-5, 4);

    id = mob_once_spawn(sd, MOB_THIS_MAP, x, y, JAPANESE_NAME, mob_id, 1, NpcEvent());
    dumb_ptr<mob_data> md = map_id_is_mob(id);
    if (md)
    {
        md->master_id = sd->bl_id;
        md->state.special_mob_ai = 1;
        md->mode = mob_db[md->mob_class].mode | MobMode::AGGRESSIVE;
        md->deletetimer = Timer(tick + std::chrono::minutes(1),
                std::bind(mob_timer_delete, ph::_1, ph::_2,
                    id));
        clif_misceffect(md, 344);
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_adjcmdlvl(const int fd, dumb_ptr<map_session_data>,
        ZString message)
{
    int newlev;
    XString cmd;

    if (!extract(message, record<' '>(&newlev, &cmd)))
    {
        clif_displaymessage(fd, "usage: @adjcmdlvl <lvl> <command>.");
        return ATCE::USAGE;
    }

    AtCommandInfo *it = atcommand_info.search(cmd);
    {
        if (it)
        {
            it->level = newlev;
            clif_displaymessage(fd, "@command level changed.");
            return ATCE::OKAY;
        }
    }

    clif_displaymessage(fd, "@command not found.");
    return ATCE::EXIST;
}

static
ATCE atcommand_adjgmlvl(const int fd, dumb_ptr<map_session_data>,
        ZString message)
{
    int newlev;
    CharName user;

    if (!asplit(message, &newlev, &user)
        || newlev < 0 || newlev > 99)
    {
        clif_displaymessage(fd, "usage: @adjgmlvl <lvl> <user>.");
        return ATCE::USAGE;
    }

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(user);
    if (pl_sd == NULL)
        return ATCE::EXIST;

    pc_set_gm_level(pl_sd->status.account_id, newlev);

    return ATCE::OKAY;
}

static
ATCE atcommand_trade(const int, dumb_ptr<map_session_data> sd,
        ZString message)
{
    CharName character;

    if (!asplit(message, &character))
        return ATCE::USAGE;

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd)
    {
        trade_traderequest(sd, pl_sd->bl_id);
        return ATCE::OKAY;
    }
    return ATCE::EXIST;
}

/* Magic atcommands by Fate */

static
SkillID magic_skills[] =
{
    SkillID::TMW_MAGIC,
    SkillID::TMW_MAGIC_LIFE,
    SkillID::TMW_MAGIC_WAR,
    SkillID::TMW_MAGIC_TRANSMUTE,
    SkillID::TMW_MAGIC_NATURE,
    SkillID::TMW_MAGIC_ETHER,
};

constexpr
size_t magic_skills_nr = sizeof(magic_skills) / sizeof(magic_skills[0]);

static
ZString magic_skill_names[magic_skills_nr] =
{
    {"magic"},
    {"life"},
    {"war"},
    {"transmute"},
    {"nature"},
    {"astral"},
};

static
ATCE atcommand_magic_info(const int fd, dumb_ptr<map_session_data>,
        ZString message)
{
    CharName character;

    if (!asplit(message, &character))
        return ATCE::USAGE;

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd)
    {
        FString buf = STRPRINTF(
                "`%s' has the following magic skills:",
                character);
        clif_displaymessage(fd, buf);

        for (size_t i = 0; i < magic_skills_nr; i++)
        {
            SkillID sk = magic_skills[i];
            buf = STRPRINTF(
                    "%d in %s",
                    pl_sd->status.skill[sk].lv,
                    magic_skill_names[i]);
            if (pl_sd->status.skill[sk].lv)
                clif_displaymessage(fd, buf);
        }

        return ATCE::OKAY;
    }

    clif_displaymessage(fd, "Character not found.");
    return ATCE::EXIST;
}

static
void set_skill(dumb_ptr<map_session_data> sd, SkillID i, int level)
{
    sd->status.skill[i].lv = level;
}

static
ATCE atcommand_set_magic(const int fd, dumb_ptr<map_session_data>,
        ZString message)
{
    CharName character;
    XString magic_type;
    int value;

    if (!asplit(message, &magic_type, &value, &character))
    {
        clif_displaymessage(fd,
                "Usage: @setmagic <school> <value> <char-name>, where <school> is either `magic', one of the school names, or `all'.");
        return ATCE::USAGE;
    }

    SkillID skill_index = SkillID::NEGATIVE;
    if ("all" == magic_type)
        skill_index = SkillID::ZERO;
    else
    {
        for (size_t i = 0; i < magic_skills_nr; i++)
        {
            if (magic_skill_names[i] == magic_type)
            {
                skill_index = magic_skills[i];
                break;
            }
        }
    }

    if (skill_index == SkillID::NEGATIVE)
    {
        clif_displaymessage(fd,
                "Incorrect school of magic.  Use `magic', `nature', `life', `war', `transmute', `ether', or `all'.");
        return ATCE::RANGE;
    }

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd != NULL)
    {
        if (skill_index == SkillID::ZERO)
            for (SkillID sk : magic_skills)
                set_skill(pl_sd, sk, value);
        else
            set_skill(pl_sd, skill_index, value);

        clif_skillinfoblock(pl_sd);
        return ATCE::OKAY;
    }

    clif_displaymessage(fd, "Character not found.");
    return ATCE::EXIST;
}

static
ATCE atcommand_log(const int, dumb_ptr<map_session_data>,
        ZString)
{
    return ATCE::OKAY;
    // only used for (implicit) logging
}

static
ATCE atcommand_tee(const int, dumb_ptr<map_session_data> sd,
        ZString message)
{
    MString data;
    data += sd->status.name.to__actual();
    data += " : ";
    data += message;
    clif_message(sd, FString(data));
    return ATCE::OKAY;
}

static
ATCE atcommand_invisible(const int, dumb_ptr<map_session_data> sd,
        ZString)
{
    pc_invisibility(sd, 1);
    return ATCE::OKAY;
}

static
ATCE atcommand_visible(const int, dumb_ptr<map_session_data> sd,
        ZString)
{
    pc_invisibility(sd, 0);
    return ATCE::OKAY;
}

static
ATCE atcommand_jump_iterate(const int fd, dumb_ptr<map_session_data> sd,
        dumb_ptr<map_session_data> (*get_start)(void),
        dumb_ptr<map_session_data> (*get_next)(dumb_ptr<map_session_data>))
{
    dumb_ptr<map_session_data> pl_sd;

    pl_sd = map_id_is_player(sd->followtarget);

    if (pl_sd)
        pl_sd = get_next(pl_sd);

    if (!pl_sd)
        pl_sd = get_start();

    if (pl_sd == sd)
    {
        pl_sd = get_next(pl_sd);
        if (!pl_sd)
            pl_sd = get_start();
    }

    if (pl_sd->bl_m && pl_sd->bl_m->flag.nowarpto
        && battle_config.any_warp_GM_min_level > pc_isGM(sd))
    {
        clif_displaymessage(fd,
                "You are not authorised to warp you to the map of this player.");
        return ATCE::PERM;
    }
    if (sd->bl_m && sd->bl_m->flag.nowarp
        && battle_config.any_warp_GM_min_level > pc_isGM(sd))
    {
        clif_displaymessage(fd,
                "You are not authorised to warp you from your actual map.");
        return ATCE::PERM;
    }
    pc_setpos(sd, pl_sd->bl_m->name_, pl_sd->bl_x, pl_sd->bl_y, BeingRemoveWhy::WARPED);
    FString output = STRPRINTF("Jump to %s", pl_sd->status.name);
    clif_displaymessage(fd, output);

    sd->followtarget = pl_sd->bl_id;

    return ATCE::OKAY;
}

static
ATCE atcommand_iterate_forward_over_players(const int fd, dumb_ptr<map_session_data> sd, ZString)
{
    return atcommand_jump_iterate(fd, sd, map_get_first_session, map_get_next_session);
}

static
ATCE atcommand_iterate_backwards_over_players(const int fd, dumb_ptr<map_session_data> sd, ZString)
{
    return atcommand_jump_iterate(fd, sd, map_get_last_session, map_get_prev_session);
}

static
ATCE atcommand_wgm(const int fd, dumb_ptr<map_session_data> sd,
        ZString message)
{
    if (tmw_CheckChatSpam(sd, message))
        return ATCE::OKAY;

    tmw_GmHackMsg(STRPRINTF("[GM] %s: %s", sd->status.name, message));
    if (!pc_isGM(sd))
        clif_displaymessage(fd, "Message sent.");

    return ATCE::OKAY;
}


static
ATCE atcommand_skillpool_info(const int fd, dumb_ptr<map_session_data>,
        ZString message)
{
    CharName character;

    if (!asplit(message, &character))
        return ATCE::USAGE;

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd != NULL)
    {
        SkillID pool_skills[MAX_SKILL_POOL];
        int pool_skills_nr = skill_pool(pl_sd, pool_skills);
        int i;

        FString buf = STRPRINTF(
                "Active skills %d out of %d for %s:",
                pool_skills_nr, skill_pool_max(pl_sd), character);
        clif_displaymessage(fd, buf);
        for (i = 0; i < pool_skills_nr; ++i)
        {
            buf = STRPRINTF(" - %s [%d]: power %d",
                    skill_name(pool_skills[i]),
                    pool_skills[i],
                    skill_power(pl_sd, pool_skills[i]));
            clif_displaymessage(fd, buf);
        }

        buf = STRPRINTF("Learned skills out of %d for %s:",
                skill_pool_skills_size, character);
        clif_displaymessage(fd, buf);

        for (i = 0; i < skill_pool_skills_size; ++i)
        {
            const FString& name = skill_name(skill_pool_skills[i]);
            int lvl = pl_sd->status.skill[skill_pool_skills[i]].lv;

            if (lvl)
            {
                buf = STRPRINTF(" - %s [%d]: lvl %d",
                        name, skill_pool_skills[i], lvl);
                clif_displaymessage(fd, buf);
            }
        }

    }
    else
    {
        clif_displaymessage(fd, "Character not found.");
        return ATCE::EXIST;
    }

    return ATCE::OKAY;
}

static
ATCE atcommand_skillpool_focus(const int fd, dumb_ptr<map_session_data>,
        ZString message)
{
    CharName character;
    SkillID skill;

    if (!asplit(message, &skill, &character))
    {
        clif_displaymessage(fd, "Usage: @sp-focus <skill-nr> <char_name>");
        return ATCE::USAGE;
    }

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd != NULL)
    {
        if (skill_pool_activate(pl_sd, skill))
            clif_displaymessage(fd, "Activation failed.");
        else
            clif_displaymessage(fd, "Activation successful.");
    }
    else
        clif_displaymessage(fd, "Character not found.");

    return ATCE::OKAY;
}

static
ATCE atcommand_skillpool_unfocus(const int fd, dumb_ptr<map_session_data>,
        ZString message)
{
    CharName character;
    SkillID skill;

    if (!asplit(message, &skill, &character))
        return ATCE::USAGE;

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd != NULL)
    {
        if (skill_pool_deactivate(pl_sd, skill))
            clif_displaymessage(fd, "Deactivation failed.");
        else
            clif_displaymessage(fd, "Deactivation successful.");
    }
    else
        clif_displaymessage(fd, "Character not found.");

    return ATCE::OKAY;
}

//static
ATCE atcommand_skill_learn(const int fd, dumb_ptr<map_session_data>,
        ZString message)
{
    CharName character;
    SkillID skill;
    int level;

    if (!asplit(message, &skill, &level, &character))
        return ATCE::USAGE;

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd != NULL)
    {
        set_skill(pl_sd, skill, level);
        clif_skillinfoblock(pl_sd);
    }
    else
        clif_displaymessage(fd, "Character not found.");

    return ATCE::OKAY;
}

static
ATCE atcommand_ipcheck(const int fd, dumb_ptr<map_session_data>,
        ZString message)
{
    CharName character;

    if (!asplit(message, &character))
        return ATCE::USAGE;

    dumb_ptr<map_session_data> pl_sd = map_nick2sd(character);
    if (pl_sd == NULL)
    {
        clif_displaymessage(fd, "Character not found.");
        return ATCE::EXIST;
    }

    IP4Address ip = pl_sd->get_ip();

    // We now have the IP address of a character.
    // Loop over all logged in sessions looking for matches.

    for (int i = 0; i < fd_max; i++)
    {
        if (!session[i])
            continue;
        pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(session[i]->session_data.get()));
        if (pl_sd && pl_sd->state.auth)
        {
            // Is checking GM levels really needed here?
            if (ip == pl_sd->get_ip())
            {
                FString output = STRPRINTF(
                        "Name: %s | Location: %s %d %d",
                        pl_sd->status.name, pl_sd->mapname_,
                        pl_sd->bl_x, pl_sd->bl_y);
                clif_displaymessage(fd, output);
            }
        }
    }

    clif_displaymessage(fd, "End of list");
    return ATCE::OKAY;
}

static
ATCE atcommand_doomspot(const int fd, dumb_ptr<map_session_data> sd,
        ZString)
{
    for (int i = 0; i < fd_max; i++)
    {
        if (!session[i])
            continue;
        dumb_ptr<map_session_data> pl_sd = dumb_ptr<map_session_data>(static_cast<map_session_data *>(session[i]->session_data.get()));
        if (pl_sd
            && pl_sd->state.auth && i != fd && sd->bl_m == pl_sd->bl_m
            && sd->bl_x == pl_sd->bl_x && sd->bl_y == pl_sd->bl_y
            && pc_isGM(sd) >= pc_isGM(pl_sd))
        {
            // you can doom only lower or same gm level
            pc_damage(NULL, pl_sd, pl_sd->status.hp + 1);
            clif_displaymessage(pl_sd->fd, "The holy messenger has given judgement.");
        }
    }
    clif_displaymessage(fd, "Judgement was made.");

    return ATCE::OKAY;
}



// declared extern above
Map<XString, AtCommandInfo> atcommand_info =
{
    {"help", {"[level[-level]|category|@command]",
        0, atcommand_help,
        "Show help"}},
    {"setup", {"<level> <charname>",
        40, atcommand_setup,
        "Safely set a chars levels and warp them to a special place (for TAW)"}},
    {"charwarp", {"<mapname> <x> <y> <charname>",
        60, atcommand_charwarp,
        "Warp a character to a point on another map"}},
    {"warp", {"<mapname> [x] [y]",
        40, atcommand_warp,
        "Warp yourself to another map"}},
    {"where", {"[charname]",
        40, atcommand_where,
        "Show location of a character or yourself"}},
    {"goto", {"<charname>",
        40, atcommand_goto,
        "Warp yourself to another character"}},
    {"jump", {"[x] [y]",
        40, atcommand_jump,
        "Warp yourself within a map"}},
    {"who", {"[subsequence]",
        40, atcommand_who,
        "List matching players online, with location info"}},
    {"whogroup", {"[subsequence]",
        40, atcommand_whogroup,
        "List matching players online, with party info"}},
    {"whomap", {"[mapname]",
        40, atcommand_whomap,
        "List all players on the map, with location info"}},
    {"whomapgroup", {"[mapname]",
        40, atcommand_whomapgroup,
        "List all players on the map, with party info"}},
    {"whogm", {"[subsequence]",
        40, atcommand_whogm,
        "List matching GM players, with location, level, and party info"}},
    {"save", {"",
        40, atcommand_save,
        "Set your respawn point to your current location"}},
    {"return", {"",
        40, atcommand_load,
        "Return to your respawn point"}},
    {"load", {"",
        40, atcommand_load,
        "Return to your respawn point"}},
    {"speed", {"<rate>",
        60, atcommand_speed,
        "Set walk rate"}},
    {"storage", {"",
        99, atcommand_storage,
        "Open your storage"}},
    {"option", {"<opt1> [opt2] [option]",
        80, atcommand_option,
        "Set your 'option' status flags"}},
    {"hide", {"",
        40, atcommand_hide,
        "Toggle invisibility from monsters and certain commands"}},
    {"die", {"",
        40, atcommand_die,
        "Cause fatal damage to yourself"}},
    {"kill", {"<charname>",
        60, atcommand_kill,
        "Cause fatal damage to another player"}},
    {"alive", {"",
        60, atcommand_alive,
        "Restore life to yourself"}},
    {"kami", {"<message ...>",
        99, atcommand_kami,
        "Send an anonymous broadcast"}},
    {"heal", {"[hp] [sp]",
        40, atcommand_heal,
        "Restore or destroy your health"}},
    {"item", {"<item-name-or-id> [count]",
        80, atcommand_item,
        "Summon items out of the void"}},
    {"itemreset", {"",
        40, atcommand_itemreset,
        "Cast all of your itens into the void (why would you ever want this?)"}},
    {"itemcheck", {"",
        80, atcommand_itemcheck,
        "Perform an internal integrity check on your items"}},
    {"blvl", {"<delta>",
        60, atcommand_baselevelup,
        "Adjust your level"}},
    {"jlvl", {"<delta>",
        60, atcommand_joblevelup,
        "Adjust your job level"}},
    {"gm", {"<password>",
        100, atcommand_gm,
        "Receive GM powers"}},
    {"pvpoff", {"",
        60, atcommand_pvpoff,
        "Enable PvP on your map"}},
    {"pvpon", {"",
        60, atcommand_pvpon,
        "Disable PvP on your map"}},
    {"model", {"<style> [color] [dye]",
        99, atcommand_model,
        "Change your hairstyle and hair color"}},
    {"spawn", {"<mob-name-or-id> [count] [x] [y]",
        50, atcommand_spawn,
        "Spawn normal monsters at location."}},
    {"killmonster", {"[map]",
        60, atcommand_killmonster,
        "Kill all monsters (with drops)"}},
    {"killmonster2", {"[map]",
        60, atcommand_killmonster2,
        "Kill all monsters (no drops)"}},
    {"gat", {"",
        99, atcommand_gat,
        "Dump the local walkmap"}},
    {"packet", {"<type> <flag>",
        99, atcommand_packet,
        "Force a status change"}},
    {"stpoint", {"<amount>",
        60, atcommand_statuspoint,
        "Increase your stat points"}},
    {"skpoint", {"<amount>",
        60, atcommand_skillpoint,
        "Increase your skill points"}},
    {"zeny", {"<amount>",
        80, atcommand_zeny,
        "Change how much money you have"}},
    {"str", {"<delta>",
        60, atcommand_param<ATTR::STR>,
        "Adjust your strength"}},
    {"agi", {"<delta>",
        60, atcommand_param<ATTR::AGI>,
        "Adjust your agility"}},
    {"vit", {"<delta>",
        60, atcommand_param<ATTR::VIT>,
        "Adjust your vitality"}},
    {"int", {"<delta>",
        60, atcommand_param<ATTR::INT>,
        "Adjust your intelligence\0(TODO make this work in real life, I'm lonely)"}},
    {"dex", {"<delta>",
        60, atcommand_param<ATTR::DEX>,
        "Adjust your dexterity"}},
    {"luk", {"<delta>",
        60, atcommand_param<ATTR::LUK>,
        "Adjust your luck"}},
    {"recall", {"<charname>",
        60, atcommand_recall,
        "Warp a player to you"}},
    {"revive", {"<charname>",
        60, atcommand_revive,
        "Restore a player to full health"}},
    {"charstats", {"<charname>",
        40, atcommand_character_stats,
        "Show a bunch of stats about a single user"}},
    {"charstatsall", {"",
        60, atcommand_character_stats_all,
        "Show a bunch of stats about all online users"}},
    {"charoption", {"<opt1> <opt2> <opt3> <charname>",
        80, atcommand_character_option,
        "Set option flags on another character"}},
    {"charsave", {"<map> <x> <y> <charname>",
        60, atcommand_character_save,
        "Set another character's save point"}},
    {"doom", {"",
        80, atcommand_doom,
        "Kill everyone on the server"}},
    {"doommap", {"",
        80, atcommand_doommap,
        "Kill everyone on your map"}},
    {"raise", {"",
        80, atcommand_raise,
        "Resurrect all players on the server"}},
    {"raisemap", {"",
        80, atcommand_raisemap,
        "Resurrect all players on your map"}},
    {"charbaselvl", {"<delta> <charname>",
        60, atcommand_character_baselevel,
        "Adjust another character's level"}},
    {"charjlvl", {"<delta> <charname>",
        60, atcommand_character_joblevel,
        "Adjust another character's job level"}},
    {"kick", {"<charname>",
        40, atcommand_kick,
        "Transiently kick a player off the server"}},
    {"kickall", {"",
        99, atcommand_kickall,
        "Transiently kick all players off the server"}},
    {"questskill", {"<skill-id>",
        99, atcommand_questskill,
        "Give yourself a quest (?) skill"}},
    {"charquestskill", {"<skill-id> <charname>",
        99, atcommand_charquestskill,
        "Give another player a quest (?) skill"}},
    {"lostskill", {"<skill-id>",
        80, atcommand_lostskill,
        "Take away one of your quest (?) skills"}},
    {"charlostskill", {"<skill-id> <charname>",
        99, atcommand_charlostskill,
        "Take away one of another player's quest (?) skills"}},
    {"party", {"<name>",
        99, atcommand_party,
        "Create a new party"}},
    {"mapexit", {"",
        99, atcommand_mapexit,
        "Try to kill the server kindly"}},
    {"idsearch", {"<item-subseq>",
        80, atcommand_idsearch,
        "Search for some items that might match"}},
    {"mapmove", {"<mapname> [x] [y]",
        40, atcommand_warp,
        "Warp to a different map"}},
    {"broadcast", {"<message ...>",
        40, atcommand_broadcast,
        "Broadcast a message from you"}},
    {"localbroadcast", {"<message ...>",
        40, atcommand_localbroadcast,
        "Broadcast a message from you locally"}},
    {"recallall", {"",
        80, atcommand_recallall,
        "Warp every online player to your current map"}},
    {"charskreset", {"<charname>",
        60, atcommand_charskreset,
        "Reset a player's skill points"}},
    {"charstreset", {"<charname>",
        60, atcommand_charstreset,
        "Reset a player's stat points"}},
    {"reloaditemdb", {"",
        99, atcommand_reloaditemdb,
        "Allegedly to reload the item database"}},
    {"reloadmobdb", {"",
        99, atcommand_reloadmobdb,
        "Allegedly to reload the mob database"}},
    {"reloadskilldb", {"",
        99, atcommand_reloadskilldb,
        "Allegedly to reload the skill database"}},
    {"reloadscript", {"",
        99, atcommand_reloadscript,
        "Allegedly to reload the script database"}},
    {"reloadgmdb", {"",
        99, atcommand_reloadgmdb,
        "Unnecessarily reload the GM database"}},
    {"charreset", {"<charname>",
        60, atcommand_charreset,
        "Reset a player's skills, stats, and magic"}},
    {"charmodel", {"<hairstyle> <hair-color> <dye> <charname>",
        99, atcommand_charmodel,
        "Change another character's appearance"}},
    {"charskpoint", {"<amount> <charname>",
        60, atcommand_charskpoint,
        "Adjust another player's skill points"}},
    {"charstpoint", {"<amount> <charname>",
        60, atcommand_charstpoint,
        "Adjust another player's stat points"}},
    {"charzeny", {"<delta> <charname>",
        80, atcommand_charzeny,
        "Adjust another player's money"}},
    {"mapinfo", {"<0-2> [map]",
        99, atcommand_mapinfo,
        "Show some stats for the map. 1 also shows players, 2 also shows NPCs"}},
    {"dye", {"<dye>",
        40, atcommand_dye,
        "Don't use"}},
    {"ccolor", {"<dye>",
        40, atcommand_dye,
        "Don't use"}},
    {"hairstyle", {"<style>",
        40, atcommand_hair_style,
        "Change your hairstyle"}},
    {"haircolor", {"<color>",
        40, atcommand_hair_color,
        "Change your hair color"}},
    {"allstats", {"[value]",
        60, atcommand_all_stats,
        "Adjust all stats by value (or maximum)"}},
    {"charchangesex", {"<charname>",
        60, atcommand_char_change_sex,
        "Flip a characters sex and disconnect them"}},
    {"block", {"<charname>",
        60, atcommand_char_block,
        "Permanently block a player's account from the server"}},
    {"unblock", {"<charname>",
        60, atcommand_char_unblock,
        "Remove a permanent block from a player's account"}},
    {"ban", {"<timedelta> <charname>",
        60, atcommand_char_ban,
        "Ban a player's account from the server for a limited time"}},
    {"unban", {"<timedelta> <charname>",
        60, atcommand_char_unban,
        "Remove a limited ban from a player's account"}},
    {"partyspy", {"<party-name-or-id>",
        99, atcommand_partyspy,
        "Listen to all chat within a party"}},
    {"partyrecall", {"<party-name-or-id>",
        99, atcommand_partyrecall,
        "Warp all members of a party to you"}},
    {"enablenpc", {"<npc-name>",
        80, atcommand_enablenpc,
        "Enable an NPC for visibility"}},
    {"disablenpc", {"<npc-name>",
        80, atcommand_disablenpc,
        "Disable an NPC for visibility"}},
    {"servertime", {"",
        0, atcommand_servertime,
        "Print the server's idea of the current time"}},
    {"chardelitem", {"<item-name-or-id> <count> <charname>",
        60, atcommand_chardelitem,
        "Delete items from a player's inventory"}},
    {"listnearby", {"",
        40, atcommand_list_nearby,
        "Print name of all nearby players"}},
    {"email", {"<actual@email> <new@email>",
        0, atcommand_email,
        "Changed your account's email"}},
    {"effect", {"<type> <flag>",
        99, atcommand_effect,
        "Apply a special effect to yourself (or everyone! wtf?)"}},
    {"charitemlist", {"<charname>",
        99, atcommand_character_item_list,
        "List a player's items"}},
    {"charstoragelist", {"<charname>",
        99, atcommand_character_storage_list,
        "List a player's storage"}},
    {"charcartlist", {"<charname>",
        99, atcommand_character_cart_list,
        "List a player's cart"}},
    {"addwarp", {"<mapname> <x> <y>",
        80, atcommand_addwarp,
        "Create a new permanent warp"}},
    {"killer", {"",
        60, atcommand_killer,
        "Toggle whether you are a killer"}},
    {"charkiller", {"<charname>",
        60, atcommand_charkiller,
        "Toggle whether a player is a killer"}},
    {"npcmove", {"<x> <y> <npc-name>",
        80, atcommand_npcmove,
        "Force an NPC to move on the map"}},
    {"killable", {"",
        60, atcommand_killable,
        "Toggle whether you are killable"}},
    {"charkillable", {"<charname>",
        60, atcommand_charkillable,
        "Toggle whether a player is killable"}},
    {"chareffect", {"<type> <target>",
        40, atcommand_chareffect,
        "Apply effect type with arg 0 to a player"}},
    {"dropall", {"",
        99, atcommand_dropall,
        "Drop all of your items"}},
    {"chardropall", {"<charname>",
        60, atcommand_chardropall,
        "Force a player to drop all of their items"}},
    {"storeall", {"",
        60, atcommand_storeall,
        "Store all of your items"}},
    {"charstoreall", {"<charname>",
        60, atcommand_charstoreall,
        "Store all of a player's items"}},
    {"rain", {"",
        99, atcommand_rain,
        "Enable the rain mapflag"}},
    {"snow", {"",
        99, atcommand_snow,
        "Enable the snow mapflag"}},
    {"sakura", {"",
        99, atcommand_sakura,
        "Enable the sakura mapflag"}},
    {"fog", {"",
        99, atcommand_fog,
        "Enable the fog mapflag"}},
    {"leaves", {"",
        99, atcommand_leaves,
        "Enable the leaves mapflag"}},
    {"summon", {"<mob-id-or-name>",
        50, atcommand_summon,
        "Summon a slave monster temporarily"}},
    {"adjgmlvl", {"<level> <cmd>",
        99, atcommand_adjgmlvl,
        "Temporarily adjust the GM level of a command"}},
    {"adjcmdlvl", {"<level> <charname>",
        99, atcommand_adjcmdlvl,
        "Temporarily adjust the GM level of a player"}},
    {"trade", {"<charname>",
        60, atcommand_trade,
        "Initiate trade with a player anywhere"}},
    {"charwipe", {"<charname>",
        60, atcommand_char_wipe,
        "Reset a character almost completely"}},
    {"setmagic", {"<school> <value> <charname>",
        80, atcommand_set_magic,
        "Force magic skill level"}},
    {"magicinfo", {"<charname>",
        80, atcommand_magic_info,
        "Show magic skills of a palyer"}},
    {"log", {"<message ...>",
        40, atcommand_log,
        "Write something directly to the log"}},
    {"l", {"<message ...>",
        40, atcommand_log,
        "Write something directly to the log"}},
    {"tee", {"<message ...>",
        40, atcommand_tee,
        "Duplicate a message to the log and public chat"}},
    {"t", {"<message ...>",
        40, atcommand_tee,
        "Duplicate a message to the log and public chat"}},
    {"invisible", {"",
        50, atcommand_invisible,
        "Make yourself invisible to players"}},
    {"visible", {"",
        50, atcommand_visible,
        "Make yourself visible to players"}},
    {"hugo", {"",
        60, atcommand_iterate_forward_over_players,
        "Jump to the next player"}},
    {"linus", {"",
        60, atcommand_iterate_backwards_over_players,
        "Jump to the previous player"}},
    {"sp-info", {"<charname>",
        40, atcommand_skillpool_info,
        "Show info about pool skills"}},
    {"sp-focus", {"<skill-id> <charname>",
        80, atcommand_skillpool_focus,
        "Focus on a pool skill"}},
    {"sp-unfocus", {"<skill-id> <charname>",
        80, atcommand_skillpool_unfocus,
        "Unfocus off of a pool skill"}},
    {"skill-learn", {"<skill-id> <level> <charname>",
        80, atcommand_skill_learn,
        "Change a skill level"}},
    {"wgm", {"<message ...>",
        0, atcommand_wgm,
        "Send a message to online GMs"}},
    {"ipcheck", {"<charname>",
        60, atcommand_ipcheck,
        "List players on the same IP address"}},
    {"doomspot", {"",
        60, atcommand_doomspot,
        "Kill all players on the same tile"}},
};