[1] | 1 | // Copyright (c) Athena Dev Teams - Licensed under GNU GPL |
---|
| 2 | // For more information, see LICENCE in the main folder |
---|
| 3 | |
---|
| 4 | #include "../common/cbasetypes.h" |
---|
| 5 | #include "../common/db.h" |
---|
| 6 | #include "../common/nullpo.h" |
---|
| 7 | #include "../common/malloc.h" |
---|
| 8 | #include "../common/showmsg.h" |
---|
| 9 | |
---|
| 10 | #include "map.h" // struct map_session_data |
---|
| 11 | #include "storage.h" |
---|
| 12 | #include "chrif.h" |
---|
| 13 | #include "itemdb.h" |
---|
| 14 | #include "clif.h" |
---|
| 15 | #include "intif.h" |
---|
| 16 | #include "pc.h" |
---|
| 17 | #include "guild.h" |
---|
| 18 | #include "battle.h" |
---|
| 19 | #include "atcommand.h" |
---|
| 20 | #include "log.h" |
---|
| 21 | |
---|
| 22 | #include <stdio.h> |
---|
| 23 | #include <stdlib.h> |
---|
| 24 | #include <string.h> |
---|
| 25 | |
---|
| 26 | |
---|
| 27 | static DBMap* storage_db; // int account_id -> struct storage* |
---|
| 28 | static DBMap* guild_storage_db; // int guild_id -> struct guild_storage* |
---|
| 29 | |
---|
| 30 | /*========================================== |
---|
| 31 | * qÉàACe\[g |
---|
| 32 | *------------------------------------------*/ |
---|
| 33 | int storage_comp_item(const void *_i1, const void *_i2) |
---|
| 34 | { |
---|
| 35 | struct item *i1 = (struct item *)_i1; |
---|
| 36 | struct item *i2 = (struct item *)_i2; |
---|
| 37 | |
---|
| 38 | if (i1->nameid == i2->nameid) |
---|
| 39 | return 0; |
---|
| 40 | else if (!(i1->nameid) || !(i1->amount)) |
---|
| 41 | return 1; |
---|
| 42 | else if (!(i2->nameid) || !(i2->amount)) |
---|
| 43 | return -1; |
---|
| 44 | return i1->nameid - i2->nameid; |
---|
| 45 | } |
---|
| 46 | |
---|
| 47 | void storage_sortitem (struct storage *stor) |
---|
| 48 | { |
---|
| 49 | nullpo_retv(stor); |
---|
| 50 | qsort(stor->storage_, MAX_STORAGE, sizeof(struct item), storage_comp_item); |
---|
| 51 | } |
---|
| 52 | |
---|
| 53 | void storage_gsortitem (struct guild_storage* gstor) |
---|
| 54 | { |
---|
| 55 | nullpo_retv(gstor); |
---|
| 56 | qsort(gstor->storage_, MAX_GUILD_STORAGE, sizeof(struct item), storage_comp_item); |
---|
| 57 | } |
---|
| 58 | |
---|
| 59 | /*========================================== |
---|
| 60 | * ú»Æ© |
---|
| 61 | *------------------------------------------*/ |
---|
| 62 | int do_init_storage(void) // map.c::do_init()©çÄÎêé |
---|
| 63 | { |
---|
| 64 | storage_db=idb_alloc(DB_OPT_RELEASE_DATA); |
---|
| 65 | guild_storage_db=idb_alloc(DB_OPT_RELEASE_DATA); |
---|
| 66 | return 1; |
---|
| 67 | } |
---|
| 68 | void do_final_storage(void) // by [MC Cameri] |
---|
| 69 | { |
---|
| 70 | storage_db->destroy(storage_db,NULL); |
---|
| 71 | guild_storage_db->destroy(guild_storage_db,NULL); |
---|
| 72 | } |
---|
| 73 | |
---|
| 74 | |
---|
| 75 | static int storage_reconnect_sub(DBKey key,void *data,va_list ap) |
---|
| 76 | { //Parses storage and saves 'dirty' ones upon reconnect. [Skotlex] |
---|
| 77 | int type = va_arg(ap, int); |
---|
| 78 | if (type) |
---|
| 79 | { //Guild Storage |
---|
| 80 | struct guild_storage* stor = (struct guild_storage*) data; |
---|
| 81 | if (stor->dirty && stor->storage_status == 0) //Save closed storages. |
---|
| 82 | storage_guild_storagesave(0, stor->guild_id,0); |
---|
| 83 | } |
---|
| 84 | else |
---|
| 85 | { //Account Storage |
---|
| 86 | struct storage* stor = (struct storage*) data; |
---|
| 87 | if (stor->dirty && stor->storage_status == 0) //Save closed storages. |
---|
| 88 | storage_storage_save(stor->account_id, stor->dirty==2?1:0); |
---|
| 89 | } |
---|
| 90 | return 0; |
---|
| 91 | } |
---|
| 92 | |
---|
| 93 | //Function to be invoked upon server reconnection to char. To save all 'dirty' storages [Skotlex |
---|
| 94 | void do_reconnect_storage(void) |
---|
| 95 | { |
---|
| 96 | storage_db->foreach(storage_db, storage_reconnect_sub, 0); |
---|
| 97 | guild_storage_db->foreach(guild_storage_db, storage_reconnect_sub, 1); |
---|
| 98 | } |
---|
| 99 | |
---|
| 100 | static void* create_storage(DBKey key, va_list args) |
---|
| 101 | { |
---|
| 102 | struct storage *stor; |
---|
| 103 | stor = (struct storage *) aCallocA (sizeof(struct storage), 1); |
---|
| 104 | stor->account_id = key.i; |
---|
| 105 | return stor; |
---|
| 106 | } |
---|
| 107 | struct storage *account2storage(int account_id) |
---|
| 108 | { |
---|
| 109 | return (struct storage*)idb_ensure(storage_db,account_id,create_storage); |
---|
| 110 | } |
---|
| 111 | |
---|
| 112 | // Just to ask storage, without creation |
---|
| 113 | struct storage *account2storage2(int account_id) |
---|
| 114 | { |
---|
| 115 | return (struct storage*)idb_get(storage_db, account_id); |
---|
| 116 | } |
---|
| 117 | |
---|
| 118 | int storage_delete(int account_id) |
---|
| 119 | { |
---|
| 120 | idb_remove(storage_db,account_id); |
---|
| 121 | return 0; |
---|
| 122 | } |
---|
| 123 | |
---|
| 124 | /*========================================== |
---|
| 125 | * Opens a storage. Returns: |
---|
| 126 | * 0 - success |
---|
| 127 | * 1 - fail |
---|
| 128 | * 2 - Storage requested from char-server (will open automatically later) |
---|
| 129 | *------------------------------------------*/ |
---|
| 130 | int storage_storageopen(struct map_session_data *sd) |
---|
| 131 | { |
---|
| 132 | struct storage *stor; |
---|
| 133 | nullpo_retr(0, sd); |
---|
| 134 | |
---|
| 135 | if(sd->state.storage_flag) |
---|
| 136 | return 1; //Already open? |
---|
| 137 | |
---|
| 138 | if( !pc_can_give_items(pc_isGM(sd)) ) |
---|
| 139 | { //check is this GM level is allowed to put items to storage |
---|
| 140 | clif_displaymessage(sd->fd, msg_txt(246)); |
---|
| 141 | return 1; |
---|
| 142 | } |
---|
| 143 | |
---|
| 144 | if((stor = (struct storage*)idb_get(storage_db,sd->status.account_id)) == NULL) |
---|
| 145 | { //Request storage. |
---|
| 146 | intif_request_storage(sd->status.account_id); |
---|
| 147 | return 2; |
---|
| 148 | } |
---|
| 149 | |
---|
| 150 | if (stor->storage_status) |
---|
| 151 | return 1; //Already open/player already has it open... |
---|
| 152 | |
---|
| 153 | stor->storage_status = 1; |
---|
| 154 | sd->state.storage_flag = 1; |
---|
| 155 | clif_storagelist(sd,stor); |
---|
| 156 | clif_updatestorageamount(sd,stor); |
---|
| 157 | return 0; |
---|
| 158 | } |
---|
| 159 | |
---|
| 160 | // helper function |
---|
| 161 | int compare_item(struct item *a, struct item *b) |
---|
| 162 | { |
---|
| 163 | if (a->nameid == b->nameid && |
---|
| 164 | a->identify == b->identify && |
---|
| 165 | a->refine == b->refine && |
---|
| 166 | a->attribute == b->attribute) |
---|
| 167 | { |
---|
| 168 | int i; |
---|
| 169 | for (i = 0; i < MAX_SLOTS && (a->card[i] == b->card[i]); i++); |
---|
| 170 | return (i == MAX_SLOTS); |
---|
| 171 | } |
---|
| 172 | return 0; |
---|
| 173 | } |
---|
| 174 | |
---|
| 175 | /*========================================== |
---|
| 176 | * Internal add-item function. |
---|
| 177 | *------------------------------------------*/ |
---|
| 178 | static int storage_additem(struct map_session_data *sd,struct storage *stor,struct item *item_data,int amount) |
---|
| 179 | { |
---|
| 180 | struct item_data *data; |
---|
| 181 | int i; |
---|
| 182 | |
---|
| 183 | if(item_data->nameid <= 0 || amount <= 0) |
---|
| 184 | return 1; |
---|
| 185 | |
---|
| 186 | data = itemdb_search(item_data->nameid); |
---|
| 187 | |
---|
| 188 | if (!itemdb_canstore(item_data, pc_isGM(sd))) |
---|
| 189 | { //Check if item is storable. [Skotlex] |
---|
| 190 | clif_displaymessage (sd->fd, msg_txt(264)); |
---|
| 191 | return 1; |
---|
| 192 | } |
---|
| 193 | |
---|
| 194 | if(itemdb_isstackable2(data)){ //Stackable |
---|
| 195 | for(i=0;i<MAX_STORAGE;i++){ |
---|
| 196 | if( compare_item (&stor->storage_[i], item_data)) { |
---|
| 197 | if(amount > MAX_AMOUNT - stor->storage_[i].amount) |
---|
| 198 | return 1; |
---|
| 199 | stor->storage_[i].amount+=amount; |
---|
| 200 | clif_storageitemadded(sd,stor,i,amount); |
---|
| 201 | stor->dirty = 1; |
---|
| 202 | if(log_config.enable_logs&0x800) |
---|
| 203 | log_pick_pc(sd, "R", item_data->nameid, -amount, item_data); |
---|
| 204 | return 0; |
---|
| 205 | } |
---|
| 206 | } |
---|
| 207 | } |
---|
| 208 | //Add item |
---|
| 209 | for(i=0;i<MAX_STORAGE && stor->storage_[i].nameid;i++); |
---|
| 210 | |
---|
| 211 | if(i>=MAX_STORAGE) |
---|
| 212 | return 1; |
---|
| 213 | |
---|
| 214 | memcpy(&stor->storage_[i],item_data,sizeof(stor->storage_[0])); |
---|
| 215 | stor->storage_[i].amount=amount; |
---|
| 216 | stor->storage_amount++; |
---|
| 217 | clif_storageitemadded(sd,stor,i,amount); |
---|
| 218 | clif_updatestorageamount(sd,stor); |
---|
| 219 | stor->dirty = 1; |
---|
| 220 | if(log_config.enable_logs&0x800) |
---|
| 221 | log_pick_pc(sd, "R", item_data->nameid, -amount, item_data); |
---|
| 222 | return 0; |
---|
| 223 | } |
---|
| 224 | /*========================================== |
---|
| 225 | * Internal del-item function |
---|
| 226 | *------------------------------------------*/ |
---|
| 227 | static int storage_delitem(struct map_session_data *sd,struct storage *stor,int n,int amount) |
---|
| 228 | { |
---|
| 229 | |
---|
| 230 | if(stor->storage_[n].nameid==0 || stor->storage_[n].amount<amount) |
---|
| 231 | return 1; |
---|
| 232 | |
---|
| 233 | stor->storage_[n].amount-=amount; |
---|
| 234 | if(log_config.enable_logs&0x800) |
---|
| 235 | log_pick_pc(sd, "R", stor->storage_[n].nameid, amount, &stor->storage_[n]); |
---|
| 236 | if(stor->storage_[n].amount==0){ |
---|
| 237 | memset(&stor->storage_[n],0,sizeof(stor->storage_[0])); |
---|
| 238 | stor->storage_amount--; |
---|
| 239 | clif_updatestorageamount(sd,stor); |
---|
| 240 | } |
---|
| 241 | clif_storageitemremoved(sd,n,amount); |
---|
| 242 | |
---|
| 243 | stor->dirty = 1; |
---|
| 244 | return 0; |
---|
| 245 | } |
---|
| 246 | /*========================================== |
---|
| 247 | * Add an item to the storage from the inventory. |
---|
| 248 | *------------------------------------------*/ |
---|
| 249 | int storage_storageadd(struct map_session_data *sd,int index,int amount) |
---|
| 250 | { |
---|
| 251 | struct storage *stor; |
---|
| 252 | |
---|
| 253 | nullpo_retr(0, sd); |
---|
| 254 | nullpo_retr(0, stor=account2storage2(sd->status.account_id)); |
---|
| 255 | |
---|
| 256 | if((stor->storage_amount > MAX_STORAGE) || !stor->storage_status) |
---|
| 257 | return 0; // storage full / storage closed |
---|
| 258 | |
---|
| 259 | if(index<0 || index>=MAX_INVENTORY) |
---|
| 260 | return 0; |
---|
| 261 | |
---|
| 262 | if(sd->status.inventory[index].nameid <= 0) |
---|
| 263 | return 0; //No item on that spot |
---|
| 264 | |
---|
| 265 | if(amount < 1 || amount > sd->status.inventory[index].amount) |
---|
| 266 | return 0; |
---|
| 267 | |
---|
| 268 | // log_tostorage(sd, index, 0); |
---|
| 269 | if(storage_additem(sd,stor,&sd->status.inventory[index],amount)==0) |
---|
| 270 | // remove item from inventory |
---|
| 271 | pc_delitem(sd,index,amount,0); |
---|
| 272 | |
---|
| 273 | return 1; |
---|
| 274 | } |
---|
| 275 | |
---|
| 276 | /*========================================== |
---|
| 277 | * Retrieve an item from the storage. |
---|
| 278 | *------------------------------------------*/ |
---|
| 279 | int storage_storageget(struct map_session_data *sd,int index,int amount) |
---|
| 280 | { |
---|
| 281 | struct storage *stor; |
---|
| 282 | int flag; |
---|
| 283 | |
---|
| 284 | nullpo_retr(0, sd); |
---|
| 285 | nullpo_retr(0, stor=account2storage2(sd->status.account_id)); |
---|
| 286 | |
---|
| 287 | |
---|
| 288 | if(index<0 || index>=MAX_STORAGE) |
---|
| 289 | return 0; |
---|
| 290 | |
---|
| 291 | if(stor->storage_[index].nameid <= 0) |
---|
| 292 | return 0; //Nothing there |
---|
| 293 | |
---|
| 294 | if(amount < 1 || amount > stor->storage_[index].amount) |
---|
| 295 | return 0; |
---|
| 296 | |
---|
| 297 | if((flag = pc_additem(sd,&stor->storage_[index],amount)) == 0) |
---|
| 298 | storage_delitem(sd,stor,index,amount); |
---|
| 299 | else |
---|
| 300 | clif_additem(sd,0,0,flag); |
---|
| 301 | // log_fromstorage(sd, index, 0); |
---|
| 302 | return 1; |
---|
| 303 | } |
---|
| 304 | /*========================================== |
---|
| 305 | * Move an item from cart to storage. |
---|
| 306 | *------------------------------------------*/ |
---|
| 307 | int storage_storageaddfromcart(struct map_session_data *sd,int index,int amount) |
---|
| 308 | { |
---|
| 309 | struct storage *stor; |
---|
| 310 | |
---|
| 311 | nullpo_retr(0, sd); |
---|
| 312 | nullpo_retr(0, stor=account2storage2(sd->status.account_id)); |
---|
| 313 | |
---|
| 314 | if(stor->storage_amount > MAX_STORAGE || !stor->storage_status) |
---|
| 315 | return 0; // storage full / storage closed |
---|
| 316 | |
---|
| 317 | if(index< 0 || index>=MAX_CART) |
---|
| 318 | return 0; |
---|
| 319 | |
---|
| 320 | if(sd->status.cart[index].nameid <= 0) |
---|
| 321 | return 0; //No item there. |
---|
| 322 | |
---|
| 323 | if(amount < 1 || amount > sd->status.cart[index].amount) |
---|
| 324 | return 0; |
---|
| 325 | |
---|
| 326 | if(storage_additem(sd,stor,&sd->status.cart[index],amount)==0) |
---|
| 327 | pc_cart_delitem(sd,index,amount,0); |
---|
| 328 | |
---|
| 329 | return 1; |
---|
| 330 | } |
---|
| 331 | |
---|
| 332 | /*========================================== |
---|
| 333 | * Get from Storage to the Cart |
---|
| 334 | *------------------------------------------*/ |
---|
| 335 | int storage_storagegettocart(struct map_session_data *sd,int index,int amount) |
---|
| 336 | { |
---|
| 337 | struct storage *stor; |
---|
| 338 | |
---|
| 339 | nullpo_retr(0, sd); |
---|
| 340 | nullpo_retr(0, stor=account2storage2(sd->status.account_id)); |
---|
| 341 | |
---|
| 342 | if(!stor->storage_status) |
---|
| 343 | return 0; |
---|
| 344 | |
---|
| 345 | if(index< 0 || index>=MAX_STORAGE) |
---|
| 346 | return 0; |
---|
| 347 | |
---|
| 348 | if(stor->storage_[index].nameid <= 0) |
---|
| 349 | return 0; //Nothing there. |
---|
| 350 | |
---|
| 351 | if(amount < 1 || amount > stor->storage_[index].amount) |
---|
| 352 | return 0; |
---|
| 353 | |
---|
| 354 | if(pc_cart_additem(sd,&stor->storage_[index],amount)==0) |
---|
| 355 | storage_delitem(sd,stor,index,amount); |
---|
| 356 | |
---|
| 357 | return 1; |
---|
| 358 | } |
---|
| 359 | |
---|
| 360 | |
---|
| 361 | /*========================================== |
---|
| 362 | * Modified By Valaris to save upon closing [massdriller] |
---|
| 363 | *------------------------------------------*/ |
---|
| 364 | int storage_storageclose(struct map_session_data *sd) |
---|
| 365 | { |
---|
| 366 | struct storage *stor; |
---|
| 367 | |
---|
| 368 | nullpo_retr(0, sd); |
---|
| 369 | nullpo_retr(0, stor=account2storage2(sd->status.account_id)); |
---|
| 370 | |
---|
| 371 | clif_storageclose(sd); |
---|
| 372 | if (stor->storage_status) |
---|
| 373 | { |
---|
| 374 | if (save_settings&4) |
---|
| 375 | chrif_save(sd,0); //Invokes the storage saving as well. |
---|
| 376 | else |
---|
| 377 | storage_storage_save(sd->status.account_id, 0); |
---|
| 378 | } |
---|
| 379 | stor->storage_status=0; |
---|
| 380 | sd->state.storage_flag=0; |
---|
| 381 | return 0; |
---|
| 382 | } |
---|
| 383 | |
---|
| 384 | /*========================================== |
---|
| 385 | * When quitting the game. |
---|
| 386 | *------------------------------------------*/ |
---|
| 387 | int storage_storage_quit(struct map_session_data *sd, int flag) |
---|
| 388 | { |
---|
| 389 | struct storage *stor; |
---|
| 390 | |
---|
| 391 | nullpo_retr(0, sd); |
---|
| 392 | nullpo_retr(0, stor=account2storage2(sd->status.account_id)); |
---|
| 393 | |
---|
| 394 | if (stor->storage_status) |
---|
| 395 | { |
---|
| 396 | if (save_settings&4) |
---|
| 397 | chrif_save(sd, flag); //Invokes the storage saving as well. |
---|
| 398 | else |
---|
| 399 | storage_storage_save(sd->status.account_id, flag); |
---|
| 400 | } |
---|
| 401 | stor->storage_status = 0; |
---|
| 402 | sd->state.storage_flag = 0; |
---|
| 403 | return 0; |
---|
| 404 | } |
---|
| 405 | |
---|
| 406 | void storage_storage_dirty(struct map_session_data *sd) |
---|
| 407 | { |
---|
| 408 | struct storage *stor; |
---|
| 409 | |
---|
| 410 | stor=account2storage2(sd->status.account_id); |
---|
| 411 | |
---|
| 412 | if(stor) |
---|
| 413 | stor->dirty = 1; |
---|
| 414 | } |
---|
| 415 | |
---|
| 416 | int storage_storage_save(int account_id, int final) |
---|
| 417 | { |
---|
| 418 | struct storage *stor; |
---|
| 419 | |
---|
| 420 | stor=account2storage2(account_id); |
---|
| 421 | if(!stor) return 0; |
---|
| 422 | |
---|
| 423 | if(stor->dirty) |
---|
| 424 | { |
---|
| 425 | if (final) { |
---|
| 426 | stor->dirty = 2; |
---|
| 427 | stor->storage_status = 0; //To prevent further manipulation of it. |
---|
| 428 | } |
---|
| 429 | intif_send_storage(stor); |
---|
| 430 | return 1; |
---|
| 431 | } |
---|
| 432 | if (final) |
---|
| 433 | { //Clear storage from memory. Nothing to save. |
---|
| 434 | storage_delete(account_id); |
---|
| 435 | return 1; |
---|
| 436 | } |
---|
| 437 | |
---|
| 438 | return 0; |
---|
| 439 | } |
---|
| 440 | |
---|
| 441 | //Ack from Char-server indicating the storage was saved. [Skotlex] |
---|
| 442 | int storage_storage_saved(int account_id) |
---|
| 443 | { |
---|
| 444 | struct storage *stor; |
---|
| 445 | |
---|
| 446 | if((stor=account2storage2(account_id)) == NULL) |
---|
| 447 | return 0; |
---|
| 448 | |
---|
| 449 | if (stor->dirty == 2) |
---|
| 450 | { //Final save of storage. Remove from memory. |
---|
| 451 | storage_delete(account_id); |
---|
| 452 | return 1; |
---|
| 453 | } |
---|
| 454 | |
---|
| 455 | if (stor->dirty && stor->storage_status == 0) |
---|
| 456 | { //Only mark it clean if it's not in use. [Skotlex] |
---|
| 457 | stor->dirty = 0; |
---|
| 458 | storage_sortitem(stor); |
---|
| 459 | return 1; |
---|
| 460 | } |
---|
| 461 | return 0; |
---|
| 462 | } |
---|
| 463 | |
---|
| 464 | static void* create_guildstorage(DBKey key, va_list args) |
---|
| 465 | { |
---|
| 466 | struct guild_storage *gs = NULL; |
---|
| 467 | gs = (struct guild_storage *) aCallocA(sizeof(struct guild_storage), 1); |
---|
| 468 | gs->guild_id=key.i; |
---|
| 469 | return gs; |
---|
| 470 | } |
---|
| 471 | struct guild_storage *guild2storage(int guild_id) |
---|
| 472 | { |
---|
| 473 | struct guild_storage *gs = NULL; |
---|
| 474 | if(guild_search(guild_id) != NULL) |
---|
| 475 | gs=(struct guild_storage *) idb_ensure(guild_storage_db,guild_id,create_guildstorage); |
---|
| 476 | return gs; |
---|
| 477 | } |
---|
| 478 | |
---|
| 479 | struct guild_storage *guild2storage2(int guild_id) |
---|
| 480 | { //For just locating a storage without creating one. [Skotlex] |
---|
| 481 | return (struct guild_storage*)idb_get(guild_storage_db,guild_id); |
---|
| 482 | } |
---|
| 483 | |
---|
| 484 | int guild_storage_delete(int guild_id) |
---|
| 485 | { |
---|
| 486 | idb_remove(guild_storage_db,guild_id); |
---|
| 487 | return 0; |
---|
| 488 | } |
---|
| 489 | |
---|
| 490 | int storage_guild_storageopen(struct map_session_data *sd) |
---|
| 491 | { |
---|
| 492 | struct guild_storage *gstor; |
---|
| 493 | |
---|
| 494 | nullpo_retr(0, sd); |
---|
| 495 | |
---|
| 496 | if(sd->status.guild_id <= 0) |
---|
| 497 | return 2; |
---|
| 498 | |
---|
| 499 | if(sd->state.storage_flag) |
---|
| 500 | return 1; //Can't open both storages at a time. |
---|
| 501 | |
---|
| 502 | if( !pc_can_give_items(pc_isGM(sd)) ) { //check is this GM level can open guild storage and store items [Lupus] |
---|
| 503 | clif_displaymessage(sd->fd, msg_txt(246)); |
---|
| 504 | return 1; |
---|
| 505 | } |
---|
| 506 | |
---|
| 507 | if((gstor = guild2storage2(sd->status.guild_id)) == NULL) { |
---|
| 508 | intif_request_guild_storage(sd->status.account_id,sd->status.guild_id); |
---|
| 509 | return 0; |
---|
| 510 | } |
---|
| 511 | if(gstor->storage_status) |
---|
| 512 | return 1; |
---|
| 513 | |
---|
| 514 | gstor->storage_status = 1; |
---|
| 515 | sd->state.storage_flag = 2; |
---|
| 516 | clif_guildstoragelist(sd,gstor); |
---|
| 517 | clif_updateguildstorageamount(sd,gstor); |
---|
| 518 | return 0; |
---|
| 519 | } |
---|
| 520 | |
---|
| 521 | int guild_storage_additem(struct map_session_data *sd,struct guild_storage *stor,struct item *item_data,int amount) |
---|
| 522 | { |
---|
| 523 | struct item_data *data; |
---|
| 524 | int i; |
---|
| 525 | |
---|
| 526 | nullpo_retr(1, sd); |
---|
| 527 | nullpo_retr(1, stor); |
---|
| 528 | nullpo_retr(1, item_data); |
---|
| 529 | nullpo_retr(1, data = itemdb_search(item_data->nameid)); |
---|
| 530 | |
---|
| 531 | if(item_data->nameid <= 0 || amount <= 0) |
---|
| 532 | return 1; |
---|
| 533 | |
---|
| 534 | if (!itemdb_canguildstore(item_data, pc_isGM(sd))) |
---|
| 535 | { //Check if item is storable. [Skotlex] |
---|
| 536 | clif_displaymessage (sd->fd, msg_txt(264)); |
---|
| 537 | return 1; |
---|
| 538 | } |
---|
| 539 | |
---|
| 540 | if(itemdb_isstackable2(data)){ //Stackable |
---|
| 541 | for(i=0;i<MAX_GUILD_STORAGE;i++){ |
---|
| 542 | if(compare_item(&stor->storage_[i], item_data)) { |
---|
| 543 | if(stor->storage_[i].amount+amount > MAX_AMOUNT) |
---|
| 544 | return 1; |
---|
| 545 | stor->storage_[i].amount+=amount; |
---|
| 546 | clif_guildstorageitemadded(sd,stor,i,amount); |
---|
| 547 | stor->dirty = 1; |
---|
| 548 | if(log_config.enable_logs&0x1000) |
---|
| 549 | log_pick_pc(sd, "G", item_data->nameid, -amount, item_data); |
---|
| 550 | return 0; |
---|
| 551 | } |
---|
| 552 | } |
---|
| 553 | } |
---|
| 554 | //Add item |
---|
| 555 | for(i=0;i<MAX_GUILD_STORAGE && stor->storage_[i].nameid;i++); |
---|
| 556 | |
---|
| 557 | if(i>=MAX_GUILD_STORAGE) |
---|
| 558 | return 1; |
---|
| 559 | |
---|
| 560 | memcpy(&stor->storage_[i],item_data,sizeof(stor->storage_[0])); |
---|
| 561 | stor->storage_[i].amount=amount; |
---|
| 562 | stor->storage_amount++; |
---|
| 563 | clif_guildstorageitemadded(sd,stor,i,amount); |
---|
| 564 | clif_updateguildstorageamount(sd,stor); |
---|
| 565 | stor->dirty = 1; |
---|
| 566 | if(log_config.enable_logs&0x1000) |
---|
| 567 | log_pick_pc(sd, "G", item_data->nameid, -amount, item_data); |
---|
| 568 | return 0; |
---|
| 569 | } |
---|
| 570 | |
---|
| 571 | int guild_storage_delitem(struct map_session_data *sd,struct guild_storage *stor,int n,int amount) |
---|
| 572 | { |
---|
| 573 | nullpo_retr(1, sd); |
---|
| 574 | nullpo_retr(1, stor); |
---|
| 575 | |
---|
| 576 | if(stor->storage_[n].nameid==0 || stor->storage_[n].amount<amount) |
---|
| 577 | return 1; |
---|
| 578 | |
---|
| 579 | stor->storage_[n].amount-=amount; |
---|
| 580 | if(log_config.enable_logs&0x1000) |
---|
| 581 | log_pick_pc(sd, "G", stor->storage_[n].nameid, amount, &stor->storage_[n]); |
---|
| 582 | if(stor->storage_[n].amount==0){ |
---|
| 583 | memset(&stor->storage_[n],0,sizeof(stor->storage_[0])); |
---|
| 584 | stor->storage_amount--; |
---|
| 585 | clif_updateguildstorageamount(sd,stor); |
---|
| 586 | } |
---|
| 587 | clif_storageitemremoved(sd,n,amount); |
---|
| 588 | stor->dirty = 1; |
---|
| 589 | return 0; |
---|
| 590 | } |
---|
| 591 | |
---|
| 592 | int storage_guild_storageadd(struct map_session_data *sd,int index,int amount) |
---|
| 593 | { |
---|
| 594 | struct guild_storage *stor; |
---|
| 595 | |
---|
| 596 | nullpo_retr(0, sd); |
---|
| 597 | nullpo_retr(0, stor=guild2storage2(sd->status.guild_id)); |
---|
| 598 | |
---|
| 599 | if (!stor->storage_status || stor->storage_amount > MAX_GUILD_STORAGE) |
---|
| 600 | return 0; |
---|
| 601 | |
---|
| 602 | if(index<0 || index>=MAX_INVENTORY) |
---|
| 603 | return 0; |
---|
| 604 | |
---|
| 605 | if(sd->status.inventory[index].nameid <= 0) |
---|
| 606 | return 0; |
---|
| 607 | |
---|
| 608 | if(amount < 1 || amount > sd->status.inventory[index].amount) |
---|
| 609 | return 0; |
---|
| 610 | |
---|
| 611 | // log_tostorage(sd, index, 1); |
---|
| 612 | if(guild_storage_additem(sd,stor,&sd->status.inventory[index],amount)==0) |
---|
| 613 | pc_delitem(sd,index,amount,0); |
---|
| 614 | |
---|
| 615 | return 1; |
---|
| 616 | } |
---|
| 617 | |
---|
| 618 | int storage_guild_storageget(struct map_session_data *sd,int index,int amount) |
---|
| 619 | { |
---|
| 620 | struct guild_storage *stor; |
---|
| 621 | int flag; |
---|
| 622 | |
---|
| 623 | nullpo_retr(0, sd); |
---|
| 624 | nullpo_retr(0, stor=guild2storage2(sd->status.guild_id)); |
---|
| 625 | |
---|
| 626 | if(!stor->storage_status) |
---|
| 627 | return 0; |
---|
| 628 | |
---|
| 629 | if(index<0 || index>=MAX_GUILD_STORAGE) |
---|
| 630 | return 0; |
---|
| 631 | |
---|
| 632 | if(stor->storage_[index].nameid <= 0) |
---|
| 633 | return 0; |
---|
| 634 | |
---|
| 635 | if(amount < 1 || amount > stor->storage_[index].amount) |
---|
| 636 | return 0; |
---|
| 637 | |
---|
| 638 | if((flag = pc_additem(sd,&stor->storage_[index],amount)) == 0) |
---|
| 639 | guild_storage_delitem(sd,stor,index,amount); |
---|
| 640 | else |
---|
| 641 | clif_additem(sd,0,0,flag); |
---|
| 642 | // log_fromstorage(sd, index, 1); |
---|
| 643 | |
---|
| 644 | return 0; |
---|
| 645 | } |
---|
| 646 | |
---|
| 647 | int storage_guild_storageaddfromcart(struct map_session_data *sd,int index,int amount) |
---|
| 648 | { |
---|
| 649 | struct guild_storage *stor; |
---|
| 650 | |
---|
| 651 | nullpo_retr(0, sd); |
---|
| 652 | nullpo_retr(0, stor=guild2storage2(sd->status.guild_id)); |
---|
| 653 | |
---|
| 654 | if(!stor->storage_status || stor->storage_amount > MAX_GUILD_STORAGE) |
---|
| 655 | return 0; |
---|
| 656 | |
---|
| 657 | if(index<0 || index>=MAX_CART) |
---|
| 658 | return 0; |
---|
| 659 | |
---|
| 660 | if(sd->status.cart[index].nameid <= 0) |
---|
| 661 | return 0; |
---|
| 662 | |
---|
| 663 | if(amount < 1 || amount > sd->status.cart[index].amount) |
---|
| 664 | return 0; |
---|
| 665 | |
---|
| 666 | if(guild_storage_additem(sd,stor,&sd->status.cart[index],amount)==0) |
---|
| 667 | pc_cart_delitem(sd,index,amount,0); |
---|
| 668 | |
---|
| 669 | return 1; |
---|
| 670 | } |
---|
| 671 | |
---|
| 672 | int storage_guild_storagegettocart(struct map_session_data *sd,int index,int amount) |
---|
| 673 | { |
---|
| 674 | struct guild_storage *stor; |
---|
| 675 | |
---|
| 676 | nullpo_retr(0, sd); |
---|
| 677 | nullpo_retr(0, stor=guild2storage2(sd->status.guild_id)); |
---|
| 678 | |
---|
| 679 | if(!stor->storage_status) |
---|
| 680 | return 0; |
---|
| 681 | |
---|
| 682 | if(index<0 || index>=MAX_GUILD_STORAGE) |
---|
| 683 | return 0; |
---|
| 684 | |
---|
| 685 | if(stor->storage_[index].nameid<=0) |
---|
| 686 | return 0; |
---|
| 687 | |
---|
| 688 | if(amount < 1 || amount > stor->storage_[index].amount) |
---|
| 689 | return 0; |
---|
| 690 | |
---|
| 691 | if(pc_cart_additem(sd,&stor->storage_[index],amount)==0) |
---|
| 692 | guild_storage_delitem(sd,stor,index,amount); |
---|
| 693 | |
---|
| 694 | return 1; |
---|
| 695 | } |
---|
| 696 | |
---|
| 697 | int storage_guild_storagesave(int account_id, int guild_id, int flag) |
---|
| 698 | { |
---|
| 699 | struct guild_storage *stor = guild2storage2(guild_id); |
---|
| 700 | |
---|
| 701 | if(stor) |
---|
| 702 | { |
---|
| 703 | if (flag) //Char quitting, close it. |
---|
| 704 | stor->storage_status = 0; |
---|
| 705 | if (stor->dirty) |
---|
| 706 | intif_send_guild_storage(account_id,stor); |
---|
| 707 | return 1; |
---|
| 708 | } |
---|
| 709 | return 0; |
---|
| 710 | } |
---|
| 711 | |
---|
| 712 | int storage_guild_storagesaved(int guild_id) |
---|
| 713 | { |
---|
| 714 | struct guild_storage *stor; |
---|
| 715 | |
---|
| 716 | if((stor=guild2storage2(guild_id)) != NULL) { |
---|
| 717 | if (stor->dirty && stor->storage_status == 0) |
---|
| 718 | { //Storage has been correctly saved. |
---|
| 719 | stor->dirty = 0; |
---|
| 720 | storage_gsortitem(stor); |
---|
| 721 | } |
---|
| 722 | return 1; |
---|
| 723 | } |
---|
| 724 | return 0; |
---|
| 725 | } |
---|
| 726 | |
---|
| 727 | int storage_guild_storageclose(struct map_session_data *sd) |
---|
| 728 | { |
---|
| 729 | struct guild_storage *stor; |
---|
| 730 | |
---|
| 731 | nullpo_retr(0, sd); |
---|
| 732 | nullpo_retr(0, stor=guild2storage2(sd->status.guild_id)); |
---|
| 733 | |
---|
| 734 | clif_storageclose(sd); |
---|
| 735 | if (stor->storage_status) |
---|
| 736 | { |
---|
| 737 | if (save_settings&4) |
---|
| 738 | chrif_save(sd, 0); //This one also saves the storage. [Skotlex] |
---|
| 739 | else |
---|
| 740 | storage_guild_storagesave(sd->status.account_id, sd->status.guild_id,0); |
---|
| 741 | stor->storage_status=0; |
---|
| 742 | } |
---|
| 743 | sd->state.storage_flag = 0; |
---|
| 744 | |
---|
| 745 | return 0; |
---|
| 746 | } |
---|
| 747 | |
---|
| 748 | int storage_guild_storage_quit(struct map_session_data *sd,int flag) |
---|
| 749 | { |
---|
| 750 | struct guild_storage *stor; |
---|
| 751 | |
---|
| 752 | nullpo_retr(0, sd); |
---|
| 753 | nullpo_retr(0, stor=guild2storage2(sd->status.guild_id)); |
---|
| 754 | |
---|
| 755 | if(flag) |
---|
| 756 | { //Only during a guild break flag is 1 (don't save storage) |
---|
| 757 | sd->state.storage_flag = 0; |
---|
| 758 | stor->storage_status = 0; |
---|
| 759 | clif_storageclose(sd); |
---|
| 760 | if (save_settings&4) |
---|
| 761 | chrif_save(sd,0); |
---|
| 762 | return 0; |
---|
| 763 | } |
---|
| 764 | |
---|
| 765 | if(stor->storage_status) { |
---|
| 766 | if (save_settings&4) |
---|
| 767 | chrif_save(sd,0); |
---|
| 768 | else |
---|
| 769 | storage_guild_storagesave(sd->status.account_id,sd->status.guild_id,1); |
---|
| 770 | } |
---|
| 771 | sd->state.storage_flag = 0; |
---|
| 772 | stor->storage_status = 0; |
---|
| 773 | |
---|
| 774 | return 0; |
---|
| 775 | } |
---|