summaryrefslogblamecommitdiff
path: root/src/map/storage.cpp
blob: f8dbd0febc7053c3e4ab7b279b2e27f8ac574617 (plain) (tree)
1
                      



















                                                                           
 


                               
 


                         
                    

                    
                     
                  
                 
 

                        
      
                                   
 
                           
 
                       

 
                                              
 
                                                  

                     
                                           
                                      

                


                                        
                                               
 
                                         

 
      
                                         
 
                                 


                                            
                           

                                            
                                                      
 
                   
 
                               
                                               
 
                                                                 
                     
                                                  
                                                         

                 
 

                                                                            
 
                             
                               


                                       
             


                                            
                              

                                            
      
                                                                 


                                                               
          
 
                                          

                 
                                            
 
                               


                                           
                                                            



                                                                   
                                                           










                                                                  
                                   

                                      

                                               

                    
 
 
                                            
                             

                                            
      
                                                                 
                                              
 
 
                                                                       
                 
 


                                       
                                   
                               
                                           
     
                                           
 

                    
 
 
                                            
                                                 

                                            
                                                                            
 
                  
 
                   
                                                       
                     
 

                                                                      
 

                                            
 
                                            
                                                      
 

                                                                  
 
                                
                                                                             

                                     
                                                       
                                         
     
 
             


                                            
                                     

                                            
                                                                            
 
                  
                    
 
                   
                                                       
                     
 

                                          
 
                                      
                                               
 

                                                            
 
                                                                                    
                                                 
        
                                     

                                  
 
 
                                            
                                                         

                                            
                                                       
 
                  
 
                   
                                                       
                     
 
                          


                              
                                                                    
            
                                                               

                             
                               
 


                                  
                                       
     
 
             


                                            
                          

                                            
                                                       
 
                  
 
                   
 
                                                       

             
                                                                    
                                 
                                   
     
 
             

 
                                                         
 
                  
 
                                        

                 
 






                                                                                
                                 



                                                                             
                                   

                 
 
             

 
                                                                  
                                               
 
                                                 
 


                                                          


                                                     
                                      



                 
 
#include "storage.hpp"
//    storage.cpp - Storage handling.
//
//    Copyright © ????-2004 Athena Dev Teams
//    Copyright © 2004-2011 The Mana World Development Team
//    Copyright © 2011-2014 Ben Longbons <b.r.longbons@gmail.com>
//
//    This file is part of The Mana World (Athena server)
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.

#include "../compat/nullpo.hpp"

#include "../generic/db.hpp"

#include "../mmo/ids.hpp"
#include "../mmo/mmo.hpp"

#include "chrif.hpp"
#include "clif.hpp"
#include "intif.hpp"
#include "itemdb.hpp"
#include "map.hpp"
#include "pc.hpp"

#include "../poison.hpp"

static
Map<AccountId, Storage> storage_db;

void do_final_storage(void)
{
    storage_db.clear();
}

Storage *account2storage(AccountId account_id)
{
    Storage *stor = storage_db.search(account_id);
    if (stor == NULL)
    {
        stor = storage_db.init(account_id);
        stor->account_id = account_id;
    }
    return stor;
}

// Just to ask storage, without creation
Storage *account2storage2(AccountId account_id)
{
    return storage_db.search(account_id);
}

static
void storage_delete(AccountId account_id)
{
    storage_db.erase(account_id);
}

/*==========================================
 * カプラ倉庫を開く
 *------------------------------------------
 */
int storage_storageopen(dumb_ptr<map_session_data> sd)
{
    nullpo_ret(sd);

    if (sd->state.storage_open)
        return 1;               //Already open?

    Storage *stor = storage_db.search(sd->status_key.account_id);
    if (stor == NULL)
    {                           //Request storage.
        intif_request_storage(sd->status_key.account_id);
        return 1;
    }

    if (stor->storage_status)
        return 1;               //Already open/player already has it open...

    stor->storage_status = 1;
    sd->state.storage_open = 1;
    clif_storageitemlist(sd, stor);
    clif_storageequiplist(sd, stor);
    clif_updatestorageamount(sd, stor);
    return 0;
}

/*==========================================
 * Internal add-item function.
 *------------------------------------------
 */
static
int storage_additem(dumb_ptr<map_session_data> sd, Storage *stor,
                            struct item *item_data, int amount)
{
    struct item_data *data;
    int i;

    if (!item_data->nameid || amount <= 0)
        return 1;

    data = itemdb_search(item_data->nameid);

    if (!itemdb_isequip2(data))
    {                           //Stackable
        for (i = 0; i < MAX_STORAGE; i++)
        {
            if (compare_item(&stor->storage_[i], item_data))
            {
                if (amount > MAX_AMOUNT - stor->storage_[i].amount)
                    return 1;
                stor->storage_[i].amount += amount;
                clif_storageitemadded(sd, stor, i, amount);
                stor->dirty = 1;
                return 0;
            }
        }
    }
    //Add item
    for (i = 0; i < MAX_STORAGE && stor->storage_[i].nameid; i++);

