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 | } |
---|