storage.c 19 KB

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