Initial release 'premium' storage
* Adapting official multiple storages. * Added config to defines storages. See conf/import-tmpl/inter_server.conf. * Added packet IZ `0x388c` for sending storage definitions. * Added script command `openstorage2` to open premium storages. * Removed `sd->storage_size`, replaced by `sd->storage.max_amount`. The value is defined in inter_server.conf in storage entries. Signed-off-by: Cydh Ramdh <cydh@pservero.com>
This commit is contained in:
parent
a0caaa1036
commit
46b1de7d50
0
conf/import-tmpl/inter_server.conf
Normal file
0
conf/import-tmpl/inter_server.conf
Normal file
@ -93,7 +93,6 @@ scdata_db: sc_data
|
||||
cart_db: cart_inventory
|
||||
inventory_db: inventory
|
||||
charlog_db: charlog
|
||||
storage_db: storage
|
||||
skill_db: skill
|
||||
interlog_db: interlog
|
||||
memo_db: memo
|
||||
@ -150,4 +149,6 @@ db_roulette_table: db_roulette
|
||||
// Use SQL item_db, mob_db and mob_skill_db for the map server? (yes/no)
|
||||
use_sql_db: no
|
||||
|
||||
inter_server_conf: conf/inter_server.conf
|
||||
|
||||
import: conf/import/inter_conf.txt
|
||||
|
25
conf/inter_server.conf
Normal file
25
conf/inter_server.conf
Normal file
@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Config for storages
|
||||
*
|
||||
* To access premium storage, use 'openstorage2' script command (except for the default storage).
|
||||
* If premium storages are added, just copy the structure of storage table then match the table name in this config.
|
||||
* The 'max' of premium storages are not adjusted by 'vip_storage_increase' config nor MIN_STORAGE.
|
||||
*
|
||||
* Structure:
|
||||
{
|
||||
id: <storage_id> // (int) Storage ID will be used for 'openstorage2' script command.
|
||||
name: "<storage name>" // (string) Storage name will be sent to the client when player open the storage.
|
||||
table: "<storage_table>" // (string) Name of table where storage is saved, the table stucture is same like default storage name
|
||||
max: <max_amount> // (int) *optional* Maximum number of storage, MAX_STORAGE will be used if no value defined
|
||||
}, // Use comma to add more storages
|
||||
**/
|
||||
storages: (
|
||||
{
|
||||
// Default storage
|
||||
// DO NOT CHANGE THIS EXCEPT YOU KNOW WHAT YOU ARE DOING
|
||||
id: 0
|
||||
name: "Storage"
|
||||
table: "storage"
|
||||
//max: 600
|
||||
}
|
||||
)
|
@ -2194,6 +2194,18 @@ Currently the max packet size is 0xFFFF (see 'WFIFOSET()' in 'src/common/socket.
|
||||
desc:
|
||||
- Info about inventory/cart/storage data is saved
|
||||
|
||||
0x388c
|
||||
Type: IZ
|
||||
Structure: <cmd>.W <len>.W { <storage_table>.? }*?
|
||||
index: 0,2,6,...
|
||||
len: 6+variable
|
||||
parameter:
|
||||
- cmd : packet identification (0x388c)
|
||||
- len : Pakcet length
|
||||
- storage_table : Storage table information
|
||||
desc:
|
||||
- Receive storage information
|
||||
|
||||
0x3890
|
||||
Type: IZ
|
||||
Structure: <cmd>.W <size>.W <account_id>.L <flag>.B <s_homunculus>.?B
|
||||
|
@ -5053,6 +5053,33 @@ window, to avoid any disruption when both windows overlap.
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*openstorage2 <storage_id>,<mode>{,<account_id>};
|
||||
|
||||
Just like 'openstorage' command, except this command can open additional storage
|
||||
by specified 'storage_id'. For storage_id, please read the conf/inter_server.conf
|
||||
for storages groups.
|
||||
|
||||
Values for 'mode' are:
|
||||
STOR_MODE_NONE : Player only can read the storage entries.
|
||||
STOR_MODE_GET : Player can get items from the storage.
|
||||
STOR_MODE_PUT : Player can put items to the storage.
|
||||
|
||||
Example:
|
||||
if (vip_status(1)) {
|
||||
mes "I will open your Premium storage.";
|
||||
mes "Thank you for using our service.";
|
||||
close2;
|
||||
openstorage2 1,STOR_MODE_GET|STOR_MODE_PUT;
|
||||
} else {
|
||||
mes "Sorry, your Premium status is expired.";
|
||||
mes "Storage will be opened but you can't put any item into it.";
|
||||
close2;
|
||||
openstorage2 1,STOR_MODE_GET;
|
||||
}
|
||||
end;
|
||||
|
||||
---------------------------------------
|
||||
|
||||
*openmail({<char_id>});
|
||||
|
||||
This will open a character's Mail window on the client connected to the
|
||||
|
38
sql-files/upgrades/premium_storage.sql
Normal file
38
sql-files/upgrades/premium_storage.sql
Normal file
@ -0,0 +1,38 @@
|
||||
--
|
||||
-- Table structure for table `storage_1`
|
||||
--
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `storage_1` (
|
||||
`id` int(11) unsigned NOT NULL auto_increment,
|
||||
`account_id` int(11) unsigned NOT NULL default '0',
|
||||
`nameid` smallint(5) unsigned NOT NULL default '0',
|
||||
`amount` smallint(11) unsigned NOT NULL default '0',
|
||||
`equip` int(11) unsigned NOT NULL default '0',
|
||||
`identify` smallint(6) unsigned NOT NULL default '0',
|
||||
`refine` tinyint(3) unsigned NOT NULL default '0',
|
||||
`attribute` tinyint(4) unsigned NOT NULL default '0',
|
||||
`card0` smallint(5) unsigned NOT NULL default '0',
|
||||
`card1` smallint(5) unsigned NOT NULL default '0',
|
||||
`card2` smallint(5) unsigned NOT NULL default '0',
|
||||
`card3` smallint(5) unsigned NOT NULL default '0',
|
||||
`option_id0` smallint(5) unsigned NOT NULL default '0',
|
||||
`option_val0` smallint(5) unsigned NOT NULL default '0',
|
||||
`option_parm0` tinyint(3) unsigned NOT NULL default '0',
|
||||
`option_id1` smallint(5) unsigned NOT NULL default '0',
|
||||
`option_val1` smallint(5) unsigned NOT NULL default '0',
|
||||
`option_parm1` tinyint(3) unsigned NOT NULL default '0',
|
||||
`option_id2` smallint(5) unsigned NOT NULL default '0',
|
||||
`option_val2` smallint(5) unsigned NOT NULL default '0',
|
||||
`option_parm2` tinyint(3) unsigned NOT NULL default '0',
|
||||
`option_id3` smallint(5) unsigned NOT NULL default '0',
|
||||
`option_val3` smallint(5) unsigned NOT NULL default '0',
|
||||
`option_parm3` tinyint(3) unsigned NOT NULL default '0',
|
||||
`option_id4` smallint(5) unsigned NOT NULL default '0',
|
||||
`option_val4` smallint(5) unsigned NOT NULL default '0',
|
||||
`option_parm4` tinyint(3) unsigned NOT NULL default '0',
|
||||
`expire_time` int(11) unsigned NOT NULL default '0',
|
||||
`bound` tinyint(3) unsigned NOT NULL default '0',
|
||||
`unique_id` bigint(20) unsigned NOT NULL default '0',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `account_id` (`account_id`)
|
||||
) ENGINE=MyISAM;
|
@ -23,6 +23,7 @@
|
||||
#include "int_mercenary.h"
|
||||
#include "int_elemental.h"
|
||||
#include "int_party.h"
|
||||
#include "int_storage.h"
|
||||
#include "inter.h"
|
||||
#include "char_logif.h"
|
||||
#include "char_mapif.h"
|
||||
@ -515,7 +516,7 @@ int char_mmo_char_tosql(uint32 char_id, struct mmo_charstatus* p){
|
||||
}
|
||||
|
||||
/// Saves an array of 'item' entries into the specified table.
|
||||
int char_memitemdata_to_sql(const struct item items[], int max, int id, enum storage_type tableswitch) {
|
||||
int char_memitemdata_to_sql(const struct item items[], int max, int id, enum storage_type tableswitch, uint8 stor_id) {
|
||||
StringBuf buf;
|
||||
SqlStmt* stmt;
|
||||
int i, j, offset = 0, errors = 0;
|
||||
@ -537,7 +538,7 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, enum sto
|
||||
break;
|
||||
case TABLE_STORAGE:
|
||||
printname = "Storage";
|
||||
tablename = schema_config.storage_db;
|
||||
tablename = inter_premiumStorage_getTableName(stor_id);
|
||||
selectoption = "account_id";
|
||||
break;
|
||||
case TABLE_GUILD_STORAGE:
|
||||
@ -720,15 +721,14 @@ int char_memitemdata_to_sql(const struct item items[], int max, int id, enum sto
|
||||
errors++;
|
||||
}
|
||||
|
||||
ShowInfo("Saved %s data for %s: %d\n", printname, selectoption, id);
|
||||
|
||||
ShowInfo("Saved %s (%d) data to table %s for %s: %d\n", printname, stor_id, tablename, selectoption, id);
|
||||
StringBuf_Destroy(&buf);
|
||||
aFree(flag);
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
bool char_memitemdata_from_sql( struct s_storage* p, int max, int id, enum storage_type tableswitch ){
|
||||
bool char_memitemdata_from_sql(struct s_storage* p, int max, int id, enum storage_type tableswitch, uint8 stor_id) {
|
||||
StringBuf buf;
|
||||
SqlStmt* stmt;
|
||||
int i,j, offset = 0;
|
||||
@ -750,7 +750,7 @@ bool char_memitemdata_from_sql( struct s_storage* p, int max, int id, enum stora
|
||||
break;
|
||||
case TABLE_STORAGE:
|
||||
printname = "Storage";
|
||||
tablename = schema_config.storage_db;
|
||||
tablename = inter_premiumStorage_getTableName(stor_id);
|
||||
selectoption = "account_id";
|
||||
storage = p->u.items_storage;
|
||||
break;
|
||||
@ -768,6 +768,8 @@ bool char_memitemdata_from_sql( struct s_storage* p, int max, int id, enum stora
|
||||
memset(p, 0, sizeof(struct s_storage)); //clean up memory
|
||||
p->id = id;
|
||||
p->type = tableswitch;
|
||||
p->stor_id = stor_id;
|
||||
p->max_amount = inter_premiumStorage_getMax(p->stor_id);
|
||||
|
||||
stmt = SqlStmt_Malloc(sql_handle);
|
||||
if (stmt == NULL) {
|
||||
@ -824,7 +826,7 @@ bool char_memitemdata_from_sql( struct s_storage* p, int max, int id, enum stora
|
||||
memcpy(&storage[i], &item, sizeof(item));
|
||||
|
||||
p->amount = i;
|
||||
ShowInfo("Loaded %s data from DB for %s: %d (total: %d)\n", printname, selectoption, id, p->amount);
|
||||
ShowInfo("Loaded %s (%d) data from table %s for %s: %d (total: %d)\n", printname, p->stor_id, tablename, selectoption, id, p->amount);
|
||||
|
||||
SqlStmt_FreeResult(stmt);
|
||||
SqlStmt_Free(stmt);
|
||||
@ -2181,7 +2183,7 @@ bool char_checkdb(void){
|
||||
int i;
|
||||
const char* sqltable[] = {
|
||||
schema_config.char_db, schema_config.hotkey_db, schema_config.scdata_db, schema_config.cart_db,
|
||||
schema_config.inventory_db, schema_config.charlog_db, schema_config.storage_db,
|
||||
schema_config.inventory_db, schema_config.charlog_db,
|
||||
schema_config.char_reg_str_table, schema_config.char_reg_num_table, schema_config.acc_reg_str_table,
|
||||
schema_config.acc_reg_num_table, schema_config.skill_db, schema_config.interlog_db, schema_config.memo_db,
|
||||
schema_config.guild_db, schema_config.guild_alliance_db, schema_config.guild_castle_db,
|
||||
@ -2404,13 +2406,6 @@ bool char_checkdb(void){
|
||||
Sql_ShowDebug(sql_handle);
|
||||
return false;
|
||||
}
|
||||
//checking storage_db
|
||||
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `id`,`account_id`,`nameid`,`amount`,`equip`,`identify`,`refine`,"
|
||||
"`attribute`,`card0`,`card1`,`card2`,`card3`,`option_id0`,`option_val0`,`option_parm0`,`option_id1`,`option_val1`,`option_parm1`,`option_id2`,`option_val2`,`option_parm2`,`option_id3`,`option_val3`,`option_parm3`,`option_id4`,`option_val4`,`option_parm4`,`expire_time`,`bound`,`unique_id`"
|
||||
" FROM `%s` LIMIT 1;", schema_config.storage_db) ){
|
||||
Sql_ShowDebug(sql_handle);
|
||||
return false;
|
||||
}
|
||||
//checking guild_storage_db
|
||||
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `id`,`guild_id`,`nameid`,`amount`,`equip`,`identify`,`refine`,"
|
||||
"`attribute`,`card0`,`card1`,`card2`,`card3`,`option_id0`,`option_val0`,`option_parm0`,`option_id1`,`option_val1`,`option_parm1`,`option_id2`,`option_val2`,`option_parm2`,`option_id3`,`option_val3`,`option_parm3`,`option_id4`,`option_val4`,`option_parm4`,`expire_time`,`bound`,`unique_id`"
|
||||
@ -2449,8 +2444,6 @@ void char_sql_config_read(const char* cfgName) {
|
||||
safestrncpy(schema_config.inventory_db, w2, sizeof(schema_config.inventory_db));
|
||||
else if(!strcmpi(w1,"charlog_db"))
|
||||
safestrncpy(schema_config.charlog_db, w2, sizeof(schema_config.charlog_db));
|
||||
else if(!strcmpi(w1,"storage_db"))
|
||||
safestrncpy(schema_config.storage_db, w2, sizeof(schema_config.storage_db));
|
||||
else if(!strcmpi(w1,"skill_db"))
|
||||
safestrncpy(schema_config.skill_db, w2, sizeof(schema_config.skill_db));
|
||||
else if(!strcmpi(w1,"interlog_db"))
|
||||
|
@ -4,8 +4,6 @@
|
||||
#ifndef _CHAR_SQL_H_
|
||||
#define _CHAR_SQL_H_
|
||||
|
||||
#define DB_NAME_LEN 256 //max len of dbs
|
||||
|
||||
#include "../config/core.h"
|
||||
#include "../common/core.h" // CORE_ST_LAST
|
||||
#include "../common/msg_conf.h"
|
||||
@ -264,8 +262,8 @@ int char_mmo_chars_fromsql(struct char_session_data* sd, uint8* buf);
|
||||
int char_delete_char_sql(uint32 char_id);
|
||||
int char_rename_char_sql(struct char_session_data *sd, uint32 char_id);
|
||||
int char_divorce_char_sql(int partner_id1, int partner_id2);
|
||||
int char_memitemdata_to_sql(const struct item items[], int max, int id, enum storage_type tableswitch);
|
||||
bool char_memitemdata_from_sql( struct s_storage* p, int max, int id, enum storage_type tableswitch );
|
||||
int char_memitemdata_to_sql(const struct item items[], int max, int id, enum storage_type tableswitch, uint8 stor_id);
|
||||
bool char_memitemdata_from_sql(struct s_storage* p, int max, int id, enum storage_type tableswitch, uint8 stor_id);
|
||||
|
||||
void disconnect_player(uint32 account_id);
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
// Copyright (c) Athena Dev Teams - Licensed under GNU GPL
|
||||
// For more information, see LICENCE in the main folder
|
||||
|
||||
#include "../common/malloc.h"
|
||||
#include "../common/mmo.h"
|
||||
#include "../common/showmsg.h"
|
||||
#include "../common/socket.h"
|
||||
@ -14,6 +15,54 @@
|
||||
|
||||
#define STORAGE_MEMINC 16
|
||||
|
||||
/**
|
||||
* Check if sotrage ID is valid
|
||||
* @param id Storage ID
|
||||
* @return True:Valid, False:Invalid
|
||||
**/
|
||||
bool inter_premiumStorage_exists(uint8 id) {
|
||||
if (interserv_config.storages && interserv_config.storage_count) {
|
||||
int i;
|
||||
for (i = 0; i < interserv_config.storage_count; i++) {
|
||||
if (interserv_config.storages[i].id == id)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get max storage amount
|
||||
* @param id Storage ID
|
||||
* @return Max amount
|
||||
**/
|
||||
int inter_premiumStorage_getMax(uint8 id) {
|
||||
if (interserv_config.storages && interserv_config.storage_count) {
|
||||
int i;
|
||||
for (i = 0; i < interserv_config.storage_count; i++) {
|
||||
if (&interserv_config.storages[i] && interserv_config.storages[i].id == id)
|
||||
return interserv_config.storages[i].max_num;
|
||||
}
|
||||
}
|
||||
return MAX_STORAGE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get table name of storage
|
||||
* @param id Storage ID
|
||||
* @return Table name
|
||||
**/
|
||||
const char *inter_premiumStorage_getTableName(uint8 id) {
|
||||
if (interserv_config.storages && interserv_config.storage_count) {
|
||||
int i;
|
||||
for (i = 0; i < interserv_config.storage_count; i++) {
|
||||
if (&interserv_config.storages[i] && interserv_config.storages[i].id == id)
|
||||
return interserv_config.storages[i].table;
|
||||
}
|
||||
}
|
||||
return schema_config.storage_db;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save inventory entries to SQL
|
||||
* @param char_id: Character ID to save
|
||||
@ -22,7 +71,7 @@
|
||||
*/
|
||||
static int inventory_tosql(uint32 char_id, struct s_storage* p)
|
||||
{
|
||||
return char_memitemdata_to_sql(p->u.items_inventory, MAX_INVENTORY, char_id, TABLE_INVENTORY);
|
||||
return char_memitemdata_to_sql(p->u.items_inventory, MAX_INVENTORY, char_id, TABLE_INVENTORY, p->stor_id);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -33,7 +82,7 @@ static int inventory_tosql(uint32 char_id, struct s_storage* p)
|
||||
*/
|
||||
static int storage_tosql(uint32 account_id, struct s_storage* p)
|
||||
{
|
||||
return char_memitemdata_to_sql(p->u.items_storage, MAX_STORAGE, account_id, TABLE_STORAGE);
|
||||
return char_memitemdata_to_sql(p->u.items_storage, MAX_STORAGE, account_id, TABLE_STORAGE, p->stor_id);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -44,7 +93,7 @@ static int storage_tosql(uint32 account_id, struct s_storage* p)
|
||||
*/
|
||||
static int cart_tosql(uint32 char_id, struct s_storage* p)
|
||||
{
|
||||
return char_memitemdata_to_sql(p->u.items_cart, MAX_CART, char_id, TABLE_CART);
|
||||
return char_memitemdata_to_sql(p->u.items_cart, MAX_CART, char_id, TABLE_CART, p->stor_id);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -55,7 +104,7 @@ static int cart_tosql(uint32 char_id, struct s_storage* p)
|
||||
*/
|
||||
static bool inventory_fromsql(uint32 char_id, struct s_storage* p)
|
||||
{
|
||||
return char_memitemdata_from_sql( p, MAX_INVENTORY, char_id, TABLE_INVENTORY );
|
||||
return char_memitemdata_from_sql( p, MAX_INVENTORY, char_id, TABLE_INVENTORY, p->stor_id );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -66,18 +115,19 @@ static bool inventory_fromsql(uint32 char_id, struct s_storage* p)
|
||||
*/
|
||||
static bool cart_fromsql(uint32 char_id, struct s_storage* p)
|
||||
{
|
||||
return char_memitemdata_from_sql( p, MAX_CART, char_id, TABLE_CART );
|
||||
return char_memitemdata_from_sql( p, MAX_CART, char_id, TABLE_CART, p->stor_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch storage entries from table
|
||||
* @param char_id: Character ID to fetch
|
||||
* @param p: Storage list to save the entries
|
||||
* @param stor_id: Storage ID
|
||||
* @return True if success, False if failed
|
||||
*/
|
||||
static bool storage_fromsql(uint32 account_id, struct s_storage* p)
|
||||
{
|
||||
return char_memitemdata_from_sql( p, MAX_STORAGE, account_id, TABLE_STORAGE );
|
||||
return char_memitemdata_from_sql( p, MAX_STORAGE, account_id, TABLE_STORAGE, p->stor_id );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -89,7 +139,7 @@ static bool storage_fromsql(uint32 account_id, struct s_storage* p)
|
||||
bool guild_storage_tosql(int guild_id, struct s_storage* p)
|
||||
{
|
||||
//ShowInfo("Guild Storage has been saved (GID: %d)\n", guild_id);
|
||||
return char_memitemdata_to_sql(p->u.items_guild, MAX_GUILD_STORAGE, guild_id, TABLE_GUILD_STORAGE);
|
||||
return char_memitemdata_to_sql(p->u.items_guild, MAX_GUILD_STORAGE, guild_id, TABLE_GUILD_STORAGE, p->stor_id);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -100,13 +150,31 @@ bool guild_storage_tosql(int guild_id, struct s_storage* p)
|
||||
*/
|
||||
bool guild_storage_fromsql(int guild_id, struct s_storage* p)
|
||||
{
|
||||
return char_memitemdata_from_sql( p, MAX_GUILD_STORAGE, guild_id, TABLE_GUILD_STORAGE );
|
||||
return char_memitemdata_from_sql( p, MAX_GUILD_STORAGE, guild_id, TABLE_GUILD_STORAGE, p->stor_id );
|
||||
}
|
||||
|
||||
static void inter_storage_checkDB(void) {
|
||||
int i = 0;
|
||||
// Checking storage tables
|
||||
for (i = 0; i < interserv_config.storage_count; i++) {
|
||||
if (!&interserv_config.storages[i] || !interserv_config.storages[i].name || !interserv_config.storages[i].table || interserv_config.storages[i].table == '\0')
|
||||
continue;
|
||||
if (SQL_ERROR == Sql_Query(sql_handle, "SELECT `id`,`account_id`,`nameid`,`amount`,`equip`,`identify`,`refine`,"
|
||||
"`attribute`,`card0`,`card1`,`card2`,`card3`,`option_id0`,`option_val0`,`option_parm0`,`option_id1`,`option_val1`,`option_parm1`,"
|
||||
"`option_id2`,`option_val2`,`option_parm2`,`option_id3`,`option_val3`,`option_parm3`,`option_id4`,`option_val4`,`option_parm4`,"
|
||||
"`expire_time`,`bound`,`unique_id`"
|
||||
" FROM `%s` LIMIT 1;", interserv_config.storages[i].table) ){
|
||||
Sql_ShowDebug(sql_handle);
|
||||
}
|
||||
}
|
||||
Sql_FreeResult(sql_handle);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// storage data initialize
|
||||
void inter_storage_sql_init(void)
|
||||
{
|
||||
inter_storage_checkDB();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -423,41 +491,56 @@ static void mapif_storage_data_loaded(int fd, uint32 account_id, char type, stru
|
||||
* @param char_id
|
||||
* @param success
|
||||
* @param type
|
||||
* @param stor_id
|
||||
*/
|
||||
void mapif_storage_saved(int fd, uint32 account_id, uint32 char_id, bool success, char type) {
|
||||
WFIFOHEAD(fd,8);
|
||||
void mapif_storage_saved(int fd, uint32 account_id, uint32 char_id, bool success, char type, uint8 stor_id) {
|
||||
WFIFOHEAD(fd,9);
|
||||
WFIFOW(fd, 0) = 0x388b;
|
||||
WFIFOL(fd, 2) = account_id;
|
||||
WFIFOB(fd, 6) = success;
|
||||
WFIFOB(fd, 7) = type;
|
||||
WFIFOSET(fd,8);
|
||||
WFIFOB(fd, 8) = stor_id;
|
||||
WFIFOSET(fd,9);
|
||||
}
|
||||
|
||||
/**
|
||||
* Requested inventory/cart/storage data for a player
|
||||
* ZI 0x308a <type>.B <account_id>.L <char_id>.L
|
||||
* ZI 0x308a <type>.B <account_id>.L <char_id>.L <storage_id>.B <mode>.B
|
||||
* @param fd
|
||||
*/
|
||||
bool mapif_parse_StorageLoad(int fd) {
|
||||
uint32 aid, cid;
|
||||
int type;
|
||||
uint8 stor_id, mode;
|
||||
struct s_storage stor;
|
||||
bool res = true;
|
||||
|
||||
RFIFOHEAD(fd);
|
||||
type = RFIFOB(fd,2);
|
||||
aid = RFIFOL(fd,3);
|
||||
cid = RFIFOL(fd,7);
|
||||
stor_id = RFIFOB(fd,11);
|
||||
|
||||
memset(&stor, 0, sizeof(struct s_storage));
|
||||
stor.stor_id = stor_id;
|
||||
|
||||
//ShowInfo("Loading storage for AID=%d.\n", aid);
|
||||
switch (type) {
|
||||
case TABLE_INVENTORY: res = inventory_fromsql(cid, &stor); break;
|
||||
case TABLE_STORAGE: res = storage_fromsql(aid, &stor); break;
|
||||
case TABLE_STORAGE:
|
||||
if (!inter_premiumStorage_exists(stor_id)) {
|
||||
ShowError("Invalid storage with id %d\n", stor_id);
|
||||
return false;
|
||||
}
|
||||
res = storage_fromsql(aid, &stor);
|
||||
break;
|
||||
case TABLE_CART: res = cart_fromsql(cid, &stor); break;
|
||||
default: return false;
|
||||
}
|
||||
|
||||
mode = RFIFOB(fd, 12);
|
||||
stor.state.put = (mode&STOR_MODE_PUT) ? 1 : 0;
|
||||
stor.state.get = (mode&STOR_MODE_GET) ? 1 : 0;
|
||||
|
||||
mapif_storage_data_loaded(fd, aid, type, stor, res);
|
||||
return true;
|
||||
}
|
||||
@ -482,11 +565,17 @@ bool mapif_parse_StorageSave(int fd) {
|
||||
//ShowInfo("Saving storage data for AID=%d.\n", aid);
|
||||
switch(type){
|
||||
case TABLE_INVENTORY: inventory_tosql(cid, &stor); break;
|
||||
case TABLE_STORAGE: storage_tosql(aid, &stor); break;
|
||||
case TABLE_CART: cart_tosql(cid, &stor); break;
|
||||
case TABLE_STORAGE:
|
||||
if (!inter_premiumStorage_exists(stor.stor_id)) {
|
||||
ShowError("Invalid storage with id %d\n", stor.stor_id);
|
||||
return false;
|
||||
}
|
||||
storage_tosql(aid, &stor);
|
||||
break;
|
||||
case TABLE_CART: cart_tosql(cid, &stor); break;
|
||||
default: return false;
|
||||
}
|
||||
mapif_storage_saved(fd, aid, cid, true, type);
|
||||
mapif_storage_saved(fd, aid, cid, true, type, stor.stor_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,10 @@ void inter_storage_sql_final(void);
|
||||
void inter_storage_delete(uint32 account_id);
|
||||
void inter_guild_storage_delete(int guild_id);
|
||||
|
||||
bool inter_premiumStorage_exists(uint8 id);
|
||||
int inter_premiumStorage_getMax(uint8 id);
|
||||
const char *inter_premiumStorage_getTableName(uint8 id);
|
||||
|
||||
bool inter_storage_parse_frommap(int fd);
|
||||
|
||||
bool guild_storage_tosql(int guild_id, struct s_storage *p);
|
||||
|
103
src/char/inter.c
103
src/char/inter.c
@ -39,7 +39,7 @@ char char_server_id[32] = "ragnarok";
|
||||
char char_server_pw[32] = ""; // Allow user to send empty password (bugreport:7787)
|
||||
char char_server_db[32] = "ragnarok";
|
||||
char default_codepage[32] = ""; //Feature by irmin.
|
||||
|
||||
struct Inter_Config interserv_config;
|
||||
unsigned int party_share_level = 10;
|
||||
|
||||
/// Received packet Lengths from map-server
|
||||
@ -52,7 +52,7 @@ int inter_recv_packet_length[] = {
|
||||
-1,-1,10,10, 0,-1,12, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3050- Auction System [Zephyrus]
|
||||
6,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3060- Quest system [Kevin] [Inkfish]
|
||||
-1,10, 6,-1, 0, 0, 0, 0, 0, 0, 0, 0, -1,10, 6,-1, // 3070- Mercenary packets [Zephyrus], Elemental packets [pakpil]
|
||||
48,14,-1, 6, 0, 0, 0, 0, 0, 0,11,-1, 0, 0, 0, 0, // 3080- Pet System, Storage
|
||||
48,14,-1, 6, 0, 0, 0, 0, 0, 0,13,-1, 0, 0, 0, 0, // 3080- Pet System, Storage
|
||||
-1,10,-1, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3090- Homunculus packets [albator]
|
||||
};
|
||||
|
||||
@ -773,6 +773,8 @@ static int inter_config_read(const char* cfgName)
|
||||
party_share_level = (unsigned int)atof(w2);
|
||||
else if(!strcmpi(w1,"log_inter"))
|
||||
charserv_config.log_inter = atoi(w2);
|
||||
else if(!strcmpi(w1,"inter_server_conf"))
|
||||
strcpy(interserv_config.cfgFile, w2);
|
||||
else if(!strcmpi(w1,"import"))
|
||||
inter_config_read(w2);
|
||||
}
|
||||
@ -801,11 +803,86 @@ int inter_log(char* fmt, ...)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read inter config file
|
||||
**/
|
||||
static void inter_config_readConf(void) {
|
||||
int count = 0;
|
||||
config_setting_t *config = NULL;
|
||||
|
||||
if (conf_read_file(&interserv_config.cfg, interserv_config.cfgFile))
|
||||
return;
|
||||
|
||||
// Read storages
|
||||
config = config_lookup(&interserv_config.cfg, "storages");
|
||||
if (config && (count = config_setting_length(config))) {
|
||||
int i;
|
||||
for (i = 0; i < count; i++) {
|
||||
int id, max_num;
|
||||
const char *name, *tablename;
|
||||
struct s_storage_table table;
|
||||
config_setting_t *entry = config_setting_get_elem(config, i);
|
||||
|
||||
if (!config_setting_lookup_int(entry, "id", &id)) {
|
||||
ShowConfigWarning(entry, "inter_config_readConf: Cannot find storage \"id\" in member %d", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!config_setting_lookup_string(entry, "name", &name)) {
|
||||
ShowConfigWarning(entry, "inter_config_readConf: Cannot find storage \"name\" in member %d", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!config_setting_lookup_string(entry, "table", &tablename)) {
|
||||
ShowConfigWarning(entry, "inter_config_readConf: Cannot find storage \"table\" in member %d", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!config_setting_lookup_int(entry, "max", &max_num))
|
||||
max_num = MAX_STORAGE;
|
||||
else if (max_num > MAX_STORAGE) {
|
||||
ShowConfigWarning(entry, "Storage \"%s\" has \"max\" %d, max is MAX_STORAGE (%d)!\n", name, max_num, MAX_STORAGE);
|
||||
max_num = MAX_STORAGE;
|
||||
}
|
||||
|
||||
memset(&table, 0, sizeof(struct s_storage_table));
|
||||
|
||||
RECREATE(interserv_config.storages, struct s_storage_table, interserv_config.storage_count+1);
|
||||
interserv_config.storages[interserv_config.storage_count].id = id;
|
||||
safestrncpy(interserv_config.storages[interserv_config.storage_count].name, name, NAME_LENGTH);
|
||||
safestrncpy(interserv_config.storages[interserv_config.storage_count].table, tablename, DB_NAME_LEN);
|
||||
interserv_config.storages[interserv_config.storage_count].max_num = max_num;
|
||||
interserv_config.storage_count++;
|
||||
}
|
||||
}
|
||||
|
||||
ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' storage informations in '"CL_WHITE"%s"CL_RESET"'\n", interserv_config.storage_count, interserv_config.cfgFile);
|
||||
}
|
||||
|
||||
void inter_config_finalConf(void) {
|
||||
|
||||
if (interserv_config.storages)
|
||||
aFree(interserv_config.storages);
|
||||
interserv_config.storages = NULL;
|
||||
interserv_config.storage_count = 0;
|
||||
|
||||
config_destroy(&interserv_config.cfg);
|
||||
}
|
||||
|
||||
static void inter_config_defaults(void) {
|
||||
interserv_config.storage_count = 0;
|
||||
interserv_config.storages = NULL;
|
||||
|
||||
safestrncpy(interserv_config.cfgFile, "conf/inter_server.conf", sizeof(interserv_config.cfgFile));
|
||||
}
|
||||
|
||||
// initialize
|
||||
int inter_init_sql(const char *file)
|
||||
{
|
||||
//int i;
|
||||
|
||||
|
||||
inter_config_defaults();
|
||||
inter_config_read(file);
|
||||
|
||||
//DB connection initialized
|
||||
@ -826,6 +903,7 @@ int inter_init_sql(const char *file)
|
||||
}
|
||||
|
||||
wis_db = idb_alloc(DB_OPT_RELEASE_DATA);
|
||||
inter_config_readConf();
|
||||
inter_guild_sql_init();
|
||||
inter_storage_sql_init();
|
||||
inter_party_sql_init();
|
||||
@ -845,6 +923,7 @@ void inter_final(void)
|
||||
{
|
||||
wis_db->destroy(wis_db, NULL);
|
||||
|
||||
inter_config_finalConf();
|
||||
inter_guild_sql_final();
|
||||
inter_storage_sql_final();
|
||||
inter_party_sql_final();
|
||||
@ -860,8 +939,28 @@ void inter_final(void)
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* IZ 0x388c <len>.W { <storage_table>.? }*?
|
||||
* Sends storage information to map-server
|
||||
* @param fd
|
||||
**/
|
||||
void inter_Storage_sendInfo(int fd) {
|
||||
int size = sizeof(struct s_storage_table), len = 4 + interserv_config.storage_count * size, i = 0;
|
||||
// Send storage table information
|
||||
WFIFOHEAD(fd, len);
|
||||
WFIFOW(fd, 0) = 0x388c;
|
||||
WFIFOW(fd, 2) = len;
|
||||
for (i = 0; i < interserv_config.storage_count; i++) {
|
||||
if (!&interserv_config.storages[i] || !interserv_config.storages[i].name)
|
||||
continue;
|
||||
memcpy(WFIFOP(fd, 4 + size*i), &interserv_config.storages[i], size);
|
||||
}
|
||||
WFIFOSET(fd, len);
|
||||
}
|
||||
|
||||
int inter_mapif_init(int fd)
|
||||
{
|
||||
inter_Storage_sendInfo(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -4,8 +4,19 @@
|
||||
#ifndef _INTER_SQL_H_
|
||||
#define _INTER_SQL_H_
|
||||
|
||||
#include "../common/conf.h"
|
||||
#include "../common/mmo.h"
|
||||
#include "../common/sql.h"
|
||||
|
||||
struct Inter_Config {
|
||||
char cfgFile[128]; ///< Inter-Config file
|
||||
config_t cfg; ///< Config
|
||||
struct s_storage_table *storages; ///< Storage name & table information
|
||||
uint8 storage_count; ///< Number of available storage
|
||||
};
|
||||
|
||||
extern struct Inter_Config interserv_config;
|
||||
|
||||
int inter_init_sql(const char *file);
|
||||
void inter_final(void);
|
||||
int inter_parse_frommap(int fd);
|
||||
|
@ -79,6 +79,7 @@
|
||||
#define MAX_QUEST_DROPS 3 ///Max quest drops for a quest
|
||||
#define MAX_PC_BONUS_SCRIPT 50 ///Max bonus script can be fetched from `bonus_script` table on player load [Cydh]
|
||||
#define MAX_ITEM_RDM_OPT 5 /// Max item random option [Napster]
|
||||
#define DB_NAME_LEN 256 //max len of dbs
|
||||
|
||||
// for produce
|
||||
#define MIN_ATTRIBUTE 0
|
||||
@ -303,13 +304,26 @@ enum storage_type {
|
||||
TABLE_GUILD_STORAGE,
|
||||
};
|
||||
|
||||
enum e_storage_mode {
|
||||
STOR_MODE_NONE = 0x0,
|
||||
STOR_MODE_GET = 0x1,
|
||||
STOR_MODE_PUT = 0x2,
|
||||
STOR_MODE_ALL = 0x3,
|
||||
};
|
||||
|
||||
struct s_storage {
|
||||
bool dirty; ///< Dirty status, data needs to be saved
|
||||
bool status; ///< Current status of storage (opened or closed)
|
||||
int amount; ///< Amount of items in storage
|
||||
uint16 amount; ///< Amount of items in storage
|
||||
bool lock; ///< If locked, can't use storage when item bound retrieval
|
||||
uint32 id; ///< Account ID / Character ID / Guild ID (owner of storage)
|
||||
enum storage_type type; ///< Type of storage (inventory, cart, storage, guild storage)
|
||||
uint16 max_amount;
|
||||
uint8 stor_id; ///< Storage ID
|
||||
struct {
|
||||
unsigned get : 1;
|
||||
unsigned put : 1;
|
||||
} state;
|
||||
union { // Max for inventory, storage, cart, and guild storage are 1637 each without changing this struct and struct item [2014/10/27]
|
||||
struct item items_inventory[MAX_INVENTORY];
|
||||
struct item items_storage[MAX_STORAGE];
|
||||
@ -318,6 +332,13 @@ struct s_storage {
|
||||
} u;
|
||||
};
|
||||
|
||||
struct s_storage_table {
|
||||
char name[NAME_LENGTH];
|
||||
char table[DB_NAME_LEN];
|
||||
uint16 max_num;
|
||||
uint8 id;
|
||||
};
|
||||
|
||||
struct s_pet {
|
||||
uint32 account_id;
|
||||
uint32 char_id;
|
||||
|
@ -922,6 +922,11 @@ ACMD_FUNC(guildstorage)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sd->state.storage_flag == 3) {
|
||||
clif_displaymessage(fd, msg_txt(sd,250));
|
||||
return -1;
|
||||
}
|
||||
|
||||
storage_guild_storageopen(sd);
|
||||
clif_displaymessage(fd, msg_txt(sd,920)); // Guild storage opened.
|
||||
return 0;
|
||||
@ -5490,7 +5495,7 @@ ACMD_FUNC(storeall)
|
||||
if (sd->inventory.u.items_inventory[i].amount) {
|
||||
if(sd->inventory.u.items_inventory[i].equip != 0)
|
||||
pc_unequipitem(sd, i, 3);
|
||||
storage_storageadd(sd, i, sd->inventory.u.items_inventory[i].amount);
|
||||
storage_storageadd(sd, &sd->storage, i, sd->inventory.u.items_inventory[i].amount);
|
||||
}
|
||||
}
|
||||
storage_storageclose(sd);
|
||||
@ -5508,10 +5513,14 @@ ACMD_FUNC(clearstorage)
|
||||
clif_displaymessage(fd, msg_txt(sd,250));
|
||||
return -1;
|
||||
}
|
||||
if (sd->state.storage_flag == 3) {
|
||||
clif_displaymessage(fd, msg_txt(sd,250));
|
||||
return -1;
|
||||
}
|
||||
|
||||
j = sd->storage.amount;
|
||||
for (i = 0; i < j; ++i) {
|
||||
storage_delitem(sd, i, sd->storage.u.items_storage[i].amount);
|
||||
storage_delitem(sd, &sd->storage, i, sd->storage.u.items_storage[i].amount);
|
||||
}
|
||||
sd->state.storage_flag = 1;
|
||||
storage_storageclose(sd);
|
||||
@ -5544,6 +5553,11 @@ ACMD_FUNC(cleargstorage)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sd->state.storage_flag == 3) {
|
||||
clif_displaymessage(fd, msg_txt(sd,250));
|
||||
return -1;
|
||||
}
|
||||
|
||||
gstorage = guild2storage2(sd->status.guild_id);
|
||||
if (gstorage == NULL) { // Doesn't have opened @gstorage yet, so we skip the deletion since *shouldn't* have any item there.
|
||||
return -1;
|
||||
@ -8606,7 +8620,7 @@ ACMD_FUNC(itemlist)
|
||||
if( strcmp(parent_cmd, "storagelist") == 0 ) {
|
||||
location = "storage";
|
||||
items = sd->storage.u.items_storage;
|
||||
size = sd->storage_size;
|
||||
size = sd->storage.max_amount;
|
||||
} else if( strcmp(parent_cmd, "cartlist") == 0 ) {
|
||||
location = "cart";
|
||||
items = sd->cart.u.items_cart;
|
||||
|
@ -300,13 +300,15 @@ int chrif_save(struct map_session_data *sd, int flag) {
|
||||
chrif_bsdata_save(sd, (flag && (flag != 3)));
|
||||
|
||||
if (sd->state.storage_flag == 1)
|
||||
intif_storage_save(sd,TABLE_STORAGE);
|
||||
intif_storage_save(sd,TABLE_INVENTORY);
|
||||
intif_storage_save(sd,TABLE_CART);
|
||||
intif_storage_save(sd,&sd->storage);
|
||||
intif_storage_save(sd,&sd->inventory);
|
||||
intif_storage_save(sd,&sd->cart);
|
||||
|
||||
//For data sync
|
||||
if (sd->state.storage_flag == 2)
|
||||
storage_guild_storagesave(sd->status.account_id, sd->status.guild_id, flag);
|
||||
if (&sd->premiumStorage && sd->premiumStorage.dirty)
|
||||
intif_storage_save(sd, &sd->premiumStorage);
|
||||
|
||||
if (flag)
|
||||
sd->state.storage_flag = 0; //Force close it.
|
||||
@ -1602,10 +1604,10 @@ void chrif_parse_ack_vipActive(int fd) {
|
||||
sd->vip.enabled = 1;
|
||||
sd->vip.time = vip_time;
|
||||
// Increase storage size for VIP.
|
||||
sd->storage_size = battle_config.vip_storage_increase + MIN_STORAGE;
|
||||
if (sd->storage_size > MAX_STORAGE) {
|
||||
sd->storage.max_amount = battle_config.vip_storage_increase + MIN_STORAGE;
|
||||
if (sd->storage.max_amount > MAX_STORAGE) {
|
||||
ShowError("intif_parse_ack_vipActive: Storage size for player %s (%d:%d) is larger than MAX_STORAGE. Storage size has been set to MAX_STORAGE.\n", sd->status.name, sd->status.account_id, sd->status.char_id);
|
||||
sd->storage_size = MAX_STORAGE;
|
||||
sd->storage.max_amount = MAX_STORAGE;
|
||||
}
|
||||
// Magic Stone requirement avoidance for VIP.
|
||||
if (battle_config.vip_gemstone)
|
||||
@ -1613,7 +1615,7 @@ void chrif_parse_ack_vipActive(int fd) {
|
||||
} else if (sd->vip.enabled) {
|
||||
sd->vip.enabled = 0;
|
||||
sd->vip.time = 0;
|
||||
sd->storage_size = MIN_STORAGE;
|
||||
sd->storage.max_amount = MIN_STORAGE;
|
||||
sd->special_state.no_gemstone = 0;
|
||||
clif_displaymessage(sd->fd,msg_txt(sd,438));
|
||||
}
|
||||
@ -1998,6 +2000,12 @@ void do_init_chrif(void) {
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (sizeof(struct s_storage) > 0xFFFF){
|
||||
ShowError("s_storage size = %d is too big to be transmitted. (must be below 0xFFFF) \n",
|
||||
sizeof(struct s_storage));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if((sizeof(struct bonus_script_data) * MAX_PC_BONUS_SCRIPT) > 0xFFFF){
|
||||
ShowError("bonus_script_data size = %d is too big, please reduce MAX_PC_BONUS_SCRIPT (%d) size. (must be below 0xFFFF).\n",
|
||||
(sizeof(struct bonus_script_data) * MAX_PC_BONUS_SCRIPT), MAX_PC_BONUS_SCRIPT);
|
||||
|
@ -2813,7 +2813,7 @@ void clif_equiplist(struct map_session_data *sd)
|
||||
}
|
||||
}
|
||||
|
||||
void clif_storagelist(struct map_session_data* sd, struct item* items, int items_length)
|
||||
void clif_storagelist(struct map_session_data* sd, struct item* items, int items_length, const char *storename)
|
||||
{
|
||||
static const int client_buf = 0x5000; // Max buffer to send
|
||||
struct item_data *id;
|
||||
@ -2883,7 +2883,7 @@ void clif_storagelist(struct map_session_data* sd, struct item* items, int items
|
||||
WFIFOW(sd->fd,0)=cmd;
|
||||
WFIFOW(sd->fd,2)=sidx+nn*s;
|
||||
#if PACKETVER >= 20120925
|
||||
memset((char*)WFIFOP(sd->fd,4),0,24); //storename
|
||||
safestrncpy((char*)WFIFOP(sd->fd,4), storename, NAME_LENGTH); //storename
|
||||
#endif
|
||||
memcpy(WFIFOP(sd->fd,sidx),buf + sidx + i*s,nn*s);
|
||||
WFIFOSET(sd->fd,WFIFOW(sd->fd,2));
|
||||
@ -2895,12 +2895,23 @@ void clif_storagelist(struct map_session_data* sd, struct item* items, int items
|
||||
WFIFOW(sd->fd,0)=cmde;
|
||||
WFIFOW(sd->fd,2)=sidxe+nn*se;
|
||||
#if PACKETVER >= 20120925
|
||||
memset((char*)WFIFOP(sd->fd,4),0,24); //storename
|
||||
safestrncpy((char*)WFIFOP(sd->fd,4), storename, NAME_LENGTH); //storename
|
||||
#endif
|
||||
memcpy(WFIFOP(sd->fd,sidxe),bufe + sidxe + i*se,nn*se);
|
||||
WFIFOSET(sd->fd,WFIFOW(sd->fd,2));
|
||||
}
|
||||
|
||||
// Empty storage
|
||||
if (n == 0 && ne == 0) {
|
||||
WFIFOHEAD(sd->fd, 4+NAME_LENGTH);
|
||||
WFIFOW(sd->fd,0) = cmd;
|
||||
WFIFOW(sd->fd,2) = 4+NAME_LENGTH;
|
||||
#if PACKETVER >= 20120925
|
||||
safestrncpy((char*)WFIFOP(sd->fd,4), storename, NAME_LENGTH); //storename
|
||||
#endif
|
||||
WFIFOSET(sd->fd,WFIFOW(sd->fd,2));
|
||||
}
|
||||
|
||||
if( buf ) aFree(buf);
|
||||
if( bufe ) aFree(bufe);
|
||||
}
|
||||
@ -9155,7 +9166,7 @@ void clif_refresh_storagewindow(struct map_session_data *sd) {
|
||||
// Notify the client that the storage is open
|
||||
if( sd->state.storage_flag == 1 ) {
|
||||
storage_sortitem(sd->storage.u.items_storage, ARRAYLENGTH(sd->storage.u.items_storage));
|
||||
clif_storagelist(sd, sd->storage.u.items_storage, ARRAYLENGTH(sd->storage.u.items_storage));
|
||||
clif_storagelist(sd, sd->storage.u.items_storage, ARRAYLENGTH(sd->storage.u.items_storage), storage_getName(0));
|
||||
clif_updatestorageamount(sd, sd->storage.amount, MAX_STORAGE);
|
||||
}
|
||||
// Notify the client that the gstorage is open otherwise it will
|
||||
@ -9167,7 +9178,7 @@ void clif_refresh_storagewindow(struct map_session_data *sd) {
|
||||
intif_request_guild_storage(sd->status.account_id, sd->status.guild_id);
|
||||
else {
|
||||
storage_sortitem(gstor->u.items_guild, ARRAYLENGTH(gstor->u.items_guild));
|
||||
clif_storagelist(sd, gstor->u.items_guild, ARRAYLENGTH(gstor->u.items_guild));
|
||||
clif_storagelist(sd, gstor->u.items_guild, ARRAYLENGTH(gstor->u.items_guild), "Guild Storage");
|
||||
clif_updatestorageamount(sd, gstor->amount, MAX_GUILD_STORAGE);
|
||||
}
|
||||
}
|
||||
@ -12504,10 +12515,12 @@ void clif_parse_MoveToKafra(int fd, struct map_session_data *sd)
|
||||
return;
|
||||
|
||||
if (sd->state.storage_flag == 1)
|
||||
storage_storageadd(sd, item_index, item_amount);
|
||||
storage_storageadd(sd, &sd->storage, item_index, item_amount);
|
||||
else
|
||||
if (sd->state.storage_flag == 2)
|
||||
storage_guild_storageadd(sd, item_index, item_amount);
|
||||
else if (sd->state.storage_flag == 3)
|
||||
storage_storageadd(sd, &sd->premiumStorage, item_index, item_amount);
|
||||
}
|
||||
|
||||
|
||||
@ -12524,9 +12537,11 @@ void clif_parse_MoveFromKafra(int fd,struct map_session_data *sd)
|
||||
item_amount = RFIFOL(fd,info->pos[1]);
|
||||
|
||||
if (sd->state.storage_flag == 1)
|
||||
storage_storageget(sd, item_index, item_amount);
|
||||
storage_storageget(sd, &sd->storage, item_index, item_amount);
|
||||
else if(sd->state.storage_flag == 2)
|
||||
storage_guild_storageget(sd, item_index, item_amount);
|
||||
else if(sd->state.storage_flag == 3)
|
||||
storage_storageget(sd, &sd->premiumStorage, item_index, item_amount);
|
||||
}
|
||||
|
||||
|
||||
@ -12544,9 +12559,11 @@ void clif_parse_MoveToKafraFromCart(int fd, struct map_session_data *sd){
|
||||
return;
|
||||
|
||||
if (sd->state.storage_flag == 1)
|
||||
storage_storageaddfromcart(sd, idx, amount);
|
||||
storage_storageaddfromcart(sd, &sd->storage, idx, amount);
|
||||
else if (sd->state.storage_flag == 2)
|
||||
storage_guild_storageaddfromcart(sd, idx, amount);
|
||||
else if (sd->state.storage_flag == 3)
|
||||
storage_storageaddfromcart(sd, &sd->premiumStorage, idx, amount);
|
||||
}
|
||||
|
||||
|
||||
@ -12563,10 +12580,12 @@ void clif_parse_MoveFromKafraToCart(int fd, struct map_session_data *sd){
|
||||
return;
|
||||
|
||||
if (sd->state.storage_flag == 1)
|
||||
storage_storagegettocart(sd, idx, amount);
|
||||
storage_storagegettocart(sd, &sd->storage, idx, amount);
|
||||
else
|
||||
if (sd->state.storage_flag == 2)
|
||||
storage_guild_storagegettocart(sd, idx, amount);
|
||||
else if (sd->state.storage_flag == 3)
|
||||
storage_storagegettocart(sd, &sd->premiumStorage, idx, amount);
|
||||
}
|
||||
|
||||
|
||||
@ -12579,6 +12598,8 @@ void clif_parse_CloseKafra(int fd, struct map_session_data *sd)
|
||||
else
|
||||
if( sd->state.storage_flag == 2 )
|
||||
storage_guild_storageclose(sd);
|
||||
else if( sd->state.storage_flag == 3 )
|
||||
storage_premiumStorage_close(sd);
|
||||
}
|
||||
|
||||
|
||||
|
@ -616,7 +616,7 @@ void clif_tradecompleted(struct map_session_data* sd, int fail);
|
||||
void clif_tradeundo(struct map_session_data* sd);
|
||||
|
||||
// storage
|
||||
void clif_storagelist(struct map_session_data* sd, struct item* items, int items_length);
|
||||
void clif_storagelist(struct map_session_data* sd, struct item* items, int items_length, const char *storename);
|
||||
void clif_updatestorageamount(struct map_session_data* sd, int amount, int max_amount);
|
||||
void clif_storageitemadded(struct map_session_data* sd, struct item* i, int index, int amount);
|
||||
void clif_storageitemremoved(struct map_session_data* sd, int index, int amount);
|
||||
|
108
src/map/intif.c
108
src/map/intif.c
@ -35,7 +35,7 @@ static const int packet_len_table[] = {
|
||||
-1,-1, 7, 7, 7,11, 8,-1, 0, 0, 0, 0, 0, 0, 0, 0, //0x3850 Auctions [Zephyrus] itembound[Akinari]
|
||||
-1, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3860 Quests [Kevin] [Inkfish]
|
||||
-1, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 3, 3, 0, //0x3870 Mercenaries [Zephyrus] / Elemental [pakpil]
|
||||
12,-1, 7, 3, 0, 0, 0, 0, 0, 0,-1, 8, 0, 0, 0, 0, //0x3880 Pet System, Storages
|
||||
12,-1, 7, 3, 0, 0, 0, 0, 0, 0,-1, 9, -1, 0, 0, 0, //0x3880 Pet System, Storages
|
||||
-1,-1, 7, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3890 Homunculus [albator]
|
||||
};
|
||||
|
||||
@ -3146,7 +3146,7 @@ static bool intif_parse_StorageReceived(int fd)
|
||||
char type = RFIFOB(fd,4);
|
||||
uint32 account_id = RFIFOL(fd, 5);
|
||||
struct map_session_data *sd = map_id2sd(account_id);
|
||||
struct s_storage *stor; //storage
|
||||
struct s_storage *stor, *p; //storage
|
||||
size_t sz_stor = sizeof(struct s_storage);
|
||||
|
||||
if (!sd) {
|
||||
@ -3159,22 +3159,31 @@ static bool intif_parse_StorageReceived(int fd)
|
||||
return false;
|
||||
}
|
||||
|
||||
p = (struct s_storage *)RFIFOP(fd,10);
|
||||
|
||||
switch (type) {
|
||||
case TABLE_INVENTORY: stor = &sd->inventory; break;
|
||||
case TABLE_STORAGE: stor = &sd->storage; break;
|
||||
case TABLE_STORAGE:
|
||||
if (p->stor_id == 0)
|
||||
stor = &sd->storage;
|
||||
else
|
||||
stor = &sd->premiumStorage;
|
||||
break;
|
||||
case TABLE_CART:
|
||||
stor = &sd->cart;
|
||||
break;
|
||||
default: return false;
|
||||
}
|
||||
|
||||
if (stor->status) { // Already open.. lets ignore this update
|
||||
ShowWarning("intif_parse_StorageReceived: storage received for a client already open (User %d:%d)\n", sd->status.account_id, sd->status.char_id);
|
||||
return false;
|
||||
}
|
||||
if (stor->dirty) { // Already have storage, and it has been modified and not saved yet! Exploit!
|
||||
ShowWarning("intif_parse_StorageReceived: received storage for an already modified non-saved storage! (User %d:%d)\n", sd->status.account_id, sd->status.char_id);
|
||||
return false;
|
||||
if (stor->stor_id == p->stor_id) {
|
||||
if (stor->status) { // Already open.. lets ignore this update
|
||||
ShowWarning("intif_parse_StorageReceived: storage received for a client already open (User %d:%d)\n", sd->status.account_id, sd->status.char_id);
|
||||
return false;
|
||||
}
|
||||
if (stor->dirty) { // Already have storage, and it has been modified and not saved yet! Exploit!
|
||||
ShowWarning("intif_parse_StorageReceived: received storage for an already modified non-saved storage! (User %d:%d)\n", sd->status.account_id, sd->status.char_id);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (RFIFOW(fd,2)-10 != sz_stor) {
|
||||
ShowError("intif_parse_StorageReceived: data size error %d %d\n",RFIFOW(fd,2)-10 , sz_stor);
|
||||
@ -3182,7 +3191,7 @@ static bool intif_parse_StorageReceived(int fd)
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(stor, RFIFOP(fd,10), sz_stor); //copy the items data to correct destination
|
||||
memcpy(stor, p, sz_stor); //copy the items data to correct destination
|
||||
|
||||
switch (type) {
|
||||
case TABLE_INVENTORY: {
|
||||
@ -3224,7 +3233,15 @@ static bool intif_parse_StorageReceived(int fd)
|
||||
break;
|
||||
|
||||
case TABLE_STORAGE:
|
||||
pc_check_available_item(sd, ITMCHK_STORAGE);
|
||||
if (stor->stor_id)
|
||||
storage_premiumStorage_open(sd);
|
||||
else {
|
||||
#ifdef VIP_ENABLE
|
||||
if (!pc_isvip(sd))
|
||||
stor->max_amount = MIN_STORAGE;
|
||||
#endif
|
||||
pc_check_available_item(sd, ITMCHK_STORAGE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
@ -3232,7 +3249,7 @@ static bool intif_parse_StorageReceived(int fd)
|
||||
|
||||
/**
|
||||
* Save inventory/cart/storage data for a player
|
||||
* IZ 0x388b <account_id>.L <result>.B <type>.B
|
||||
* IZ 0x388b <account_id>.L <result>.B <type>.B <storage_id>.B
|
||||
* @param fd
|
||||
*/
|
||||
static void intif_parse_StorageSaved(int fd)
|
||||
@ -3244,6 +3261,8 @@ static void intif_parse_StorageSaved(int fd)
|
||||
break;
|
||||
case TABLE_STORAGE: //storage
|
||||
//ShowInfo("Storage has been saved (AID: %d).\n", RFIFOL(fd, 2));
|
||||
if (RFIFOB(fd, 8))
|
||||
storage_premiumStorage_saved(map_id2sd(RFIFOL(fd, 2)));
|
||||
break;
|
||||
case TABLE_CART: // cart
|
||||
//ShowInfo("Cart has been saved (AID: %d).\n", RFIFOL(fd, 2));
|
||||
@ -3251,7 +3270,7 @@ static void intif_parse_StorageSaved(int fd)
|
||||
struct map_session_data *sd = map_id2sd(RFIFOL(fd, 2));
|
||||
|
||||
if( sd && sd->state.prevend ){
|
||||
intif_storage_request(sd,TABLE_CART);
|
||||
intif_storage_request(sd,TABLE_CART,0,STOR_MODE_ALL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -3262,24 +3281,54 @@ static void intif_parse_StorageSaved(int fd)
|
||||
ShowError("Failed to save inventory/cart/storage data (AID: %d, type: %d).\n", RFIFOL(fd, 2), RFIFOB(fd, 7));
|
||||
}
|
||||
|
||||
/**
|
||||
* IZ 0x388c <len>.W { <storage_table>.? }*?
|
||||
* Receive storage information
|
||||
**/
|
||||
void intif_parse_StorageInfo_recv(int fd) {
|
||||
int i, size = sizeof(struct s_storage_table), count = (RFIFOW(fd, 2) - 4) / size;
|
||||
|
||||
storage_count = 0;
|
||||
if (storage_db)
|
||||
aFree(storage_db);
|
||||
storage_db = NULL;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
char name[NAME_LENGTH+1];
|
||||
safestrncpy(name, (char *)RFIFOP(fd, 5 + size * i), NAME_LENGTH);
|
||||
if (!name || name[0] == '\0')
|
||||
continue;
|
||||
RECREATE(storage_db, struct s_storage_table, storage_count+1);
|
||||
memcpy(&storage_db[storage_count], RFIFOP(fd, 4 + size * i), size);
|
||||
storage_count++;
|
||||
}
|
||||
|
||||
if (battle_config.etc_log)
|
||||
ShowInfo("Received '"CL_WHITE"%d"CL_RESET"' storage info from inter-server.\n", storage_count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Request inventory/cart/storage data for a player
|
||||
* ZI 0x308a <type>.B <account_id>.L <char_id>.L
|
||||
* ZI 0x308a <type>.B <account_id>.L <char_id>.L <storage_id>.B
|
||||
* @param sd: Player data
|
||||
* @param type: Storage type
|
||||
* @param stor_id: Storage ID
|
||||
* @param mode: Storage mode
|
||||
* @return false - error, true - message sent
|
||||
*/
|
||||
bool intif_storage_request(struct map_session_data *sd, enum storage_type type)
|
||||
bool intif_storage_request(struct map_session_data *sd, enum storage_type type, uint8 stor_id, uint8 mode)
|
||||
{
|
||||
if (CheckForCharServer())
|
||||
return false;
|
||||
|
||||
WFIFOHEAD(inter_fd, 11);
|
||||
WFIFOHEAD(inter_fd, 13);
|
||||
WFIFOW(inter_fd, 0) = 0x308a;
|
||||
WFIFOB(inter_fd, 2) = type;
|
||||
WFIFOL(inter_fd, 3) = sd->status.account_id;
|
||||
WFIFOL(inter_fd, 7) = sd->status.char_id;
|
||||
WFIFOSET(inter_fd, 11);
|
||||
WFIFOB(inter_fd, 11) = stor_id;
|
||||
WFIFOB(inter_fd, 12) = mode;
|
||||
WFIFOSET(inter_fd, 13);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -3287,37 +3336,23 @@ bool intif_storage_request(struct map_session_data *sd, enum storage_type type)
|
||||
* Request to save inventory/cart/storage data from player
|
||||
* ZI 0x308b <size>.W <type>.B <account_id>.L <char_id>.L <entries>.?B
|
||||
* @param sd: Player data
|
||||
* @param type: Storage type
|
||||
* @param stor: Storage data
|
||||
* @ return false - error, true - message sent
|
||||
*/
|
||||
bool intif_storage_save(struct map_session_data *sd, enum storage_type type)
|
||||
bool intif_storage_save(struct map_session_data *sd, struct s_storage *stor)
|
||||
{
|
||||
int stor_size = sizeof(struct s_storage);
|
||||
struct s_storage *stor;
|
||||
|
||||
nullpo_retr(false, sd);
|
||||
nullpo_retr(false, stor);
|
||||
|
||||
if (CheckForCharServer())
|
||||
return false;
|
||||
|
||||
switch(type) {
|
||||
case TABLE_INVENTORY:
|
||||
stor = &sd->inventory;
|
||||
break;
|
||||
case TABLE_STORAGE:
|
||||
stor = &sd->storage;
|
||||
break;
|
||||
case TABLE_CART:
|
||||
stor = &sd->cart;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
WFIFOHEAD(inter_fd, stor_size+13);
|
||||
WFIFOW(inter_fd, 0) = 0x308b;
|
||||
WFIFOW(inter_fd, 2) = stor_size+13;
|
||||
WFIFOB(inter_fd, 4) = type;
|
||||
WFIFOB(inter_fd, 4) = stor->type;
|
||||
WFIFOL(inter_fd, 5) = sd->status.account_id;
|
||||
WFIFOL(inter_fd, 9) = sd->status.char_id;
|
||||
memcpy(WFIFOP(inter_fd, 13), stor, stor_size);
|
||||
@ -3440,6 +3475,7 @@ int intif_parse(int fd)
|
||||
// Storage
|
||||
case 0x388a: intif_parse_StorageReceived(fd); break;
|
||||
case 0x388b: intif_parse_StorageSaved(fd); break;
|
||||
case 0x388c: intif_parse_StorageInfo_recv(fd); break;
|
||||
|
||||
// Homunculus System
|
||||
case 0x3890: intif_parse_CreateHomunculus(fd); break;
|
||||
|
@ -111,8 +111,8 @@ int intif_elemental_save(struct s_elemental *ele);
|
||||
int intif_request_accinfo(int u_fd, int aid, int group_lv, char* query, char type);
|
||||
|
||||
// STORAGE
|
||||
bool intif_storage_request(struct map_session_data *sd, enum storage_type type);
|
||||
bool intif_storage_save(struct map_session_data *sd, enum storage_type type);
|
||||
bool intif_storage_request(struct map_session_data *sd, enum storage_type type, uint8 stor_id, uint8 mode);
|
||||
bool intif_storage_save(struct map_session_data *sd, struct s_storage *stor);
|
||||
|
||||
int CheckForCharServer(void);
|
||||
|
||||
|
13
src/map/pc.c
13
src/map/pc.c
@ -1151,6 +1151,7 @@ bool pc_authok(struct map_session_data *sd, uint32 login_id2, time_t expiration_
|
||||
memset(&sd->inventory, 0, sizeof(struct s_storage));
|
||||
memset(&sd->cart, 0, sizeof(struct s_storage));
|
||||
memset(&sd->storage, 0, sizeof(struct s_storage));
|
||||
memset(&sd->premiumStorage, 0, sizeof(struct s_storage));
|
||||
memset(&sd->equip_index, -1, sizeof(sd->equip_index));
|
||||
|
||||
if( sd->status.option&OPTION_INVISIBLE && !pc_can_use_command( sd, "hide", COMMAND_ATCOMMAND ) ){
|
||||
@ -1399,11 +1400,9 @@ void pc_reg_received(struct map_session_data *sd)
|
||||
return;
|
||||
sd->state.active = 1;
|
||||
|
||||
intif_storage_request(sd,TABLE_INVENTORY); // Request inventory data
|
||||
intif_storage_request(sd,TABLE_CART); // Request cart data
|
||||
intif_storage_request(sd,TABLE_STORAGE); // Request storage data
|
||||
|
||||
sd->storage_size = MIN_STORAGE; //default to min
|
||||
intif_storage_request(sd,TABLE_STORAGE, 0, STOR_MODE_ALL); // Request storage data
|
||||
intif_storage_request(sd,TABLE_CART, 0, STOR_MODE_ALL); // Request cart data
|
||||
intif_storage_request(sd,TABLE_INVENTORY, 0, STOR_MODE_ALL); // Request inventory data
|
||||
|
||||
if (sd->status.party_id)
|
||||
party_member_joined(sd);
|
||||
@ -9970,7 +9969,7 @@ void pc_check_available_item(struct map_session_data *sd, uint8 type)
|
||||
}
|
||||
|
||||
if (battle_config.item_check&ITMCHK_STORAGE || type&ITMCHK_STORAGE) { // Check for invalid(ated) items in storage.
|
||||
for(i = 0; i < sd->storage_size; i++) {
|
||||
for(i = 0; i < sd->storage.max_amount; i++) {
|
||||
nameid = sd->storage.u.items_storage[i].nameid;
|
||||
|
||||
if (!nameid)
|
||||
@ -9979,7 +9978,7 @@ void pc_check_available_item(struct map_session_data *sd, uint8 type)
|
||||
sprintf(output, msg_txt(sd, 711), nameid); // Item %hu has been removed from your storage.
|
||||
clif_displaymessage(sd->fd, output);
|
||||
ShowWarning("Removed invalid/disabled item (ID: %hu, amount: %d) from storage (char_id: %d).\n", nameid, sd->storage.u.items_storage[i].amount, sd->status.char_id);
|
||||
storage_delitem(sd, i, sd->storage.u.items_storage[i].amount);
|
||||
storage_delitem(sd, &sd->storage, i, sd->storage.u.items_storage[i].amount);
|
||||
continue;
|
||||
}
|
||||
if (!sd->storage.u.items_storage[i].unique_id && !itemdb_isstackable(nameid))
|
||||
|
@ -206,7 +206,7 @@ struct map_session_data {
|
||||
unsigned int arrow_atk : 1;
|
||||
unsigned int gangsterparadise : 1;
|
||||
unsigned int rest : 1;
|
||||
unsigned int storage_flag : 2; //0: closed, 1: Normal Storage open, 2: guild storage open [Skotlex]
|
||||
unsigned int storage_flag : 3; //0: closed, 1: Normal Storage open, 2: guild storage open [Skotlex], 3: Premium Storage
|
||||
unsigned int snovice_dead_flag : 1; //Explosion spirits on death: 0 off, 1 used.
|
||||
unsigned int abra_flag : 2; // Abracadabra bugfix by Aru
|
||||
unsigned int autocast : 1; // Autospell flag [Inkfish]
|
||||
@ -275,7 +275,7 @@ struct map_session_data {
|
||||
struct mmo_charstatus status;
|
||||
|
||||
// Item Storages
|
||||
struct s_storage storage;
|
||||
struct s_storage storage, premiumStorage;
|
||||
struct s_storage inventory;
|
||||
struct s_storage cart;
|
||||
|
||||
@ -654,7 +654,6 @@ struct map_session_data {
|
||||
int c_marker[MAX_SKILL_CRIMSON_MARKER]; /// Store target that marked by Crimson Marker [Cydh]
|
||||
bool flicker; /// Check RL_FLICKER usage status [Cydh]
|
||||
|
||||
int storage_size; /// Holds player storage size (VIP system).
|
||||
#ifdef VIP_ENABLE
|
||||
struct vip_info vip;
|
||||
#endif
|
||||
|
@ -7382,7 +7382,7 @@ static void buildin_delitem_delete(struct map_session_data* sd, int idx, int* am
|
||||
pc_cart_delitem(sd,idx,delamount,0,LOG_TYPE_SCRIPT);
|
||||
break;
|
||||
case TABLE_STORAGE:
|
||||
storage_delitem(sd,idx,delamount);
|
||||
storage_delitem(sd,&sd->storage,idx,delamount);
|
||||
log_pick_pc(sd,LOG_TYPE_SCRIPT,-delamount,itm);
|
||||
break;
|
||||
case TABLE_GUILD_STORAGE:
|
||||
@ -22012,7 +22012,28 @@ BUILDIN_FUNC(getguildalliance)
|
||||
script_pushint(st, 2);
|
||||
else
|
||||
script_pushint(st, 1);
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* openstorage2 <storage_id>,<mode>{,<account_id>}
|
||||
* mode @see enum e_storage_mode
|
||||
**/
|
||||
BUILDIN_FUNC(openstorage2) {
|
||||
int stor_id = script_getnum(st, 2);
|
||||
TBL_PC *sd = NULL;
|
||||
|
||||
if (!script_accid2sd(4, sd)) {
|
||||
script_pushint(st, 0);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
if (!storage_exists(stor_id)) {
|
||||
ShowError("buildin_openstorage2: Invalid storage_id '%d'!\n", stor_id);
|
||||
return SCRIPT_CMD_FAILURE;
|
||||
}
|
||||
|
||||
script_pushint(st, storage_premiumStorage_load(sd, stor_id, script_getnum(st, 3)));
|
||||
return SCRIPT_CMD_SUCCESS;
|
||||
}
|
||||
|
||||
@ -22607,6 +22628,7 @@ struct script_function buildin_func[] = {
|
||||
BUILDIN_DEF(setrandomoption,"iiiii?"),
|
||||
BUILDIN_DEF(needed_status_point,"ii?"),
|
||||
BUILDIN_DEF(jobcanentermap,"s?"),
|
||||
BUILDIN_DEF(openstorage2,"ii?"),
|
||||
|
||||
// WoE TE
|
||||
BUILDIN_DEF(agitstart3,""),
|
||||
|
@ -3170,6 +3170,10 @@
|
||||
export_constant(CARD0_CREATE);
|
||||
export_constant(CARD0_PET);
|
||||
|
||||
export_constant(STOR_MODE_NONE);
|
||||
export_constant(STOR_MODE_GET);
|
||||
export_constant(STOR_MODE_PUT);
|
||||
|
||||
#undef export_constant
|
||||
|
||||
#endif /* _SCRIPT_CONSTANTS_H_ */
|
||||
|
@ -7319,7 +7319,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui
|
||||
sd->vend_skill_lv = skill_lv;
|
||||
ARR_FIND(0, MAX_CART, i, sd->cart.u.items_cart[i].nameid && sd->cart.u.items_cart[i].id == 0);
|
||||
if (i < MAX_CART)
|
||||
intif_storage_save(sd, TABLE_CART);
|
||||
intif_storage_save(sd, &sd->cart);
|
||||
else
|
||||
clif_openvendingreq(sd,2+skill_lv);
|
||||
}
|
||||
|
@ -20,6 +20,41 @@
|
||||
|
||||
|
||||
static DBMap* guild_storage_db; ///Databases of guild_storage : int guild_id -> struct guild_storage*
|
||||
struct s_storage_table *storage_db;
|
||||
int storage_count;
|
||||
|
||||
/**
|
||||
* Get storage name
|
||||
* @param id Storage ID
|
||||
* @return Storage name or "Storage" if not found
|
||||
* @author [Cydh]
|
||||
**/
|
||||
const char *storage_getName(uint8 id) {
|
||||
if (storage_db && storage_count) {
|
||||
int i;
|
||||
for (i = 0; i < storage_count; i++) {
|
||||
if (&storage_db[i] && storage_db[i].id == id && storage_db[i].name && storage_db[i].name[0] != '\0')
|
||||
return storage_db[i].name;
|
||||
}
|
||||
}
|
||||
return "Storage";
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if sotrage ID is valid
|
||||
* @param id Storage ID
|
||||
* @return True:Valid, False:Invalid
|
||||
**/
|
||||
bool storage_exists(uint8 id) {
|
||||
if (storage_db && storage_count) {
|
||||
int i;
|
||||
for (i = 0; i < storage_count; i++) {
|
||||
if (storage_db[i].id == id)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Storage item comparator (for qsort)
|
||||
@ -64,6 +99,8 @@ void storage_sortitem(struct item* items, unsigned int size)
|
||||
void do_init_storage(void)
|
||||
{
|
||||
guild_storage_db = idb_alloc(DB_OPT_RELEASE_DATA);
|
||||
storage_db = NULL;
|
||||
storage_count = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -74,6 +111,10 @@ void do_init_storage(void)
|
||||
void do_final_storage(void)
|
||||
{
|
||||
guild_storage_db->destroy(guild_storage_db,NULL);
|
||||
if (storage_db)
|
||||
aFree(storage_db);
|
||||
storage_db = NULL;
|
||||
storage_count = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -119,9 +160,9 @@ int storage_storageopen(struct map_session_data *sd)
|
||||
}
|
||||
|
||||
sd->state.storage_flag = 1;
|
||||
storage_sortitem(sd->storage.u.items_storage, ARRAYLENGTH(sd->storage.u.items_storage));
|
||||
clif_storagelist(sd, sd->storage.u.items_storage, ARRAYLENGTH(sd->storage.u.items_storage));
|
||||
clif_updatestorageamount(sd, sd->storage.amount, sd->storage_size);
|
||||
storage_sortitem(sd->storage.u.items_storage, sd->storage.max_amount);
|
||||
clif_storagelist(sd, sd->storage.u.items_storage, sd->storage.max_amount, storage_getName(0));
|
||||
clif_updatestorageamount(sd, sd->storage.amount, sd->storage.max_amount);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -153,44 +194,98 @@ int compare_item(struct item *a, struct item *b)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if item can be added to storage
|
||||
* @param stor Storage data
|
||||
* @param idx Index item from inventory/cart
|
||||
* @param items List of items from inventory/cart
|
||||
* @param amount Amount of item will be added
|
||||
* @param max_num Max inventory/cart
|
||||
* @return @see enum e_storage_add
|
||||
**/
|
||||
static enum e_storage_add storage_canAddItem(struct s_storage *stor, int idx, struct item items[], int amount, int max_num) {
|
||||
if (stor->amount >= stor->max_amount)
|
||||
return STORAGE_ADD_NOROOM; // storage full
|
||||
|
||||
if (idx < 0 || idx >= max_num)
|
||||
return STORAGE_ADD_INVALID;
|
||||
|
||||
if (items[idx].nameid <= 0)
|
||||
return STORAGE_ADD_INVALID; // No item on that spot
|
||||
|
||||
if (amount < 1 || amount > items[idx].amount)
|
||||
return STORAGE_ADD_INVALID;
|
||||
|
||||
if (!stor->state.put)
|
||||
return STORAGE_ADD_NOACCESS;
|
||||
|
||||
return STORAGE_ADD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if item can be moved from storage
|
||||
* @param stor Storage data
|
||||
* @param idx Index from storage
|
||||
* @param amount Number of item
|
||||
* @return @see enum e_storage_add
|
||||
**/
|
||||
static enum e_storage_add storage_canGetItem(struct s_storage *stor, int idx, int amount) {
|
||||
// If last index check is sd->storage_size, if player isn't VIP anymore but there's item, player can't take it
|
||||
// Example the storage size when not VIP anymore is 350/300, player still can take the 301st~349th item.
|
||||
if( idx < 0 || idx >= ARRAYLENGTH(stor->u.items_storage) )
|
||||
return STORAGE_ADD_INVALID;
|
||||
|
||||
if( stor->u.items_storage[idx].nameid <= 0 )
|
||||
return STORAGE_ADD_INVALID; //Nothing there
|
||||
|
||||
if( amount < 1 || amount > stor->u.items_storage[idx].amount )
|
||||
return STORAGE_ADD_INVALID;
|
||||
|
||||
if (!stor->state.get)
|
||||
return STORAGE_ADD_NOACCESS;
|
||||
|
||||
return STORAGE_ADD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a player add an item to his storage
|
||||
* @param sd : player
|
||||
* @param stor : Storage data
|
||||
* @param item_data : item to add
|
||||
* @param amount : quantity of items
|
||||
* @return 0:success, 1:failed
|
||||
*/
|
||||
static int storage_additem(struct map_session_data* sd, struct item* item_data, int amount)
|
||||
static int storage_additem(struct map_session_data* sd, struct s_storage *stor, struct item *it, int amount)
|
||||
{
|
||||
struct s_storage* stor = &sd->storage;
|
||||
struct item_data *data;
|
||||
int i;
|
||||
|
||||
if( item_data->nameid == 0 || amount <= 0 )
|
||||
if( it->nameid == 0 || amount <= 0 )
|
||||
return 1;
|
||||
|
||||
data = itemdb_search(item_data->nameid);
|
||||
data = itemdb_search(it->nameid);
|
||||
|
||||
if( data->stack.storage && amount > data->stack.amount ) // item stack limitation
|
||||
return 1;
|
||||
|
||||
if( !itemdb_canstore(item_data, pc_get_group_level(sd)) ) { // Check if item is storable. [Skotlex]
|
||||
if( !itemdb_canstore(it, pc_get_group_level(sd)) ) { // Check if item is storable. [Skotlex]
|
||||
clif_displaymessage (sd->fd, msg_txt(sd,264));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( (item_data->bound > BOUND_ACCOUNT) && !pc_can_give_bounded_items(sd) ) {
|
||||
if( (it->bound > BOUND_ACCOUNT) && !pc_can_give_bounded_items(sd) ) {
|
||||
clif_displaymessage(sd->fd, msg_txt(sd,294));
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( itemdb_isstackable2(data) ) { // Stackable
|
||||
for( i = 0; i < sd->storage_size; i++ ) {
|
||||
if( compare_item(&stor->u.items_storage[i], item_data) ) { // existing items found, stack them
|
||||
for( i = 0; i < stor->max_amount; i++ ) {
|
||||
if( compare_item(&stor->u.items_storage[i], it) ) { // existing items found, stack them
|
||||
if( amount > MAX_AMOUNT - stor->u.items_storage[i].amount || ( data->stack.storage && amount > data->stack.amount - stor->u.items_storage[i].amount ) )
|
||||
return 1;
|
||||
|
||||
stor->u.items_storage[i].amount += amount;
|
||||
stor->dirty = true;
|
||||
clif_storageitemadded(sd,&stor->u.items_storage[i],i,amount);
|
||||
|
||||
return 0;
|
||||
@ -199,16 +294,17 @@ static int storage_additem(struct map_session_data* sd, struct item* item_data,
|
||||
}
|
||||
|
||||
// find free slot
|
||||
ARR_FIND( 0, sd->storage_size, i, stor->u.items_storage[i].nameid == 0 );
|
||||
if( i >= sd->storage_size )
|
||||
ARR_FIND( 0, stor->max_amount, i, stor->u.items_storage[i].nameid == 0 );
|
||||
if( i >= stor->max_amount )
|
||||
return 1;
|
||||
|
||||
// add item to slot
|
||||
memcpy(&stor->u.items_storage[i],item_data,sizeof(stor->u.items_storage[0]));
|
||||
memcpy(&stor->u.items_storage[i],it,sizeof(stor->u.items_storage[0]));
|
||||
stor->amount++;
|
||||
stor->u.items_storage[i].amount = amount;
|
||||
stor->dirty = true;
|
||||
clif_storageitemadded(sd,&stor->u.items_storage[i],i,amount);
|
||||
clif_updatestorageamount(sd, stor->amount, sd->storage_size);
|
||||
clif_updatestorageamount(sd, stor->amount, stor->max_amount);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -220,22 +316,23 @@ static int storage_additem(struct map_session_data* sd, struct item* item_data,
|
||||
* @param amount :number of item to remove
|
||||
* @return 0:sucess, 1:fail
|
||||
*/
|
||||
int storage_delitem(struct map_session_data* sd, int n, int amount)
|
||||
int storage_delitem(struct map_session_data* sd, struct s_storage *stor, int index, int amount)
|
||||
{
|
||||
if( sd->storage.u.items_storage[n].nameid == 0 || sd->storage.u.items_storage[n].amount < amount )
|
||||
if( stor->u.items_storage[index].nameid == 0 || stor->u.items_storage[index].amount < amount )
|
||||
return 1;
|
||||
|
||||
sd->storage.u.items_storage[n].amount -= amount;
|
||||
stor->u.items_storage[index].amount -= amount;
|
||||
stor->dirty = true;
|
||||
|
||||
if( sd->storage.u.items_storage[n].amount == 0 ) {
|
||||
memset(&sd->storage.u.items_storage[n],0,sizeof(sd->storage.u.items_storage[0]));
|
||||
sd->storage.amount--;
|
||||
if( sd->state.storage_flag == 1 )
|
||||
clif_updatestorageamount(sd, sd->storage.amount, sd->storage_size);
|
||||
if( stor->u.items_storage[index].amount == 0 ) {
|
||||
memset(&stor->u.items_storage[index],0,sizeof(stor->u.items_storage[0]));
|
||||
stor->amount--;
|
||||
if( sd->state.storage_flag == 1 || sd->state.storage_flag == 3 )
|
||||
clif_updatestorageamount(sd, stor->amount, sd->storage.max_amount);
|
||||
}
|
||||
|
||||
if( sd->state.storage_flag == 1 )
|
||||
clif_storageitemremoved(sd,n,amount);
|
||||
if( sd->state.storage_flag == 1 || sd->state.storage_flag == 3 )
|
||||
clif_storageitemremoved(sd,index,amount);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -243,32 +340,27 @@ int storage_delitem(struct map_session_data* sd, int n, int amount)
|
||||
/**
|
||||
* Add an item to the storage from the inventory.
|
||||
* @param sd : player
|
||||
* @param stor : Storage data
|
||||
* @param index : inventory index to take the item from
|
||||
* @param amount : number of item to take
|
||||
* @return 0:fail, 1:success
|
||||
*/
|
||||
void storage_storageadd(struct map_session_data* sd, int index, int amount)
|
||||
void storage_storageadd(struct map_session_data* sd, struct s_storage *stor, int index, int amount)
|
||||
{
|
||||
enum e_storage_add result;
|
||||
|
||||
nullpo_retv(sd);
|
||||
|
||||
if( sd->storage.amount > sd->storage_size )
|
||||
return; // storage full
|
||||
|
||||
if( index < 0 || index >= MAX_INVENTORY )
|
||||
result = storage_canAddItem(stor, index, sd->inventory.u.items_inventory, amount, MAX_INVENTORY);
|
||||
if (result == STORAGE_ADD_INVALID)
|
||||
return;
|
||||
|
||||
if( sd->inventory.u.items_inventory[index].nameid <= 0 )
|
||||
return; // No item on that spot
|
||||
|
||||
if( amount < 1 || amount > sd->inventory.u.items_inventory[index].amount )
|
||||
return;
|
||||
|
||||
if( storage_additem(sd,&sd->inventory.u.items_inventory[index],amount) == 0 )
|
||||
else if (result == STORAGE_ADD_OK && storage_additem(sd,stor,&sd->inventory.u.items_inventory[index],amount) == 0) {
|
||||
pc_delitem(sd,index,amount,0,4,LOG_TYPE_STORAGE);
|
||||
else {
|
||||
clif_storageitemremoved(sd,index,0);
|
||||
clif_dropitem(sd,index,0);
|
||||
return;
|
||||
}
|
||||
|
||||
clif_storageitemremoved(sd,index,0);
|
||||
clif_dropitem(sd,index,0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -278,21 +370,19 @@ void storage_storageadd(struct map_session_data* sd, int index, int amount)
|
||||
* @param amount : number of item to take
|
||||
* @return 0:fail, 1:success
|
||||
*/
|
||||
void storage_storageget(struct map_session_data* sd, int index, int amount)
|
||||
void storage_storageget(struct map_session_data *sd, struct s_storage *stor, int index, int amount)
|
||||
{
|
||||
unsigned char flag = 0;
|
||||
enum e_storage_add result;
|
||||
|
||||
if( index < 0 || index >= sd->storage_size )
|
||||
nullpo_retv(sd);
|
||||
|
||||
result = storage_canGetItem(stor, index, amount);
|
||||
if (result != STORAGE_ADD_OK)
|
||||
return;
|
||||
|
||||
if( sd->storage.u.items_storage[index].nameid <= 0 )
|
||||
return; //Nothing there
|
||||
|
||||
if( amount < 1 || amount > sd->storage.u.items_storage[index].amount )
|
||||
return;
|
||||
|
||||
if( (flag = pc_additem(sd,&sd->storage.u.items_storage[index],amount,LOG_TYPE_STORAGE)) == 0 )
|
||||
storage_delitem(sd,index,amount);
|
||||
if ((flag = pc_additem(sd,&stor->u.items_storage[index],amount,LOG_TYPE_STORAGE)) == ADDITEM_SUCCESS)
|
||||
storage_delitem(sd,stor,index,amount);
|
||||
else {
|
||||
clif_storageitemremoved(sd,index,0);
|
||||
clif_additem(sd,0,0,flag);
|
||||
@ -302,58 +392,49 @@ void storage_storageget(struct map_session_data* sd, int index, int amount)
|
||||
/**
|
||||
* Move an item from cart to storage.
|
||||
* @param sd : player
|
||||
* @param stor : Storage data
|
||||
* @param index : cart index to take the item from
|
||||
* @param amount : number of item to take
|
||||
* @return 0:fail, 1:success
|
||||
*/
|
||||
void storage_storageaddfromcart(struct map_session_data* sd, int index, int amount)
|
||||
void storage_storageaddfromcart(struct map_session_data *sd, struct s_storage *stor, int index, int amount)
|
||||
{
|
||||
enum e_storage_add result;
|
||||
nullpo_retv(sd);
|
||||
|
||||
if( sd->storage.amount > sd->storage_size )
|
||||
return; // storage full / storage closed
|
||||
|
||||
if( index < 0 || index >= MAX_CART )
|
||||
result = storage_canAddItem(stor, index, sd->cart.u.items_inventory, amount, MAX_INVENTORY);
|
||||
if (result == STORAGE_ADD_INVALID)
|
||||
return;
|
||||
|
||||
if( sd->cart.u.items_cart[index].nameid <= 0 )
|
||||
return; //No item there.
|
||||
|
||||
if( amount < 1 || amount > sd->cart.u.items_cart[index].amount )
|
||||
return;
|
||||
|
||||
if( storage_additem(sd,&sd->cart.u.items_cart[index],amount) == 0 )
|
||||
else if (result == STORAGE_ADD_OK && storage_additem(sd,stor,&sd->cart.u.items_cart[index],amount) == 0) {
|
||||
pc_cart_delitem(sd,index,amount,0,LOG_TYPE_STORAGE);
|
||||
else {
|
||||
clif_storageitemremoved(sd,index,0);
|
||||
clif_dropitem(sd,index,0);
|
||||
return;
|
||||
}
|
||||
|
||||
clif_storageitemremoved(sd,index,0);
|
||||
clif_dropitem(sd,index,0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get from Storage to the Cart inventory
|
||||
* @param sd : player
|
||||
* @param stor : Storage data
|
||||
* @param index : storage index to take the item from
|
||||
* @param amount : number of item to take
|
||||
* @return 0:fail, 1:success
|
||||
*/
|
||||
void storage_storagegettocart(struct map_session_data* sd, int index, int amount)
|
||||
void storage_storagegettocart(struct map_session_data* sd, struct s_storage *stor, int index, int amount)
|
||||
{
|
||||
unsigned char flag;
|
||||
unsigned char flag = 0;
|
||||
enum e_storage_add result;
|
||||
|
||||
nullpo_retv(sd);
|
||||
|
||||
if( index < 0 || index >= sd->storage_size )
|
||||
result = storage_canGetItem(stor, index, amount);
|
||||
if (result != STORAGE_ADD_OK)
|
||||
return;
|
||||
|
||||
if( sd->storage.u.items_storage[index].nameid <= 0 )
|
||||
return; //Nothing there.
|
||||
|
||||
if( amount < 1 || amount > sd->storage.u.items_storage[index].amount )
|
||||
return;
|
||||
|
||||
if( (flag = pc_cart_additem(sd,&sd->storage.u.items_storage[index],amount,LOG_TYPE_STORAGE)) == 0 )
|
||||
storage_delitem(sd,index,amount);
|
||||
if ((flag = pc_cart_additem(sd,&stor->u.items_storage[index],amount,LOG_TYPE_STORAGE)) == 0)
|
||||
storage_delitem(sd,stor,index,amount);
|
||||
else {
|
||||
clif_storageitemremoved(sd,index,0);
|
||||
clif_cart_additem_ack(sd,(flag==1)?ADDITEM_TO_CART_FAIL_WEIGHT:ADDITEM_TO_CART_FAIL_COUNT);
|
||||
@ -487,7 +568,7 @@ char storage_guild_storageopen(struct map_session_data* sd)
|
||||
gstor->status = true;
|
||||
sd->state.storage_flag = 2;
|
||||
storage_sortitem(gstor->u.items_guild, ARRAYLENGTH(gstor->u.items_guild));
|
||||
clif_storagelist(sd, gstor->u.items_guild, ARRAYLENGTH(gstor->u.items_guild));
|
||||
clif_storagelist(sd, gstor->u.items_guild, ARRAYLENGTH(gstor->u.items_guild), "Guild Storage");
|
||||
clif_updatestorageamount(sd, gstor->amount, MAX_GUILD_STORAGE);
|
||||
|
||||
return 0;
|
||||
@ -871,3 +952,121 @@ void storage_guild_storage_quit(struct map_session_data* sd, int flag)
|
||||
sd->state.storage_flag = 0;
|
||||
stor->status = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open premium storage
|
||||
* @param sd Player
|
||||
**/
|
||||
void storage_premiumStorage_open(struct map_session_data *sd) {
|
||||
nullpo_retv(sd);
|
||||
|
||||
if (!&sd->premiumStorage)
|
||||
return;
|
||||
|
||||
sd->state.storage_flag = 3;
|
||||
storage_sortitem(sd->premiumStorage.u.items_storage, sd->premiumStorage.max_amount);
|
||||
clif_storagelist(sd, sd->premiumStorage.u.items_storage, sd->premiumStorage.max_amount, storage_getName(sd->premiumStorage.stor_id));
|
||||
clif_updatestorageamount(sd, sd->premiumStorage.amount, sd->premiumStorage.max_amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Request to open premium storage
|
||||
* @param sd Player who request
|
||||
* @param num Storage number
|
||||
* @param mode Storage mode @see enum e_storage_mode
|
||||
* @return 1:Success to request, 0:Failed
|
||||
* @author [Cydh]
|
||||
**/
|
||||
bool storage_premiumStorage_load(struct map_session_data *sd, uint8 num, uint8 mode) {
|
||||
nullpo_ret(sd);
|
||||
|
||||
if (sd->state.storage_flag)
|
||||
return 0;
|
||||
|
||||
if (sd->state.vending || sd->state.buyingstore || sd->state.prevend || sd->state.autotrade)
|
||||
return 0;
|
||||
|
||||
if (sd->state.banking || sd->state.callshop)
|
||||
return 0;
|
||||
|
||||
if (!pc_can_give_items(sd)) { // check is this GM level is allowed to put items to storage
|
||||
clif_displaymessage(sd->fd, msg_txt(sd,246));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!&sd->premiumStorage || sd->premiumStorage.stor_id != num)
|
||||
return intif_storage_request(sd, TABLE_STORAGE, num, mode);
|
||||
else {
|
||||
sd->premiumStorage.state.put = (mode&STOR_MODE_PUT) ? 1 : 0;
|
||||
sd->premiumStorage.state.get = (mode&STOR_MODE_GET) ? 1 : 0;
|
||||
storage_premiumStorage_open(sd);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request to save premium storage
|
||||
* @param sd Player who has the storage
|
||||
* @author [Cydh]
|
||||
**/
|
||||
void storage_premiumStorage_save(struct map_session_data *sd) {
|
||||
nullpo_retv(sd);
|
||||
|
||||
if (!&sd->premiumStorage)
|
||||
return;
|
||||
|
||||
intif_storage_save(sd, &sd->premiumStorage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ack of secondary premium has been saved
|
||||
* @param sd Player who has the storage
|
||||
**/
|
||||
void storage_premiumStorage_saved(struct map_session_data *sd) {
|
||||
if (!sd)
|
||||
return;
|
||||
|
||||
if (&sd->premiumStorage) {
|
||||
sd->premiumStorage.dirty = 0;
|
||||
}
|
||||
if (sd->state.storage_flag == 3) {
|
||||
sd->state.storage_flag = 0;
|
||||
clif_storageclose(sd);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request to close premium storage
|
||||
* @param sd Player who has the storage
|
||||
* @author [Cydh]
|
||||
**/
|
||||
void storage_premiumStorage_close(struct map_session_data *sd) {
|
||||
nullpo_retv(sd);
|
||||
|
||||
if (!&sd->premiumStorage)
|
||||
return;
|
||||
|
||||
if (sd->premiumStorage.dirty) {
|
||||
intif_storage_save(sd, &sd->premiumStorage);
|
||||
if (sd->state.storage_flag == 3) {
|
||||
sd->state.storage_flag = 0;
|
||||
clif_storageclose(sd);
|
||||
}
|
||||
}
|
||||
else
|
||||
storage_premiumStorage_saved(sd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force save then close the premium storage
|
||||
* @param sd Player who has the storage
|
||||
* @author [Cydh]
|
||||
**/
|
||||
void storage_premiumStorage_quit(struct map_session_data *sd) {
|
||||
nullpo_retv(sd);
|
||||
|
||||
if (!&sd->premiumStorage)
|
||||
return;
|
||||
|
||||
intif_storage_save(sd, &sd->premiumStorage);
|
||||
}
|
||||
|
@ -10,12 +10,25 @@ struct item;
|
||||
//#include "map.h"
|
||||
struct map_session_data;
|
||||
|
||||
int storage_delitem(struct map_session_data* sd, int n, int amount);
|
||||
extern struct s_storage_table *storage_db;
|
||||
extern int storage_count;
|
||||
|
||||
enum e_storage_add {
|
||||
STORAGE_ADD_OK,
|
||||
STORAGE_ADD_NOROOM,
|
||||
STORAGE_ADD_NOACCESS,
|
||||
STORAGE_ADD_INVALID,
|
||||
};
|
||||
|
||||
const char *storage_getName(uint8 id);
|
||||
bool storage_exists(uint8 id);
|
||||
|
||||
int storage_delitem(struct map_session_data* sd, struct s_storage *stor, int index, int amount);
|
||||
int storage_storageopen(struct map_session_data *sd);
|
||||
void storage_storageadd(struct map_session_data *sd,int index,int amount);
|
||||
void storage_storageget(struct map_session_data *sd,int index,int amount);
|
||||
void storage_storageaddfromcart(struct map_session_data *sd,int index,int amount);
|
||||
void storage_storagegettocart(struct map_session_data *sd,int index,int amount);
|
||||
void storage_storageadd(struct map_session_data *sd, struct s_storage *stor, int index, int amount);
|
||||
void storage_storageget(struct map_session_data *sd, struct s_storage *stor, int index, int amount);
|
||||
void storage_storageaddfromcart(struct map_session_data *sd, struct s_storage *stor, int index, int amount);
|
||||
void storage_storagegettocart(struct map_session_data *sd, struct s_storage *stor, int index, int amount);
|
||||
void storage_storageclose(struct map_session_data *sd);
|
||||
void storage_sortitem(struct item* items, unsigned int size);
|
||||
void do_init_storage(void);
|
||||
@ -39,6 +52,14 @@ void storage_guild_storage_quit(struct map_session_data *sd,int flag);
|
||||
bool storage_guild_storagesave(uint32 account_id, int guild_id, int flag);
|
||||
void storage_guild_storagesaved(int guild_id); //Ack from char server that guild store was saved.
|
||||
|
||||
// Premium Storage [Cydh]
|
||||
void storage_premiumStorage_open(struct map_session_data *sd);
|
||||
bool storage_premiumStorage_load(struct map_session_data *sd, uint8 num, uint8 mode);
|
||||
void storage_premiumStorage_save(struct map_session_data *sd);
|
||||
void storage_premiumStorage_saved(struct map_session_data *sd);
|
||||
void storage_premiumStorage_close(struct map_session_data *sd);
|
||||
void storage_premiumStorage_quit(struct map_session_data *sd);
|
||||
|
||||
int compare_item(struct item *a, struct item *b);
|
||||
|
||||
#endif /* _STORAGE_H_ */
|
||||
|
@ -2912,6 +2912,8 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
|
||||
storage_storage_quit(sd,0);
|
||||
else if (sd->state.storage_flag == 2)
|
||||
storage_guild_storage_quit(sd, 0);
|
||||
else if (sd->state.storage_flag == 3)
|
||||
storage_premiumStorage_quit(sd);
|
||||
|
||||
sd->state.storage_flag = 0; //Force close it when being warped.
|
||||
}
|
||||
|
@ -282,6 +282,7 @@
|
||||
<Copy SourceFiles="..\conf\import-tmpl\battle_conf.txt" DestinationFolder="..\conf\import\" ContinueOnError="true" Condition="!Exists('..\conf\import\battle_conf.txt')" />
|
||||
<Copy SourceFiles="..\conf\import-tmpl\char_conf.txt" DestinationFolder="..\conf\import\" ContinueOnError="true" Condition="!Exists('..\conf\import\char_conf.txt')" />
|
||||
<Copy SourceFiles="..\conf\import-tmpl\inter_conf.txt" DestinationFolder="..\conf\import\" ContinueOnError="true" Condition="!Exists('..\conf\import\inter_conf.txt')" />
|
||||
<Copy SourceFiles="..\conf\import-tmpl\inter_server.conf" DestinationFolder="..\conf\import\" ContinueOnError="true" Condition="!Exists('..\conf\import\inter_server.conf')" />
|
||||
<Copy SourceFiles="..\conf\import-tmpl\log_conf.txt" DestinationFolder="..\conf\import\" ContinueOnError="true" Condition="!Exists('..\conf\import\log_conf.txt')" />
|
||||
<Copy SourceFiles="..\conf\import-tmpl\login_conf.txt" DestinationFolder="..\conf\import\" ContinueOnError="true" Condition="!Exists('..\conf\import\login_conf.txt')" />
|
||||
<Copy SourceFiles="..\conf\import-tmpl\map_conf.txt" DestinationFolder="..\conf\import\" ContinueOnError="true" Condition="!Exists('..\conf\import\map_conf.txt')" />
|
||||
|
@ -286,6 +286,7 @@
|
||||
<Copy SourceFiles="..\conf\import-tmpl\battle_conf.txt" DestinationFolder="..\conf\import\" ContinueOnError="true" Condition="!Exists('..\conf\import\battle_conf.txt')" />
|
||||
<Copy SourceFiles="..\conf\import-tmpl\char_conf.txt" DestinationFolder="..\conf\import\" ContinueOnError="true" Condition="!Exists('..\conf\import\char_conf.txt')" />
|
||||
<Copy SourceFiles="..\conf\import-tmpl\inter_conf.txt" DestinationFolder="..\conf\import\" ContinueOnError="true" Condition="!Exists('..\conf\import\inter_conf.txt')" />
|
||||
<Copy SourceFiles="..\conf\import-tmpl\inter_server.conf" DestinationFolder="..\conf\import\" ContinueOnError="true" Condition="!Exists('..\conf\import\inter_server.conf')" />
|
||||
<Copy SourceFiles="..\conf\import-tmpl\log_conf.txt" DestinationFolder="..\conf\import\" ContinueOnError="true" Condition="!Exists('..\conf\import\log_conf.txt')" />
|
||||
<Copy SourceFiles="..\conf\import-tmpl\login_conf.txt" DestinationFolder="..\conf\import\" ContinueOnError="true" Condition="!Exists('..\conf\import\login_conf.txt')" />
|
||||
<Copy SourceFiles="..\conf\import-tmpl\map_conf.txt" DestinationFolder="..\conf\import\" ContinueOnError="true" Condition="!Exists('..\conf\import\map_conf.txt')" />
|
||||
|
@ -286,6 +286,7 @@
|
||||
<Copy SourceFiles="..\conf\import-tmpl\battle_conf.txt" DestinationFolder="..\conf\import\" ContinueOnError="true" Condition="!Exists('..\conf\import\battle_conf.txt')" />
|
||||
<Copy SourceFiles="..\conf\import-tmpl\char_conf.txt" DestinationFolder="..\conf\import\" ContinueOnError="true" Condition="!Exists('..\conf\import\char_conf.txt')" />
|
||||
<Copy SourceFiles="..\conf\import-tmpl\inter_conf.txt" DestinationFolder="..\conf\import\" ContinueOnError="true" Condition="!Exists('..\conf\import\inter_conf.txt')" />
|
||||
<Copy SourceFiles="..\conf\import-tmpl\inter_server.conf" DestinationFolder="..\conf\import\" ContinueOnError="true" Condition="!Exists('..\conf\import\inter_server.conf')" />
|
||||
<Copy SourceFiles="..\conf\import-tmpl\log_conf.txt" DestinationFolder="..\conf\import\" ContinueOnError="true" Condition="!Exists('..\conf\import\log_conf.txt')" />
|
||||
<Copy SourceFiles="..\conf\import-tmpl\login_conf.txt" DestinationFolder="..\conf\import\" ContinueOnError="true" Condition="!Exists('..\conf\import\login_conf.txt')" />
|
||||
<Copy SourceFiles="..\conf\import-tmpl\map_conf.txt" DestinationFolder="..\conf\import\" ContinueOnError="true" Condition="!Exists('..\conf\import\map_conf.txt')" />
|
||||
|
@ -284,6 +284,7 @@
|
||||
<Copy SourceFiles="..\conf\import-tmpl\battle_conf.txt" DestinationFolder="..\conf\import\" ContinueOnError="true" Condition="!Exists('..\conf\import\battle_conf.txt')" />
|
||||
<Copy SourceFiles="..\conf\import-tmpl\char_conf.txt" DestinationFolder="..\conf\import\" ContinueOnError="true" Condition="!Exists('..\conf\import\char_conf.txt')" />
|
||||
<Copy SourceFiles="..\conf\import-tmpl\inter_conf.txt" DestinationFolder="..\conf\import\" ContinueOnError="true" Condition="!Exists('..\conf\import\inter_conf.txt')" />
|
||||
<Copy SourceFiles="..\conf\import-tmpl\inter_server.conf" DestinationFolder="..\conf\import\" ContinueOnError="true" Condition="!Exists('..\conf\import\inter_server.conf')" />
|
||||
<Copy SourceFiles="..\conf\import-tmpl\log_conf.txt" DestinationFolder="..\conf\import\" ContinueOnError="true" Condition="!Exists('..\conf\import\log_conf.txt')" />
|
||||
<Copy SourceFiles="..\conf\import-tmpl\login_conf.txt" DestinationFolder="..\conf\import\" ContinueOnError="true" Condition="!Exists('..\conf\import\login_conf.txt')" />
|
||||
<Copy SourceFiles="..\conf\import-tmpl\map_conf.txt" DestinationFolder="..\conf\import\" ContinueOnError="true" Condition="!Exists('..\conf\import\map_conf.txt')" />
|
||||
|
Loading…
x
Reference in New Issue
Block a user