    if (i >= MAX_STORAGE)
        return 1;

    stor->storage_[i] = *item_data;
    stor->storage_[i].amount = amount;
    stor->storage_amount++;
    clif_storageitemadded(sd, stor, i, amount);
    clif_updatestorageamount(sd, stor);
    stor->dirty = 1;
    return 0;
}

/*==========================================
 * Internal del-item function
 *------------------------------------------
 */
static
int storage_delitem(dumb_ptr<map_session_data> sd, Storage *stor,
                            int n, int amount)
{

    if (!stor->storage_[n].nameid || stor->storage_[n].amount < amount)
        return 1;

    stor->storage_[n].amount -= amount;
    if (stor->storage_[n].amount == 0)
    {
        stor->storage_[n] = item{};
        stor->storage_amount--;
        clif_updatestorageamount(sd, stor);
    }
    clif_storageitemremoved(sd, n, amount);

    stor->dirty = 1;
    return 0;
}

/*==========================================
 * Add an item to the storage from the inventory.
 *------------------------------------------
 */
int storage_storageadd(dumb_ptr<map_session_data> sd, int index, int amount)
{
    Storage *stor;

    nullpo_ret(sd);
    stor = account2storage2(sd->status_key.account_id);
    nullpo_ret(stor);

    if ((stor->storage_amount > MAX_STORAGE) || !stor->storage_status)
        return 0;               // storage full / storage closed

    if (index < 0 || index >= MAX_INVENTORY)
        return 0;

    if (!sd->status.inventory[index].nameid)
        return 0;               //No item on that spot

    if (amount < 1 || amount > sd->status.inventory[index].amount)
        return 0;

//  log_tostorage(sd, index, 0);
    if (storage_additem(sd, stor, &sd->status.inventory[index], amount) == 0)
    {
        // remove item from inventory
        pc_unequipinvyitem(sd, index, CalcStatus::NOW);
        pc_delitem(sd, index, amount, 0);
    }

    return 1;
}

/*==========================================
 * Retrieve an item from the storage.
 *------------------------------------------
 */
int storage_storageget(dumb_ptr<map_session_data> sd, int index, int amount)
{
    Storage *stor;
    PickupFail flag;

    nullpo_ret(sd);
    stor = account2storage2(sd->status_key.account_id);
    nullpo_ret(stor);

    if (index < 0 || index >= MAX_STORAGE)
        return 0;

    if (!stor->storage_[index].nameid)
        return 0;               //Nothing there

    if (amount < 1 || amount > stor->storage_[index].amount)
        return 0;

    if ((flag = pc_additem(sd, &stor->storage_[index], amount)) == PickupFail::OKAY)
        storage_delitem(sd, stor, index, amount);
    else
        clif_additem(sd, 0, 0, flag);
//  log_fromstorage(sd, index, 0);
    return 1;
}

/*==========================================
 * Modified By Valaris to save upon closing [massdriller]
 *------------------------------------------
 */
int storage_storageclose(dumb_ptr<map_session_data> sd)
{
    Storage *stor;

    nullpo_ret(sd);
    stor = account2storage2(sd->status_key.account_id);
    nullpo_ret(stor);

    clif_storageclose(sd);
    if (stor->storage_status)
    {
        if (save_settings & 4)
            chrif_save(sd);    //Invokes the storage saving as well.
        else
            storage_storage_save(sd->status_key.account_id, 0);
    }
    stor->storage_status = 0;
    sd->state.storage_open = 0;

    if (sd->npc_flags.storage)
    {
        sd->npc_flags.storage = 0;
        map_scriptcont(sd, sd->npc_id);
    }

    return 0;
}

/*==========================================
 * When quitting the game.
 *------------------------------------------
 */
int storage_storage_quit(dumb_ptr<map_session_data> sd)
{
    Storage *stor;

    nullpo_ret(sd);

    stor = account2storage2(sd->status_key.account_id);
    if (stor)
    {
        chrif_save(sd);        //Invokes the storage saving as well.
        stor->storage_status = 0;
        sd->state.storage_open = 0;
    }

    return 0;
}

int storage_storage_save(AccountId account_id, int final)
{
    Storage *stor;

    stor = account2storage2(account_id);
    if (!stor)
        return 0;

    if (stor->dirty)
    {
        if (final)
        {
            stor->dirty = 2;
            stor->storage_status = 0;   //To prevent further manipulation of it.
        }
        intif_send_storage(stor);
        return 1;
    }
    if (final)
    {                           //Clear storage from memory. Nothing to save.
        storage_delete(account_id);
        return 1;
    }

    return 0;
}

//Ack from Char-server indicating the storage was saved. [Skotlex]
int storage_storage_saved(AccountId account_id)
{
    Storage *stor = account2storage2(account_id);

    if (stor)
    {
        //Only mark it clean if it's not in use. [Skotlex]
        if (stor->dirty && stor->storage_status == 0)
        {
            stor->dirty = 0;
            // sortage_sortitem(stor);
        }
        return 1;
    }
    return 0;
}