root/src/map/guild.c @ 22

Revision 1, 51.6 kB (checked in by jinshiro, 17 years ago)
Line 
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/timer.h"
6#include "../common/nullpo.h"
7#include "../common/malloc.h"
8#include "../common/mapindex.h"
9#include "../common/showmsg.h"
10#include "../common/ers.h"
11#include "../common/strlib.h"
12#include "../common/utils.h"
13
14#include "map.h"
15#include "guild.h"
16#include "storage.h"
17#include "battle.h"
18#include "npc.h"
19#include "pc.h"
20#include "status.h"
21#include "mob.h"
22#include "intif.h"
23#include "clif.h"
24#include "skill.h"
25#include "log.h"
26
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30
31
32static DBMap* guild_db; // int guild_id -> struct guild*
33static DBMap* castle_db; // int castle_id -> struct guild_castle*
34static DBMap* guild_expcache_db; // int char_id -> struct guild_expcache*
35static DBMap* guild_infoevent_db; // int guild_id -> struct eventlist*
36static DBMap* guild_castleinfoevent_db; // int castle_id_index -> struct eventlist*
37
38struct eventlist {
39        char name[50];
40        struct eventlist *next;
41};
42
43// ƒMƒ‹ƒh‚ÌEXPƒLƒƒƒbƒVƒ…‚̃tƒ‰ƒbƒVƒ…‚ÉŠÖ˜A‚·‚é’萔
44#define GUILD_SEND_XY_INVERVAL  5000    // À•W‚â‚g‚o‘—M‚ÌŠÔŠu
45#define GUILD_PAYEXP_INVERVAL 10000     // ŠÔŠu(ƒLƒƒƒbƒVƒ…‚̍ő吶‘¶ŽžŠÔAƒ~ƒŠ•b)
46#define GUILD_PAYEXP_LIST 8192  // ƒLƒƒƒbƒVƒ…‚̍ő吔
47
48// ƒMƒ‹ƒh‚ÌEXPƒLƒƒƒbƒVƒ…
49struct guild_expcache {
50        int guild_id, account_id, char_id;
51        unsigned int exp;
52};
53static struct eri *expcache_ers; //For handling of guild exp payment.
54
55struct{
56        int id;
57        int max;
58        struct{
59                short id;
60                short lv;
61        }need[6];
62} guild_skill_tree[MAX_GUILDSKILL];
63
64// timer for auto saving guild data during WoE
65#define GUILD_SAVE_INTERVAL 300000
66int guild_save_timer = -1;
67
68int guild_payexp_timer(int tid, unsigned int tick, int id, intptr data);
69int guild_save_sub(int tid, unsigned int tick, int id, intptr data);
70static int guild_send_xy_timer(int tid, unsigned int tick, int id, intptr data);
71
72/*==========================================
73 * Retrieves and validates the sd pointer for this guild member [Skotlex]
74 *------------------------------------------*/
75static TBL_PC* guild_sd_check(int guild_id, int account_id, int char_id)
76{
77        TBL_PC* sd = map_id2sd(account_id);
78
79        if (!(sd && sd->status.char_id == char_id))
80                return NULL;
81
82        if (sd->status.guild_id != guild_id)
83        {       //If player belongs to a different guild, kick him out.
84                intif_guild_leave(guild_id,account_id,char_id,0,"** Guild Mismatch **");
85                return NULL;
86        }
87
88        return sd;
89}
90
91 // Modified [Komurka]
92int guild_skill_get_max (int id)
93{
94        if (id < GD_SKILLBASE || id >= GD_SKILLBASE+MAX_GUILDSKILL)
95                return 0;
96        return guild_skill_tree[id-GD_SKILLBASE].max;
97}
98
99// ƒMƒ‹ƒhƒXƒLƒ‹‚ª‚ ‚é‚©Šm”F
100int guild_checkskill(struct guild *g,int id)
101{
102        int idx = id-GD_SKILLBASE;
103        if (idx < 0 || idx >= MAX_GUILDSKILL)
104                return 0;
105        return g->skill[idx].lv;
106}
107
108/*==========================================
109 * guild_skill_tree.txt reading - from jA [Komurka]
110 *------------------------------------------*/
111int guild_read_guildskill_tree_db(void)
112{
113        int i,k,id=0,ln=0;
114        FILE *fp;
115        char line[1024],*p;
116
117        memset(guild_skill_tree,0,sizeof(guild_skill_tree));
118        sprintf(line, "%s/guild_skill_tree.txt", db_path);
119        if( (fp=fopen(line,"r"))==NULL){
120                ShowError("can't read %s\n", line);
121                return -1;
122        }
123        while(fgets(line, sizeof(line), fp))
124        {
125                char *split[50];
126                if(line[0]=='/' && line[1]=='/')
127                        continue;
128                for(i=0,p=line;i<12 && p;i++){
129                        split[i]=p;
130                        p=strchr(p,',');
131                        if(p) *p++=0;
132                }
133                if(i<12)
134                        continue;
135                id = atoi(split[0]) - GD_SKILLBASE;
136                if(id<0 || id>=MAX_GUILDSKILL)
137                        continue;
138                guild_skill_tree[id].id=atoi(split[0]);
139                guild_skill_tree[id].max=atoi(split[1]);
140                if (guild_skill_tree[id].id==GD_GLORYGUILD && battle_config.require_glory_guild && guild_skill_tree[id].max==0) guild_skill_tree[id].max=1;
141                for(k=0;k<5;k++){
142                        guild_skill_tree[id].need[k].id=atoi(split[k*2+2]);
143                        guild_skill_tree[id].need[k].lv=atoi(split[k*2+3]);
144                }
145        ln++;
146        }
147        fclose(fp);
148        ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,"guild_skill_tree.txt");
149
150        return 0;
151}
152
153/*==========================================
154 * Guild skill check - from jA [Komurka]
155 *------------------------------------------*/
156int guild_check_skill_require(struct guild *g,int id)
157{
158        int i;
159        int idx = id-GD_SKILLBASE;
160
161        if(g == NULL)
162                return 0;
163
164        if (idx < 0 || idx >= MAX_GUILDSKILL)
165                return 0;
166
167        for(i=0;i<5;i++)
168        {
169                if(guild_skill_tree[idx].need[i].id == 0) break;
170                if(guild_skill_tree[idx].need[i].lv > guild_checkskill(g,guild_skill_tree[idx].need[i].id))
171                        return 0;
172        }
173        return 1;
174}
175
176static int guild_read_castledb(void)
177{
178        FILE *fp;
179        char line[1024];
180        int j,ln=0;
181        char *str[32],*p;
182        struct guild_castle *gc;
183
184        sprintf(line, "%s/castle_db.txt", db_path);
185        if( (fp=fopen(line,"r"))==NULL){
186                ShowError("can't read %s\n", line);
187                return -1;
188        }
189
190        while(fgets(line, sizeof(line), fp))
191        {
192                if(line[0]=='/' && line[1]=='/')
193                        continue;
194                memset(str,0,sizeof(str));
195                for(j=0,p=line;j<6 && p;j++){
196                        str[j]=p;
197                        p=strchr(p,',');
198                        if(p) *p++=0;
199                }
200                if (j < 4) //Insufficient data for castle. [Skotlex]
201                {
202                        ShowError("castle_db.txt: invalid line '%s'\n", line);
203                        continue;
204                }
205
206                gc=(struct guild_castle *)aCalloc(1,sizeof(struct guild_castle));
207                gc->castle_id=atoi(str[0]);
208                gc->mapindex = mapindex_name2id(str[1]);
209                safestrncpy(gc->castle_name,str[2],NAME_LENGTH);
210                safestrncpy(gc->castle_event,str[3],NAME_LENGTH);
211
212                idb_put(castle_db,gc->castle_id,gc);
213
214                //intif_guild_castle_info(gc->castle_id);
215
216                ln++;
217        }
218        fclose(fp);
219        ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",ln,"castle_db.txt");
220        return 0;
221}
222
223/// lookup: guild id -> guild*
224struct guild* guild_search(int guild_id)
225{
226        return (struct guild*)idb_get(guild_db,guild_id);
227}
228
229/// lookup: guild name -> guild*
230struct guild* guild_searchname(char* str)
231{
232        struct guild* g;
233
234        DBIterator* iter = guild_db->iterator(guild_db);
235        for( g = (struct guild*)iter->first(iter,NULL); iter->exists(iter); g = (struct guild*)iter->next(iter,NULL) )
236        {
237                if( strcmpi(g->name, str) == 0 )
238                        break;
239        }
240        iter->destroy(iter);
241
242        return g;
243}
244
245/// lookup: castle id -> castle*
246struct guild_castle* guild_castle_search(int gcid)
247{
248        return (struct guild_castle*)idb_get(castle_db,gcid);
249}
250
251/// lookup: map index -> castle*
252struct guild_castle* guild_mapindex2gc(short mapindex)
253{
254        struct guild_castle* gc;
255
256        DBIterator* iter = castle_db->iterator(castle_db);
257        for( gc = (struct guild_castle*)iter->first(iter,NULL); iter->exists(iter); gc = (struct guild_castle*)iter->next(iter,NULL) )
258        {
259                if( gc->mapindex == mapindex )
260                        break;
261        }
262        iter->destroy(iter);
263
264        return gc;
265}
266
267/// lookup: map name -> castle*
268struct guild_castle* guild_mapname2gc(const char* mapname)
269{
270        return guild_mapindex2gc(mapindex_name2id(mapname));
271}
272
273struct map_session_data* guild_getavailablesd(struct guild* g)
274{
275        int i;
276
277        nullpo_retr(NULL, g);
278
279        ARR_FIND( 0, g->max_member, i, g->member[i].sd != NULL );
280        return( i < g->max_member ) ? g->member[i].sd : NULL;
281}
282
283/// lookup: player AID/CID -> member index
284int guild_getindex(struct guild *g,int account_id,int char_id)
285{
286        int i;
287
288        if( g == NULL )
289                return -1;
290
291        ARR_FIND( 0, g->max_member, i, g->member[i].account_id == account_id && g->member[i].char_id == char_id );
292        return( i < g->max_member ) ? i : -1;
293}
294
295/// lookup: player sd -> member position
296int guild_getposition(struct guild* g, struct map_session_data* sd)
297{
298        int i;
299
300        if( g == NULL && (g=guild_search(sd->status.guild_id)) == NULL )
301                return -1;
302       
303        ARR_FIND( 0, g->max_member, i, g->member[i].account_id == sd->status.account_id && g->member[i].char_id == sd->status.char_id );
304        return( i < g->max_member ) ? g->member[i].position : -1;
305}
306
307// ƒƒ“ƒo[î•ñ‚̍쐬
308void guild_makemember(struct guild_member *m,struct map_session_data *sd)
309{
310        nullpo_retv(sd);
311
312        memset(m,0,sizeof(struct guild_member));
313        m->account_id   =sd->status.account_id;
314        m->char_id              =sd->status.char_id;
315        m->hair                 =sd->status.hair;
316        m->hair_color   =sd->status.hair_color;
317        m->gender               =sd->status.sex;
318        m->class_               =sd->status.class_;
319        m->lv                   =sd->status.base_level;
320//      m->exp                  =0;
321//      m->exp_payper   =0;
322        m->online               =1;
323        m->position             =MAX_GUILDPOSITION-1;
324        memcpy(m->name,sd->status.name,NAME_LENGTH);
325        return;
326}
327
328// ƒMƒ‹ƒh‚ÌEXPƒLƒƒƒbƒVƒ…‚ðinterŽI‚Ƀtƒ‰ƒbƒVƒ…‚·‚é
329int guild_payexp_timer_sub(DBKey dataid, void *data, va_list ap)
330{
331        int i;
332        struct guild_expcache *c;
333        struct guild *g;
334
335        c = (struct guild_expcache *)data;
336       
337        if (
338                (g = guild_search(c->guild_id)) == NULL ||
339                (i = guild_getindex(g, c->account_id, c->char_id)) < 0
340        ) {
341                ers_free(expcache_ers, data);
342                return 0;
343        }
344
345        if (g->member[i].exp > UINT_MAX - c->exp)
346                g->member[i].exp = UINT_MAX;
347        else
348                g->member[i].exp+= c->exp;
349
350        intif_guild_change_memberinfo(g->guild_id,c->account_id,c->char_id,
351                GMI_EXP,&g->member[i].exp,sizeof(g->member[i].exp));
352        c->exp=0;
353
354        ers_free(expcache_ers, data);
355        return 0;
356}
357
358int guild_payexp_timer(int tid, unsigned int tick, int id, intptr data)
359{
360        guild_expcache_db->clear(guild_expcache_db,guild_payexp_timer_sub);
361        return 0;
362}
363
364//Taken from party_send_xy_timer_sub. [Skotlex]
365int guild_send_xy_timer_sub(DBKey key,void *data,va_list ap)
366{
367        struct guild *g=(struct guild *)data;
368        int i;
369
370        nullpo_retr(0, g);
371
372        for(i=0;i<g->max_member;i++){
373                struct map_session_data *sd;
374                if((sd=g->member[i].sd)!=NULL){
375                        if(sd->guild_x!=sd->bl.x || sd->guild_y!=sd->bl.y){
376                                clif_guild_xy(sd);
377                                sd->guild_x=sd->bl.x;
378                                sd->guild_y=sd->bl.y;
379                        }
380                }
381        }
382        return 0;
383}
384
385//Code from party_send_xy_timer [Skotlex]
386static int guild_send_xy_timer(int tid, unsigned int tick, int id, intptr data)
387{
388        guild_db->foreach(guild_db,guild_send_xy_timer_sub,tick);
389        return 0;
390}
391
392int guild_send_dot_remove(struct map_session_data *sd)
393{
394        if (sd->status.guild_id)
395                clif_guild_xy_remove(sd);
396        return 0;
397}
398//------------------------------------------------------------------------
399
400int guild_create(struct map_session_data *sd, const char *name)
401{
402        char tname[NAME_LENGTH];
403        struct guild_member m;
404        nullpo_retr(0, sd);
405
406        safestrncpy(tname, name, NAME_LENGTH);
407        if( strlen(trim(tname)) == 0 )
408                return 0; // empty name
409
410        if( sd->status.guild_id )
411        {// already in a guild
412                clif_guild_created(sd,1);
413                return 0;
414        }
415        if( battle_config.guild_emperium_check && pc_search_inventory(sd,714) == -1 )
416        {// item required
417                clif_guild_created(sd,3);
418                return 0;
419        }
420
421        guild_makemember(&m,sd);
422        m.position=0;
423        intif_guild_create(name,&m);
424        return 1;
425}
426
427// ì¬‰Â”Û
428int guild_created(int account_id,int guild_id)
429{
430        struct map_session_data *sd=map_id2sd(account_id);
431
432        if(sd==NULL)
433                return 0;
434        if(!guild_id) {
435                clif_guild_created(sd,2);       // ì¬Žž”si“¯–ŒƒMƒ‹ƒh‘¶Ýj
436                return 0;
437        }
438        //struct guild *g;
439        sd->status.guild_id=guild_id;
440        clif_guild_created(sd,0);
441        if(battle_config.guild_emperium_check)
442                pc_delitem(sd,pc_search_inventory(sd,714),1,0); // ƒGƒ“ƒyƒŠƒEƒ€Á–Õ
443        return 0;
444}
445
446// î•ñ—v‹
447int guild_request_info(int guild_id)
448{
449        return intif_guild_request_info(guild_id);
450}
451
452// ƒCƒxƒ“ƒg•t‚«î•ñ—v‹
453int guild_npc_request_info(int guild_id,const char *event)
454{
455        if( guild_search(guild_id) )
456        {
457                if( event && *event )
458                        npc_event_do(event);
459
460                return 0;
461        }
462
463        if( event && *event )
464        {
465                struct eventlist* ev;
466                ev=(struct eventlist *)aCalloc(sizeof(struct eventlist),1);
467                memcpy(ev->name,event,strlen(event));
468                //The one in the db becomes the next event from this.
469                ev->next = (struct eventlist*)idb_put(guild_infoevent_db,guild_id,ev);
470        }
471
472        return guild_request_info(guild_id);
473}
474
475// Š‘®ƒLƒƒƒ‰‚ÌŠm”F
476int guild_check_member(struct guild *g)
477{
478        int i;
479        struct map_session_data *sd;
480        struct s_mapiterator* iter;
481
482        nullpo_retr(0, g);
483
484        iter = mapit_getallusers();
485        for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) )
486        {
487                if( sd->status.guild_id != g->guild_id )
488                        continue;
489
490                i = guild_getindex(g,sd->status.account_id,sd->status.char_id);
491                if (i < 0) {
492                        sd->status.guild_id=0;
493                        sd->guild_emblem_id=0;
494                        ShowWarning("guild: check_member %d[%s] is not member\n",sd->status.account_id,sd->status.name);
495                }
496        }
497        mapit_free(iter);
498
499        return 0;
500}
501
502// î•ñŠ“ŸŽž”si‚»‚ÌID‚̃Lƒƒƒ‰‚ð‘S•”–¢Š‘®‚É‚·‚éj
503int guild_recv_noinfo(int guild_id)
504{
505        struct map_session_data *sd;
506        struct s_mapiterator* iter;
507
508        iter = mapit_getallusers();
509        for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) )
510        {
511                if( sd->status.guild_id == guild_id )
512                        sd->status.guild_id = 0; // erase guild
513        }
514        mapit_free(iter);
515
516        return 0;
517}
518
519// î•ñŠ“Ÿ
520int guild_recv_info(struct guild *sg)
521{
522        struct guild *g,before;
523        int i,bm,m;
524        struct eventlist *ev,*ev2;
525        struct map_session_data *sd;
526        bool guild_new = false;
527
528        nullpo_retr(0, sg);
529
530        if((g = (struct guild*)idb_get(guild_db,sg->guild_id))==NULL)
531        {
532                guild_new = true;
533                g=(struct guild *)aCalloc(1,sizeof(struct guild));
534                idb_put(guild_db,sg->guild_id,g);
535                before=*sg;
536
537                // Å‰‚̃[ƒh‚Ȃ̂ц[ƒU[‚̃`ƒFƒbƒN‚ðs‚€
538                guild_check_member(sg);
539                if ((sd = map_nick2sd(sg->master)) != NULL)
540                {
541                        //If the guild master is online the first time the guild_info is received,
542                        //that means he was the first to join, so apply guild skill blocking here.
543                        if( battle_config.guild_skill_relog_delay )
544                                guild_block_skill(sd, 300000);
545
546                        //Also set the guild master flag.
547                        sd->state.gmaster_flag = g;
548                        clif_charnameupdate(sd); // [LuzZza]
549                        clif_guild_masterormember(sd);
550                }
551        }else
552                before=*g;
553        memcpy(g,sg,sizeof(struct guild));
554
555        if(g->max_member > MAX_GUILD)
556        {
557                ShowError("guild_recv_info: Received guild with %d members, but MAX_GUILD is only %d. Extra guild-members have been lost!\n", g->max_member, MAX_GUILD);
558                g->max_member = MAX_GUILD;
559        }
560       
561        for(i=bm=m=0;i<g->max_member;i++){
562                if(g->member[i].account_id>0){
563                        sd = g->member[i].sd = guild_sd_check(g->guild_id, g->member[i].account_id, g->member[i].char_id);
564                        if (sd) clif_charnameupdate(sd); // [LuzZza]
565                        m++;
566                }else
567                        g->member[i].sd=NULL;
568                if(before.member[i].account_id>0)
569                        bm++;
570        }
571
572        for(i=0;i<g->max_member;i++){   // î•ñ‚Ì‘—M
573                sd = g->member[i].sd;
574                if( sd==NULL )
575                        continue;
576
577                if(     before.guild_lv!=g->guild_lv || bm!=m ||
578                        before.max_member!=g->max_member ){
579                        clif_guild_basicinfo(sd);       // Šî–{î•ñ‘—M
580                        clif_guild_emblem(sd,g);        // ƒGƒ“ƒuƒŒƒ€‘—M
581                }
582
583                if(bm!=m){              // ƒƒ“ƒo[î•ñ‘—M
584                        clif_guild_memberlist(g->member[i].sd);
585                }
586
587                if( before.skill_point!=g->skill_point)
588                        clif_guild_skillinfo(sd);       // ƒXƒLƒ‹î•ñ‘—M
589
590                if( guild_new ){        // –¢‘—M‚Ȃ珊‘®î•ñ‚à‘—‚é
591                        clif_guild_belonginfo(sd,g);
592                        clif_guild_notice(sd,g);
593                        sd->guild_emblem_id=g->emblem_id;
594                }
595        }
596
597        // ƒCƒxƒ“ƒg‚Ì”­¶
598        if( (ev = (struct eventlist*)idb_remove(guild_infoevent_db,sg->guild_id))!=NULL )
599        {
600                while(ev){
601                        npc_event_do(ev->name);
602                        ev2=ev->next;
603                        aFree(ev);
604                        ev=ev2;
605                }
606        }
607
608        return 0;
609}
610
611
612// ƒMƒ‹ƒh‚Ö‚ÌŠ©—U
613int guild_invite(struct map_session_data *sd,struct map_session_data *tsd)
614{
615        struct guild *g;
616        int i;
617
618        nullpo_retr(0, sd);
619
620        g=guild_search(sd->status.guild_id);
621
622        if(tsd==NULL || g==NULL)
623                return 0;
624
625        if( (i=guild_getposition(g,sd))<0 || !(g->position[i].mode&0x0001) )
626                return 0; //Invite permission.
627
628        if(!battle_config.invite_request_check) {
629                if (tsd->party_invite>0 || tsd->trade_partner || tsd->adopt_invite ) {  // ‘ŠŽè‚ªŽæˆø’†‚©‚Ç‚€‚©
630                        clif_guild_inviteack(sd,0);
631                        return 0;
632                }
633        }
634       
635        if (!tsd->fd) { //You can't invite someone who has already disconnected.
636                clif_guild_inviteack(sd,1);
637                return 0;
638        }
639
640        if(tsd->status.guild_id>0 ||
641                tsd->guild_invite>0 ||
642                (agit_flag && map[tsd->bl.m].flag.gvg_castle))
643        {       //Can't invite people inside castles. [Skotlex]
644                clif_guild_inviteack(sd,0);
645                return 0;
646        }
647
648        // ’èˆõŠm”F
649        ARR_FIND( 0, g->max_member, i, g->member[i].account_id == 0 );
650        if(i==g->max_member){
651                clif_guild_inviteack(sd,3);
652                return 0;
653        }
654
655        tsd->guild_invite=sd->status.guild_id;
656        tsd->guild_invite_account=sd->status.account_id;
657
658        clif_guild_invite(tsd,g);
659        return 0;
660}
661
662/// Guild invitation reply.
663/// flag: 0:rejected, 1:accepted
664int guild_reply_invite(struct map_session_data* sd, int guild_id, int flag)
665{
666        struct map_session_data* tsd;
667
668        nullpo_retr(0, sd);
669
670        // subsequent requests may override the value
671        if( sd->guild_invite != guild_id )
672                return 0; // mismatch
673
674        // look up the person who sent the invite
675        //NOTE: this can be NULL because the person might have logged off in the meantime
676        tsd = map_id2sd(sd->guild_invite_account);
677
678        if( flag == 0 )
679        {// rejected
680                sd->guild_invite = 0;
681                sd->guild_invite_account = 0;
682                if( tsd ) clif_guild_inviteack(tsd,1);
683        }
684        else
685        {// accepted
686                struct guild_member m;
687                struct guild* g;
688                int i;
689
690                if( (g=guild_search(guild_id)) == NULL )
691                {
692                        sd->guild_invite = 0;
693                        sd->guild_invite_account = 0;
694                        return 0;
695                }
696
697                ARR_FIND( 0, g->max_member, i, g->member[i].account_id == 0 );
698                if( i == g->max_member )
699                {
700                        sd->guild_invite = 0;
701                        sd->guild_invite_account = 0;
702                        if( tsd ) clif_guild_inviteack(tsd,3);
703                        return 0;
704                }
705
706                guild_makemember(&m,sd);
707                intif_guild_addmember(guild_id, &m);
708                //TODO: send a minimap update to this player
709        }
710
711        return 0;
712}
713
714//Invoked when a player joins.
715//- If guild is not in memory, it is requested
716//- Otherwise sd pointer is set up.
717//- Player must be authed and must belong to a guild before invoking this method
718void guild_member_joined(struct map_session_data *sd)
719{
720        struct guild* g;
721        int i;
722        g=guild_search(sd->status.guild_id);
723        if (!g) {
724                guild_request_info(sd->status.guild_id);
725                return;
726        }
727        if (strcmp(sd->status.name,g->master) == 0)
728        {       // set the Guild Master flag
729                sd->state.gmaster_flag = g;
730                // prevent Guild Skills from being used directly after relog
731                if( battle_config.guild_skill_relog_delay )
732                        guild_block_skill(sd, 300000);
733        }
734        i = guild_getindex(g, sd->status.account_id, sd->status.char_id);
735        if (i == -1)
736                sd->status.guild_id = 0;
737        else
738                g->member[i].sd = sd;
739}
740
741// ƒMƒ‹ƒhƒƒ“ƒo‚ª’ljÁ‚³‚ꂜ
742int guild_member_added(int guild_id,int account_id,int char_id,int flag)
743{
744        struct map_session_data *sd= map_id2sd(account_id),*sd2;
745        struct guild *g;
746
747        if( (g=guild_search(guild_id))==NULL )
748                return 0;
749
750        if(sd==NULL || sd->guild_invite==0){
751                // ƒLƒƒƒ‰‘€‚É“o˜^‚Å‚«‚È‚©‚Á‚œ‚œ‚ß’E‘Þ—v‹‚ðo‚·
752                if (flag == 0) {
753                        ShowError("guild: member added error %d is not online\n",account_id);
754                        intif_guild_leave(guild_id,account_id,char_id,0,"** Data Error **");
755                }
756                return 0;
757        }
758        sd2 = map_id2sd(sd->guild_invite_account);
759        sd->guild_invite = 0;
760        sd->guild_invite_account = 0;
761
762        if(flag==1){    // Žž”s
763                if( sd2!=NULL )
764                        clif_guild_inviteack(sd2,3);
765                return 0;
766        }
767
768                // ¬Œ÷
769        sd->status.guild_id = g->guild_id;
770        sd->guild_emblem_id = g->emblem_id;
771        //Packets which were sent in the previous 'guild_sent' implementation.
772        clif_guild_belonginfo(sd,g);
773        clif_guild_notice(sd,g);
774
775        //TODO: send new emblem info to others
776
777        if( sd2!=NULL )
778                clif_guild_inviteack(sd2,2);
779
780        //Next line commented because it do nothing, look at guild_recv_info [LuzZza]
781        //clif_charnameupdate(sd); //Update display name [Skotlex]
782
783        return 0;
784}
785
786// ƒMƒ‹ƒh’E‘Þ—v‹
787int guild_leave(struct map_session_data* sd, int guild_id, int account_id, int char_id, const char* mes)
788{
789        struct guild *g;
790
791        nullpo_retr(0, sd);
792
793        g = guild_search(sd->status.guild_id);
794
795        if(g==NULL)
796                return 0;
797
798        if(sd->status.account_id!=account_id ||
799                sd->status.char_id!=char_id || sd->status.guild_id!=guild_id ||
800                (agit_flag && map[sd->bl.m].flag.gvg_castle))
801                return 0;
802
803        intif_guild_leave(sd->status.guild_id, sd->status.account_id, sd->status.char_id,0,mes);
804        return 0;
805}
806
807// ƒMƒ‹ƒh’Ç•ú—v‹
808int guild_expulsion(struct map_session_data* sd, int guild_id, int account_id, int char_id, const char* mes)
809{
810        struct map_session_data *tsd;
811        struct guild *g;
812        int i,ps;
813
814        nullpo_retr(0, sd);
815
816        g = guild_search(sd->status.guild_id);
817
818        if(g==NULL)
819                return 0;
820
821        if(sd->status.guild_id!=guild_id)
822                return 0;
823
824        if( (ps=guild_getposition(g,sd))<0 || !(g->position[ps].mode&0x0010) )
825                return 0;       //Expulsion permission
826
827        //Can't leave inside guild castles.
828        if ((tsd = map_id2sd(account_id)) &&
829                tsd->status.char_id == char_id &&
830                (agit_flag && map[tsd->bl.m].flag.gvg_castle))
831                return 0;
832
833        // find the member and perform expulsion
834        i = guild_getindex(g, account_id, char_id);
835        if( i != -1 && strcmp(g->member[i].name,g->master) != 0 ) //Can't expel the GL!
836                intif_guild_leave(g->guild_id,account_id,char_id,1,mes);
837
838        return 0;
839}
840
841int guild_member_leaved(int guild_id, int account_id, int char_id, int flag, const char* name, const char* mes)
842{
843        int i;
844        struct guild* g = guild_search(guild_id);
845        struct map_session_data* sd = map_charid2sd(char_id);
846        struct map_session_data* online_member_sd;
847
848        if(g == NULL)
849                return 0; // no such guild (error!)
850       
851        i = guild_getindex(g, account_id, char_id);
852        if( i == -1 )
853                return 0; // not a member (inconsistency!)
854
855        online_member_sd = guild_getavailablesd(g);
856        if(online_member_sd == NULL)
857                return 0; // noone online to inform
858
859        if(!flag)
860                clif_guild_leave(online_member_sd, name, mes);
861        else
862                clif_guild_expulsion(online_member_sd, name, mes, account_id);
863
864        // remove member from guild
865        memset(&g->member[i],0,sizeof(struct guild_member));
866        clif_guild_memberlist(online_member_sd);
867
868        // update char, if online
869        if(sd != NULL && sd->status.guild_id == guild_id)
870        {
871                // do stuff that needs the guild_id first, BEFORE we wipe it
872                if (sd->state.storage_flag == 2) //Close the guild storage.
873                        storage_guild_storageclose(sd);
874                guild_send_dot_remove(sd);
875
876                sd->status.guild_id = 0;
877                sd->guild_emblem_id = 0;
878               
879                clif_charnameupdate(sd); //Update display name [Skotlex]
880                //TODO: send emblem update to self and people around
881        }
882        return 0;
883}
884
885int guild_send_memberinfoshort(struct map_session_data *sd,int online)
886{ // cleaned up [LuzZza]
887        struct guild *g;
888       
889        nullpo_retr(0, sd);
890               
891        if(sd->status.guild_id <= 0)
892                return 0;
893
894        if(!(g = guild_search(sd->status.guild_id)))
895                return 0;
896
897        intif_guild_memberinfoshort(g->guild_id,
898                sd->status.account_id,sd->status.char_id,online,sd->status.base_level,sd->status.class_);
899
900        if(!online){
901                int i=guild_getindex(g,sd->status.account_id,sd->status.char_id);
902                if(i>=0)
903                        g->member[i].sd=NULL;
904                else
905                        ShowError("guild_send_memberinfoshort: Failed to locate member %d:%d in guild %d!\n", sd->status.account_id, sd->status.char_id, g->guild_id);
906                return 0;
907        }
908       
909        if(sd->state.connect_new)
910        {       //Note that this works because it is invoked in parse_LoadEndAck before connect_new is cleared.
911                clif_guild_belonginfo(sd,g);
912                clif_guild_notice(sd,g);
913                sd->guild_emblem_id = g->emblem_id;
914        }
915        return 0;
916}
917
918int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int online,int lv,int class_)
919{ // cleaned up [LuzZza]
920       
921        int i,alv,c,idx=-1,om=0,oldonline=-1;
922        struct guild *g = guild_search(guild_id);
923       
924        if(g == NULL)
925                return 0;
926       
927        for(i=0,alv=0,c=0,om=0;i<g->max_member;i++){
928                struct guild_member *m=&g->member[i];
929                if(!m->account_id) continue;
930                if(m->account_id==account_id && m->char_id==char_id ){
931                        oldonline=m->online;
932                        m->online=online;
933                        m->lv=lv;
934                        m->class_=class_;
935                        idx=i;
936                }
937                alv+=m->lv;
938                c++;
939                if(m->online)
940                        om++;
941        }
942       
943        if(idx == -1 || c == 0) {
944                // ƒMƒ‹ƒh‚̃ƒ“ƒo[ŠO‚Ȃ̂ŒǕúˆµ‚¢‚·‚é
945                struct map_session_data *sd = map_id2sd(account_id);
946                if(sd && sd->status.char_id == char_id) {
947                        sd->status.guild_id=0;
948                        sd->guild_emblem_id=0;
949                }
950                ShowWarning("guild: not found member %d,%d on %d[%s]\n",        account_id,char_id,guild_id,g->name);
951                return 0;
952        }
953       
954        g->average_lv=alv/c;
955        g->connect_member=om;
956
957        //Ensure validity of pointer (ie: player logs in/out, changes map-server)
958        g->member[idx].sd = guild_sd_check(guild_id, account_id, char_id);
959
960        if(oldonline!=online) 
961                clif_guild_memberlogin_notice(g, idx, online);
962       
963        if(!g->member[idx].sd)
964                return 0;
965
966        //Send XY dot updates. [Skotlex]
967        //Moved from guild_send_memberinfoshort [LuzZza]
968        for(i=0; i < g->max_member; i++) {
969               
970                if(!g->member[i].sd || i == idx ||
971                        g->member[i].sd->bl.m != g->member[idx].sd->bl.m)
972                        continue;
973
974                clif_guild_xy_single(g->member[idx].sd->fd, g->member[i].sd);
975                clif_guild_xy_single(g->member[i].sd->fd, g->member[idx].sd);
976        }
977
978        return 0;
979}
980// ƒMƒ‹ƒh‰ï˜b‘—M
981int guild_send_message(struct map_session_data *sd,const char *mes,int len)
982{
983        nullpo_retr(0, sd);
984
985        if(sd->status.guild_id==0)
986                return 0;
987        intif_guild_message(sd->status.guild_id,sd->status.account_id,mes,len);
988        guild_recv_message(sd->status.guild_id,sd->status.account_id,mes,len);
989
990        // Chat logging type 'G' / Guild Chat
991        if( log_config.chat&1 || (log_config.chat&16 && !(agit_flag && log_config.chat&64)) )
992                log_chat("G", sd->status.guild_id, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, mes);
993
994        return 0;
995}
996// ƒMƒ‹ƒh‰ï˜bŽóM
997int guild_recv_message(int guild_id,int account_id,const char *mes,int len)
998{
999        struct guild *g;
1000        if( (g=guild_search(guild_id))==NULL)
1001                return 0;
1002        clif_guild_message(g,account_id,mes,len);
1003        return 0;
1004}
1005// ƒMƒ‹ƒhƒƒ“ƒo‚Ì–ðE•ύX
1006int guild_change_memberposition(int guild_id,int account_id,int char_id,int idx)
1007{
1008        return intif_guild_change_memberinfo(guild_id,account_id,char_id,GMI_POSITION,&idx,sizeof(idx));
1009}
1010// ƒMƒ‹ƒhƒƒ“ƒo‚Ì–ðE•ύX’Ê’m
1011int guild_memberposition_changed(struct guild *g,int idx,int pos)
1012{
1013        nullpo_retr(0, g);
1014
1015        g->member[idx].position=pos;
1016        clif_guild_memberpositionchanged(g,idx);
1017       
1018        // Update char position in client [LuzZza]
1019        if(g->member[idx].sd != NULL)
1020                clif_charnameupdate(g->member[idx].sd);
1021        return 0;
1022}
1023// ƒMƒ‹ƒh–ðE•ύX
1024int guild_change_position(int guild_id,int idx,
1025        int mode,int exp_mode,const char *name)
1026{
1027        struct guild_position p;
1028
1029        exp_mode = cap_value(exp_mode, 0, battle_config.guild_exp_limit);
1030        //Mode 0x01 <- Invite
1031        //Mode 0x10 <- Expel.
1032        p.mode=mode&0x11;
1033        p.exp_mode=exp_mode;
1034        safestrncpy(p.name,name,NAME_LENGTH);
1035        return intif_guild_position(guild_id,idx,&p);
1036}
1037// ƒMƒ‹ƒh–ðE•ύX’Ê’m
1038int guild_position_changed(int guild_id,int idx,struct guild_position *p)
1039{
1040        struct guild *g=guild_search(guild_id);
1041        int i;
1042        if(g==NULL)
1043                return 0;
1044        memcpy(&g->position[idx],p,sizeof(struct guild_position));
1045        clif_guild_positionchanged(g,idx);
1046       
1047        // Update char name in client [LuzZza]
1048        for(i=0;i<g->max_member;i++)
1049                if(g->member[i].position == idx && g->member[i].sd != NULL)
1050                        clif_charnameupdate(g->member[i].sd);
1051        return 0;
1052}
1053// ƒMƒ‹ƒh’m•ύX
1054int guild_change_notice(struct map_session_data *sd,int guild_id,const char *mes1,const char *mes2)
1055{
1056        nullpo_retr(0, sd);
1057
1058        if(guild_id!=sd->status.guild_id)
1059                return 0;
1060        return intif_guild_notice(guild_id,mes1,mes2);
1061}
1062// ƒMƒ‹ƒh’m•ύX’Ê’m
1063int guild_notice_changed(int guild_id,const char *mes1,const char *mes2)
1064{
1065        int i;
1066        struct map_session_data *sd;
1067        struct guild *g=guild_search(guild_id);
1068        if(g==NULL)
1069                return 0;
1070
1071        memcpy(g->mes1,mes1,60);
1072        memcpy(g->mes2,mes2,120);
1073
1074        for(i=0;i<g->max_member;i++){
1075                if((sd=g->member[i].sd)!=NULL)
1076                        clif_guild_notice(sd,g);
1077        }
1078        return 0;
1079}
1080// ƒMƒ‹ƒhƒGƒ“ƒuƒŒƒ€•ύX
1081int guild_change_emblem(struct map_session_data *sd,int len,const char *data)
1082{
1083        struct guild *g;
1084        nullpo_retr(0, sd);
1085
1086        if (battle_config.require_glory_guild &&
1087                !((g = guild_search(sd->status.guild_id)) && guild_checkskill(g, GD_GLORYGUILD)>0)) {
1088                clif_skill_fail(sd,GD_GLORYGUILD,0,0);
1089                return 0;
1090        }
1091
1092        return intif_guild_emblem(sd->status.guild_id,len,data);
1093}
1094// ƒMƒ‹ƒhƒGƒ“ƒuƒŒƒ€•ύX’Ê’m
1095int guild_emblem_changed(int len,int guild_id,int emblem_id,const char *data)
1096{
1097        int i;
1098        struct map_session_data *sd;
1099        struct guild *g=guild_search(guild_id);
1100        if(g==NULL)
1101                return 0;
1102
1103        memcpy(g->emblem_data,data,len);
1104        g->emblem_len=len;
1105        g->emblem_id=emblem_id;
1106
1107        for(i=0;i<g->max_member;i++){
1108                if((sd=g->member[i].sd)!=NULL){
1109                        sd->guild_emblem_id=emblem_id;
1110                        clif_guild_belonginfo(sd,g);
1111                        clif_guild_emblem(sd,g);
1112                        clif_guild_emblem_area(&sd->bl);
1113                }
1114        }
1115        {// update guardians (mobs)
1116                DBIterator* iter = db_iterator(castle_db);
1117                struct guild_castle* gc;
1118                for( gc = (struct guild_castle*)dbi_first(iter) ; dbi_exists(iter); gc = (struct guild_castle*)dbi_next(iter) )
1119                {
1120                        if( gc->guild_id != guild_id )
1121                                continue;
1122                        // update permanent guardians
1123                        for( i = 0; i < ARRAYLENGTH(gc->guardian); ++i )
1124                        {
1125                                TBL_MOB* md = (gc->guardian[i].id ? map_id2md(gc->guardian[i].id) : NULL);
1126                                if( md == NULL || md->guardian_data == NULL )
1127                                        continue;
1128                                md->guardian_data->emblem_id = emblem_id;
1129                                clif_guild_emblem_area(&md->bl);
1130                        }
1131                        // update temporary guardians
1132                        for( i = 0; i < gc->temp_guardians_max; ++i )
1133                        {
1134                                TBL_MOB* md = (gc->temp_guardians[i] ? map_id2md(gc->temp_guardians[i]) : NULL);
1135                                if( md == NULL || md->guardian_data == NULL )
1136                                        continue;
1137                                md->guardian_data->emblem_id = emblem_id;
1138                                clif_guild_emblem_area(&md->bl);
1139                        }
1140                }
1141                dbi_destroy(iter);
1142        }
1143        {// update npcs (flags or other npcs that used flagemblem to attach to this guild)
1144                // TODO this is not efficient [FlavioJS]
1145                struct s_mapiterator* iter = mapit_geteachnpc();
1146                TBL_NPC* nd;
1147                for( nd = (TBL_NPC*)mapit_first(iter) ; mapit_exists(iter); nd = (TBL_NPC*)mapit_next(iter) )
1148                {
1149                        if( nd->subtype != SCRIPT || nd->u.scr.guild_id != guild_id )
1150                                continue;
1151                        clif_guild_emblem_area(&nd->bl);
1152                }
1153                mapit_free(iter);
1154        }
1155        return 0;
1156}
1157
1158static void* create_expcache(DBKey key, va_list args)
1159{
1160        struct guild_expcache *c;
1161        struct map_session_data *sd = va_arg(args, struct map_session_data*);
1162
1163        c = ers_alloc(expcache_ers, struct guild_expcache);
1164        c->guild_id = sd->status.guild_id;
1165        c->account_id = sd->status.account_id;
1166        c->char_id = sd->status.char_id;
1167        c->exp = 0;
1168        return c;
1169}
1170
1171// ƒMƒ‹ƒh‚ÌEXPã”[
1172unsigned int guild_payexp(struct map_session_data *sd,unsigned int exp)
1173{
1174        struct guild *g;
1175        struct guild_expcache *c;
1176        int per;
1177       
1178        nullpo_retr(0, sd);
1179
1180        if (!exp) return 0;
1181       
1182        if (sd->status.guild_id == 0 ||
1183                (g = guild_search(sd->status.guild_id)) == NULL ||
1184                (per = guild_getposition(g,sd)) < 0 ||
1185                (per = g->position[per].exp_mode) < 1)
1186                return 0;
1187       
1188
1189        if (per < 100)
1190                exp = (unsigned int) exp * per / 100;
1191        //Otherwise tax everything.
1192       
1193        c = (struct guild_expcache*)guild_expcache_db->ensure(guild_expcache_db, i2key(sd->status.char_id), create_expcache, sd);
1194
1195        if (c->exp > UINT_MAX - exp)
1196                c->exp = UINT_MAX;
1197        else
1198                c->exp += exp;
1199       
1200        return exp;
1201}
1202
1203// Celest
1204int guild_getexp(struct map_session_data *sd,int exp)
1205{
1206        struct guild *g;
1207        struct guild_expcache *c;
1208        nullpo_retr(0, sd);
1209
1210        if (sd->status.guild_id == 0 || (g = guild_search(sd->status.guild_id)) == NULL)
1211                return 0;
1212
1213        c = (struct guild_expcache*)guild_expcache_db->ensure(guild_expcache_db, i2key(sd->status.char_id), create_expcache, sd);
1214        if (c->exp > UINT_MAX - exp)
1215                c->exp = UINT_MAX;
1216        else
1217                c->exp += exp;
1218        return exp;
1219}
1220
1221// ƒXƒLƒ‹ƒ|ƒCƒ“ƒgŠ„‚èU‚è
1222int guild_skillup(TBL_PC* sd, int skill_num)
1223{
1224        struct guild* g;
1225        int idx = skill_num - GD_SKILLBASE;
1226
1227        nullpo_retr(0, sd);
1228
1229        if( idx < 0 || idx >= MAX_GUILDSKILL || // not a guild skill
1230                        sd->status.guild_id == 0 || (g=guild_search(sd->status.guild_id)) == NULL || // no guild
1231                        strcmp(sd->status.name, g->master) ) // not the guild master
1232                return 0;
1233
1234        if( g->skill_point > 0 &&
1235                        g->skill[idx].id != 0 &&
1236                        g->skill[idx].lv < guild_skill_get_max(skill_num) )
1237                intif_guild_skillup(g->guild_id, skill_num, sd->status.account_id);
1238
1239        return 0;
1240}
1241// ƒXƒLƒ‹ƒ|ƒCƒ“ƒgŠ„‚èU‚è’Ê’m
1242int guild_skillupack(int guild_id,int skill_num,int account_id)
1243{
1244        struct map_session_data *sd=map_id2sd(account_id);
1245        struct guild *g=guild_search(guild_id);
1246        int i;
1247        if(g==NULL)
1248                return 0;
1249        if(sd!=NULL)
1250                clif_guild_skillup(sd,skill_num,g->skill[skill_num-GD_SKILLBASE].lv);
1251        // ‘Sˆõ‚É’Ê’m
1252        for(i=0;i<g->max_member;i++)
1253                if((sd=g->member[i].sd)!=NULL)
1254                        clif_guild_skillinfo(sd);
1255        return 0;
1256}
1257
1258// ƒMƒ‹ƒh“¯–¿”Š“Ÿ
1259int guild_get_alliance_count(struct guild *g,int flag)
1260{
1261        int i,c;
1262
1263        nullpo_retr(0, g);
1264
1265        for(i=c=0;i<MAX_GUILDALLIANCE;i++){
1266                if(     g->alliance[i].guild_id>0 &&
1267                        g->alliance[i].opposition==flag )
1268                        c++;
1269        }
1270        return c;
1271}
1272
1273// Blocks all guild skills which have a common delay time.
1274void guild_block_skill(struct map_session_data *sd, int time)
1275{
1276        int skill_num[] = { GD_BATTLEORDER, GD_REGENERATION, GD_RESTORE, GD_EMERGENCYCALL };
1277        int i;
1278        for (i = 0; i < 4; i++)
1279                skill_blockpc_start(sd, skill_num[i], time);
1280}
1281
1282// “¯–¿ŠÖŒW‚©‚Ç‚€‚©ƒ`ƒFƒbƒN
1283// “¯–¿‚È‚ç1A‚»‚êˆÈŠO‚Í0
1284int guild_check_alliance(int guild_id1, int guild_id2, int flag)
1285{
1286        struct guild *g;
1287        int i;
1288
1289        g = guild_search(guild_id1);
1290        if (g == NULL)
1291                return 0;
1292
1293        ARR_FIND( 0, MAX_GUILDALLIANCE, i, g->alliance[i].guild_id == guild_id2 && g->alliance[i].opposition == flag );
1294        return( i < MAX_GUILDALLIANCE ) ? 1 : 0;
1295}
1296
1297// ƒMƒ‹ƒh“¯–¿—v‹
1298int guild_reqalliance(struct map_session_data *sd,struct map_session_data *tsd)
1299{
1300        struct guild *g[2];
1301        int i;
1302
1303        if(agit_flag)   {       // Disable alliance creation during woe [Valaris]
1304                clif_displaymessage(sd->fd,"Alliances cannot be made during Guild Wars!");
1305                return 0;
1306        }       // end addition [Valaris]
1307
1308
1309        nullpo_retr(0, sd);
1310
1311        if(tsd==NULL || tsd->status.guild_id<=0)
1312                return 0;
1313
1314        g[0]=guild_search(sd->status.guild_id);
1315        g[1]=guild_search(tsd->status.guild_id);
1316
1317        if(g[0]==NULL || g[1]==NULL)
1318                return 0;
1319
1320        // Prevent creation alliance with same guilds [LuzZza]
1321        if(sd->status.guild_id == tsd->status.guild_id)
1322                return 0;
1323
1324        if( guild_get_alliance_count(g[0],0) >= battle_config.max_guild_alliance )      {
1325                clif_guild_allianceack(sd,4);
1326                return 0;
1327        }
1328        if( guild_get_alliance_count(g[1],0) >= battle_config.max_guild_alliance ) {
1329                clif_guild_allianceack(sd,3);
1330                return 0;
1331        }
1332
1333        if( tsd->guild_alliance>0 ){
1334                clif_guild_allianceack(sd,1);
1335                return 0;
1336        }
1337
1338        for(i=0;i<MAX_GUILDALLIANCE;i++){       // ‚·‚łɓ¯–¿ó‘Ô‚©Šm”F
1339                if(     g[0]->alliance[i].guild_id==tsd->status.guild_id &&
1340                        g[0]->alliance[i].opposition==0){
1341                        clif_guild_allianceack(sd,0);
1342                        return 0;
1343                }
1344        }
1345
1346        tsd->guild_alliance=sd->status.guild_id;
1347        tsd->guild_alliance_account=sd->status.account_id;
1348
1349        clif_guild_reqalliance(tsd,sd->status.account_id,g[0]->name);
1350        return 0;
1351}
1352// ƒMƒ‹ƒhŠ©—U‚ւ̕ԓš
1353int guild_reply_reqalliance(struct map_session_data *sd,int account_id,int flag)
1354{
1355        struct map_session_data *tsd;
1356
1357        nullpo_retr(0, sd);
1358        tsd= map_id2sd( account_id );
1359        if (!tsd) { //Character left? Cancel alliance.
1360                clif_guild_allianceack(sd,3);
1361                return 0;
1362        }
1363
1364        if(sd->guild_alliance!=tsd->status.guild_id)    // Š©—U‚ƃMƒ‹ƒhID‚ªˆá‚€
1365                return 0;
1366
1367        if(flag==1){    // ³‘ø
1368                int i;
1369
1370                struct guild *g,*tg;    // “¯–¿”ÄŠm”F
1371                g=guild_search(sd->status.guild_id);
1372                tg=guild_search(tsd->status.guild_id);
1373               
1374                if(g==NULL || guild_get_alliance_count(g,0) >= battle_config.max_guild_alliance){
1375                        clif_guild_allianceack(sd,4);
1376                        clif_guild_allianceack(tsd,3);
1377                        return 0;
1378                }
1379                if(tg==NULL || guild_get_alliance_count(tg,0) >= battle_config.max_guild_alliance){
1380                        clif_guild_allianceack(sd,3);
1381                        clif_guild_allianceack(tsd,4);
1382                        return 0;
1383                }
1384
1385                for(i=0;i<MAX_GUILDALLIANCE;i++){
1386                        if(g->alliance[i].guild_id==tsd->status.guild_id &&
1387                                g->alliance[i].opposition==1)
1388                                intif_guild_alliance( sd->status.guild_id,tsd->status.guild_id,
1389                                        sd->status.account_id,tsd->status.account_id,9 );
1390                }
1391                for(i=0;i<MAX_GUILDALLIANCE;i++){
1392                        if(tg->alliance[i].guild_id==sd->status.guild_id &&
1393                                tg->alliance[i].opposition==1)
1394                                intif_guild_alliance( tsd->status.guild_id,sd->status.guild_id,
1395                                        tsd->status.account_id,sd->status.account_id,9 );
1396                }
1397
1398                // interŽI‚Ö“¯–¿—v¿
1399                intif_guild_alliance( sd->status.guild_id,tsd->status.guild_id,
1400                        sd->status.account_id,tsd->status.account_id,0 );
1401                return 0;
1402        }else{          // ‹‘”Û
1403                sd->guild_alliance=0;
1404                sd->guild_alliance_account=0;
1405                if(tsd!=NULL)
1406                        clif_guild_allianceack(tsd,3);
1407        }
1408        return 0;
1409}
1410
1411// ƒMƒ‹ƒhŠÖŒW‰ðÁ
1412int guild_delalliance(struct map_session_data *sd,int guild_id,int flag)
1413{
1414        nullpo_retr(0, sd);
1415
1416        if(agit_flag)   {       // Disable alliance breaking during woe [Valaris]
1417                clif_displaymessage(sd->fd,"Alliances cannot be broken during Guild Wars!");
1418                return 0;
1419        }       // end addition [Valaris]
1420
1421        intif_guild_alliance( sd->status.guild_id,guild_id,sd->status.account_id,0,flag|8 );
1422        return 0;
1423}
1424
1425// ƒMƒ‹ƒh“G‘Î
1426int guild_opposition(struct map_session_data *sd,struct map_session_data *tsd)
1427{
1428        struct guild *g;
1429        int i;
1430
1431        nullpo_retr(0, sd);
1432
1433        g=guild_search(sd->status.guild_id);
1434        if(g==NULL || tsd==NULL)
1435                return 0;
1436
1437        // Prevent creation opposition with same guilds [LuzZza]
1438        if(sd->status.guild_id == tsd->status.guild_id)
1439                return 0;
1440
1441        if( guild_get_alliance_count(g,1) >= battle_config.max_guild_alliance ) {
1442                clif_guild_oppositionack(sd,1);
1443                return 0;
1444        }
1445
1446        for(i=0;i<MAX_GUILDALLIANCE;i++){       // ‚·‚łɊ֌W‚ðŽ‚Á‚Ä‚¢‚é‚©Šm”F
1447                if(g->alliance[i].guild_id==tsd->status.guild_id){
1448                        if(g->alliance[i].opposition==1){       // ‚·‚łɓG‘Î
1449                                clif_guild_oppositionack(sd,2);
1450                                return 0;
1451                        }
1452                        //Change alliance to opposition.
1453                        intif_guild_alliance( sd->status.guild_id,tsd->status.guild_id,
1454                                sd->status.account_id,tsd->status.account_id,8 );
1455                }
1456        }
1457
1458        // interŽI‚É“G‘Ηv¿
1459        intif_guild_alliance( sd->status.guild_id,tsd->status.guild_id,
1460                        sd->status.account_id,tsd->status.account_id,1 );
1461        return 0;
1462}
1463
1464// ƒMƒ‹ƒh“¯–¿/“G‘Î’Ê’m
1465int guild_allianceack(int guild_id1,int guild_id2,int account_id1,int account_id2,int flag,const char *name1,const char *name2)
1466{
1467        struct guild *g[2];
1468        int guild_id[2];
1469        const char *guild_name[2];
1470        struct map_session_data *sd[2];
1471        int j,i;
1472
1473        guild_id[0] = guild_id1;
1474        guild_id[1] = guild_id2;
1475        guild_name[0] = name1;
1476        guild_name[1] = name2;
1477        sd[0] = map_id2sd(account_id1);
1478        sd[1] = map_id2sd(account_id2);
1479
1480        g[0]=guild_search(guild_id1);
1481        g[1]=guild_search(guild_id2);
1482
1483        if(sd[0]!=NULL && (flag&0x0f)==0){
1484                sd[0]->guild_alliance=0;
1485                sd[0]->guild_alliance_account=0;
1486        }
1487
1488        if(flag&0x70){  // Žž”s
1489                for(i=0;i<2-(flag&1);i++)
1490                        if( sd[i]!=NULL )
1491                                clif_guild_allianceack(sd[i],((flag>>4)==i+1)?3:4);
1492                return 0;
1493        }
1494
1495        if(!(flag&0x08)){       // ŠÖŒW’ljÁ
1496                for(i=0;i<2-(flag&1);i++)
1497                {
1498                        if(g[i]!=NULL)
1499                        {
1500                                ARR_FIND( 0, MAX_GUILDALLIANCE, j, g[i]->alliance[j].guild_id == 0 );
1501                                if( j < MAX_GUILDALLIANCE )
1502                                {
1503                                        g[i]->alliance[j].guild_id=guild_id[1-i];
1504                                        memcpy(g[i]->alliance[j].name,guild_name[1-i],NAME_LENGTH);
1505                                        g[i]->alliance[j].opposition=flag&1;
1506                                }
1507                        }
1508                }
1509        }else{                          // ŠÖŒW‰ðÁ
1510                for(i=0;i<2-(flag&1);i++)
1511                {
1512                        if(g[i]!=NULL)
1513                        {
1514                                ARR_FIND( 0, MAX_GUILDALLIANCE, j, g[i]->alliance[j].guild_id == guild_id[1-i] && g[i]->alliance[j].opposition == (flag&1) );
1515                                if( j < MAX_GUILDALLIANCE )
1516                                        g[i]->alliance[j].guild_id = 0;
1517                        }
1518                        if( sd[i]!=NULL )       // ‰ðÁ’Ê’m
1519                                clif_guild_delalliance(sd[i],guild_id[1-i],(flag&1));
1520                }
1521        }
1522
1523        if((flag&0x0f)==0){                     // “¯–¿’Ê’m
1524                if( sd[1]!=NULL )
1525                        clif_guild_allianceack(sd[1],2);
1526        }else if((flag&0x0f)==1){       // “G‘Î’Ê’m
1527                if( sd[0]!=NULL )
1528                        clif_guild_oppositionack(sd[0],0);
1529        }
1530
1531
1532        for(i=0;i<2-(flag&1);i++){      // “¯–¿/“G‘ÎƒŠƒXƒg‚̍đ—M
1533                struct map_session_data *sd;
1534                if(g[i]!=NULL)
1535                        for(j=0;j<g[i]->max_member;j++)
1536                                if((sd=g[i]->member[j].sd)!=NULL)
1537                                        clif_guild_allianceinfo(sd);
1538        }
1539        return 0;
1540}
1541// ƒMƒ‹ƒh‰ðŽU’Ê’m—p
1542int guild_broken_sub(DBKey key,void *data,va_list ap)
1543{
1544        struct guild *g=(struct guild *)data;
1545        int guild_id=va_arg(ap,int);
1546        int i,j;
1547        struct map_session_data *sd=NULL;
1548
1549        nullpo_retr(0, g);
1550
1551        for(i=0;i<MAX_GUILDALLIANCE;i++){       // ŠÖŒW‚ð”jŠü
1552                if(g->alliance[i].guild_id==guild_id){
1553                        for(j=0;j<g->max_member;j++)
1554                                if( (sd=g->member[j].sd)!=NULL )
1555                                        clif_guild_delalliance(sd,guild_id,g->alliance[i].opposition);
1556                        intif_guild_alliance(g->guild_id, guild_id,0,0,g->alliance[i].opposition|8);
1557                        g->alliance[i].guild_id=0;
1558                }
1559        }
1560        return 0;
1561}
1562
1563//Invoked on Castles when a guild is broken. [Skotlex]
1564int castle_guild_broken_sub(DBKey key,void *data,va_list ap)
1565{
1566        struct guild_castle *gc=(struct guild_castle *)data;
1567        int guild_id=va_arg(ap,int);
1568
1569        nullpo_retr(0, gc);
1570
1571        if (gc->guild_id == guild_id)
1572        {       //Save the new 'owner', this should invoke guardian clean up and other such things.
1573                gc->guild_id = 0;
1574                guild_castledatasave(gc->castle_id, 1, 0);
1575        }
1576        return 0;
1577}
1578
1579//Innvoked on /breakguild "Guild name"
1580int guild_broken(int guild_id,int flag)
1581{
1582        struct guild *g=guild_search(guild_id);
1583        struct guild_castle *gc=NULL;
1584        struct map_session_data *sd;
1585        int i;
1586        char name[50];
1587
1588        if(flag!=0 || g==NULL)
1589                return 0;
1590
1591        //we call castle_event::OnGuildBreak of all castlesof the guild
1592        //you can set all castle_events in the castle_db.txt
1593        for(i=0;i<MAX_GUILDCASTLE;i++){
1594                if( (gc=guild_castle_search(i)) != NULL ){
1595                        if(gc->guild_id == guild_id){
1596                                safestrncpy(name, gc->castle_event, 50);
1597                                npc_event_do(strcat(name,"::OnGuildBreak"));
1598                        }
1599                }
1600        }
1601
1602        for(i=0;i<g->max_member;i++){   // ƒMƒ‹ƒh‰ðŽU‚ð’Ê’m
1603                if((sd=g->member[i].sd)!=NULL){
1604                        if(sd->state.storage_flag == 2)
1605                                storage_guild_storage_quit(sd,1);
1606                        sd->status.guild_id=0;
1607                        clif_guild_broken(g->member[i].sd,0);
1608                        clif_charnameupdate(sd); // [LuzZza]
1609                }
1610        }
1611
1612        guild_db->foreach(guild_db,guild_broken_sub,guild_id);
1613        castle_db->foreach(castle_db,castle_guild_broken_sub,guild_id);
1614        guild_storage_delete(guild_id);
1615        idb_remove(guild_db,guild_id);
1616        return 0;
1617}
1618
1619//Changes the Guild Master to the specified player. [Skotlex]
1620int guild_gm_change(int guild_id, struct map_session_data *sd)
1621{
1622        struct guild *g;
1623        nullpo_retr(0, sd);
1624
1625        if (sd->status.guild_id != guild_id)
1626                return 0;
1627       
1628        g=guild_search(guild_id);
1629
1630        nullpo_retr(0, g);
1631
1632        if (strcmp(g->master, sd->status.name) == 0) //Nothing to change.
1633                return 0;
1634
1635        //Notify servers that master has changed.
1636        intif_guild_change_gm(guild_id, sd->status.name, strlen(sd->status.name));
1637        return 1;
1638}
1639
1640//Notification from Char server that a guild's master has changed. [Skotlex]
1641int guild_gm_changed(int guild_id, int account_id, int char_id)
1642{
1643        struct guild *g;
1644        struct guild_member gm;
1645        int pos;
1646
1647        g=guild_search(guild_id);
1648
1649        if (!g)
1650                return 0;
1651
1652        for(pos=0; pos<g->max_member && !(
1653                g->member[pos].account_id==account_id &&
1654                g->member[pos].char_id==char_id);
1655                pos++);
1656
1657        if (pos == 0 || pos == g->max_member) return 0;
1658
1659        memcpy(&gm, &g->member[pos], sizeof (struct guild_member));
1660        memcpy(&g->member[pos], &g->member[0], sizeof(struct guild_member));
1661        memcpy(&g->member[0], &gm, sizeof(struct guild_member));
1662
1663        g->member[pos].position = g->member[0].position;
1664        g->member[0].position = 0; //Position 0: guild Master.
1665        strcpy(g->master, g->member[0].name);
1666
1667        if (g->member[pos].sd && g->member[pos].sd->fd)
1668        {
1669                clif_displaymessage(g->member[pos].sd->fd, "You no longer are the Guild Master.");
1670                g->member[pos].sd->state.gmaster_flag = 0;
1671        }
1672       
1673        if (g->member[0].sd && g->member[0].sd->fd)
1674        {
1675                clif_displaymessage(g->member[0].sd->fd, "You have become the Guild Master!");
1676                g->member[0].sd->state.gmaster_flag = g;
1677                //Block his skills for 5 minutes to prevent abuse.
1678                guild_block_skill(g->member[0].sd, 300000);
1679        }       
1680        return 1;
1681}
1682
1683// ƒMƒ‹ƒh‰ðŽU
1684int guild_break(struct map_session_data *sd,char *name)
1685{
1686        struct guild *g;
1687        int i;
1688
1689        nullpo_retr(0, sd);
1690
1691        if( (g=guild_search(sd->status.guild_id))==NULL )
1692                return 0;
1693        if(strcmp(g->name,name)!=0)
1694                return 0;
1695        if(!sd->state.gmaster_flag)
1696                return 0;
1697        for(i=0;i<g->max_member;i++){
1698                if(     g->member[i].account_id>0 && (
1699                        g->member[i].account_id!=sd->status.account_id ||
1700                        g->member[i].char_id!=sd->status.char_id ))
1701                        break;
1702        }
1703        if(i<g->max_member){
1704                clif_guild_broken(sd,2);
1705                return 0;
1706        }
1707
1708        intif_guild_break(g->guild_id);
1709        return 0;
1710}
1711
1712// ƒMƒ‹ƒhéƒf[ƒ^—v‹
1713int guild_castledataload(int castle_id,int index)
1714{
1715        return intif_guild_castle_dataload(castle_id,index);
1716}
1717// ƒMƒ‹ƒhéî•ñŠ“ŸŽžƒCƒxƒ“ƒg’ljÁ
1718int guild_addcastleinfoevent(int castle_id,int index,const char *name)
1719{
1720        struct eventlist *ev;
1721        int code=castle_id|(index<<16);
1722
1723        if( name==NULL || *name==0 )
1724                return 0;
1725
1726        ev = (struct eventlist *)aMalloc(sizeof(struct eventlist));
1727        memcpy(ev->name,name,sizeof(ev->name));
1728        //The next event becomes whatever was currently stored.
1729        ev->next = (struct eventlist *)idb_put(guild_castleinfoevent_db,code,ev);
1730        return 0;
1731}
1732
1733// ƒMƒ‹ƒhéƒf[ƒ^—v‹•ԐM
1734int guild_castledataloadack(int castle_id,int index,int value)
1735{
1736        struct guild_castle *gc=guild_castle_search(castle_id);
1737        int code=castle_id|(index<<16);
1738        struct eventlist *ev,*ev2;
1739
1740        if(gc==NULL){
1741                return 0;
1742        }
1743        switch(index){
1744        case 1:
1745                gc->guild_id = value;
1746                if (gc->guild_id && guild_search(gc->guild_id)==NULL) //Request guild data which will be required for spawned guardians. [Skotlex]
1747                        guild_request_info(gc->guild_id);
1748                break;
1749        case 2: gc->economy = value; break;
1750        case 3: gc->defense = value; break;
1751        case 4: gc->triggerE = value; break;
1752        case 5: gc->triggerD = value; break;
1753        case 6: gc->nextTime = value; break;
1754        case 7: gc->payTime = value; break;
1755        case 8: gc->createTime = value; break;
1756        case 9: gc->visibleC = value; break;
1757        case 10:
1758        case 11:
1759        case 12:
1760        case 13:
1761        case 14:
1762        case 15:
1763        case 16:
1764        case 17:
1765                gc->guardian[index-10].visible = value; break;
1766        default:
1767                ShowError("guild_castledataloadack ERROR!! (Not found index=%d)\n", index);
1768                return 0;
1769        }
1770
1771        if( (ev = (struct eventlist *)idb_remove(guild_castleinfoevent_db,code))!=NULL )
1772        {
1773                while(ev){
1774                        npc_event_do(ev->name);
1775                        ev2=ev->next;
1776                        aFree(ev);
1777                        ev=ev2;
1778                }
1779        }
1780        return 1;
1781}
1782// ƒMƒ‹ƒhéƒf[ƒ^•ύX—v‹
1783int guild_castledatasave(int castle_id,int index,int value)
1784{
1785        if( index == 1 )
1786        {       //The castle's owner has changed? Update Guardian ownership, too. [Skotlex]
1787                struct guild_castle *gc = guild_castle_search(castle_id);
1788                int m = -1;
1789                if (gc) m = map_mapindex2mapid(gc->mapindex);
1790                if (m != -1)
1791                        map_foreachinmap(mob_guardian_guildchange, m, BL_MOB); //FIXME: why not iterate over gc->guardian[i].id ?
1792        }
1793        else
1794        if( index == 3 )
1795        {       // defense invest change -> recalculate guardian hp
1796                struct guild_castle* gc = guild_castle_search(castle_id);
1797                if( gc )
1798                {
1799                        int i;
1800                        struct mob_data* gd;
1801                        for( i = 0; i < MAX_GUARDIANS; i++ )
1802                                if( gc->guardian[i].visible && (gd = map_id2md(gc->guardian[i].id)) != NULL )
1803                                                status_calc_mob(gd,0);
1804                }
1805        }
1806
1807        return intif_guild_castle_datasave(castle_id,index,value);
1808}
1809
1810// ƒMƒ‹ƒhéƒf[ƒ^•ύX’Ê’m
1811int guild_castledatasaveack(int castle_id,int index,int value)
1812{
1813        struct guild_castle *gc=guild_castle_search(castle_id);
1814        if(gc==NULL){
1815                return 0;
1816        }
1817        switch(index){
1818        case 1: gc->guild_id = value; break;
1819        case 2: gc->economy = value; break;
1820        case 3: gc->defense = value; break;
1821        case 4: gc->triggerE = value; break;
1822        case 5: gc->triggerD = value; break;
1823        case 6: gc->nextTime = value; break;
1824        case 7: gc->payTime = value; break;
1825        case 8: gc->createTime = value; break;
1826        case 9: gc->visibleC = value; break;
1827        case 10:
1828        case 11:
1829        case 12:
1830        case 13:
1831        case 14:
1832        case 15:
1833        case 16:
1834        case 17:
1835                gc->guardian[index-10].visible = value; break;
1836        default:
1837                ShowError("guild_castledatasaveack ERROR!! (Not found index=%d)\n", index);
1838                return 0;
1839        }
1840        return 1;
1841}
1842
1843// ƒMƒ‹ƒhƒf[ƒ^ˆêЇŽóMi‰Šú‰»Žžj
1844int guild_castlealldataload(int len,struct guild_castle *gc)
1845{
1846        int i;
1847        int n = (len-4) / sizeof(struct guild_castle);
1848        int ev;
1849
1850        nullpo_retr(0, gc);
1851
1852        //Last owned castle in the list invokes ::OnAgitinit
1853        for( i = n-1; i >= 0 && !(gc[i].guild_id); --i );
1854        ev = i; // offset of castle or -1
1855
1856        if( ev < 0 ) //No castles owned, invoke OnAgitInit as it is.
1857                npc_event_doall("OnAgitInit");
1858        else // load received castles into memory, one by one
1859        for( i = 0; i < n; i++, gc++ )
1860        {
1861                struct guild_castle *c = guild_castle_search(gc->castle_id);
1862                if (!c) {
1863                        ShowError("guild_castlealldataload Castle id=%d not found.\n", gc->castle_id);
1864                        continue;
1865                }
1866
1867                // update mapserver castle data with new info
1868                memcpy(&c->guild_id, &gc->guild_id, sizeof(struct guild_castle) - ((int)&c->guild_id - (int)c));
1869
1870                if( c->guild_id )
1871                {
1872                        if( i != ev )
1873                                guild_request_info(c->guild_id);
1874                        else // last owned one
1875                                guild_npc_request_info(c->guild_id, "::OnAgitInit");
1876                }
1877        }
1878
1879        return 0;
1880}
1881
1882int guild_agit_start(void)
1883{       // Run All NPC_Event[OnAgitStart]
1884        int c = npc_event_doall("OnAgitStart");
1885        ShowStatus("NPC_Event:[OnAgitStart] Run (%d) Events by @AgitStart.\n",c);
1886        // Start auto saving
1887        guild_save_timer = add_timer_interval (gettick() + GUILD_SAVE_INTERVAL, guild_save_sub, 0, 0, GUILD_SAVE_INTERVAL);
1888        return 0;
1889}
1890
1891int guild_agit_end(void)
1892{       // Run All NPC_Event[OnAgitEnd]
1893        int c = npc_event_doall("OnAgitEnd");
1894        ShowStatus("NPC_Event:[OnAgitEnd] Run (%d) Events by @AgitEnd.\n",c);
1895        // Stop auto saving
1896        delete_timer (guild_save_timer, guild_save_sub);
1897        return 0;
1898}
1899
1900int guild_save_sub(int tid, unsigned int tick, int id, intptr data)
1901{
1902        static int Gid[MAX_GUILDCASTLE]; // previous owning guild
1903        struct guild_castle *gc;
1904        int i;
1905
1906        for(i = 0; i < MAX_GUILDCASTLE; i++) {  // [Yor]
1907                gc = guild_castle_search(i);
1908                if (!gc) continue;
1909                if (gc->guild_id != Gid[i]) {
1910                        // Re-save guild id if its owner guild has changed
1911                        guild_castledatasave(gc->castle_id, 1, gc->guild_id);
1912                        Gid[i] = gc->guild_id;
1913                }
1914        }
1915
1916        return 0;
1917}
1918
1919// How many castles does this guild have?
1920int guild_checkcastles(struct guild *g)
1921{
1922        int i, nb_cas = 0;
1923        struct guild_castle* gc;
1924
1925        for(i = 0; i < MAX_GUILDCASTLE; i++) {
1926                gc = guild_castle_search(i);
1927                if(gc && gc->guild_id == g->guild_id)
1928                        nb_cas++;
1929        }
1930
1931        return nb_cas;
1932}
1933
1934// Are these two guilds allied?
1935bool guild_isallied(int guild_id, int guild_id2)
1936{
1937        int i;
1938        struct guild* g = guild_search(guild_id);
1939        nullpo_retr(0, g);
1940
1941        ARR_FIND( 0, MAX_GUILDALLIANCE, i, g->alliance[i].guild_id == guild_id2 );
1942        return( i < MAX_GUILDALLIANCE && g->alliance[i].opposition == 0 );
1943}
1944
1945static int guild_infoevent_db_final(DBKey key,void *data,va_list ap)
1946{
1947        aFree(data);
1948        return 0;
1949}
1950
1951static int guild_expcache_db_final(DBKey key,void *data,va_list ap)
1952{
1953        ers_free(expcache_ers, data);
1954        return 0;
1955}
1956
1957static int guild_castle_db_final(DBKey key, void* data,va_list ap)
1958{
1959        struct guild_castle* gc = (struct guild_castle*)data;
1960        if( gc->temp_guardians )
1961                aFree(gc->temp_guardians);
1962        aFree(data);
1963        return 0;
1964}
1965
1966void do_init_guild(void)
1967{
1968        guild_db=idb_alloc(DB_OPT_RELEASE_DATA);
1969        castle_db=idb_alloc(DB_OPT_BASE);
1970        guild_expcache_db=idb_alloc(DB_OPT_BASE);
1971        guild_infoevent_db=idb_alloc(DB_OPT_BASE);
1972        expcache_ers = ers_new(sizeof(struct guild_expcache)); 
1973        guild_castleinfoevent_db=idb_alloc(DB_OPT_BASE);
1974
1975        guild_read_castledb();
1976
1977        guild_read_guildskill_tree_db(); //guild skill tree [Komurka]
1978
1979        add_timer_func_list(guild_payexp_timer,"guild_payexp_timer");
1980        add_timer_func_list(guild_save_sub, "guild_save_sub");
1981        add_timer_func_list(guild_send_xy_timer, "guild_send_xy_timer");
1982        add_timer_interval(gettick()+GUILD_PAYEXP_INVERVAL,guild_payexp_timer,0,0,GUILD_PAYEXP_INVERVAL);
1983        add_timer_interval(gettick()+GUILD_SEND_XY_INVERVAL,guild_send_xy_timer,0,0,GUILD_SEND_XY_INVERVAL);
1984}
1985
1986void do_final_guild(void)
1987{
1988        guild_db->destroy(guild_db,NULL);
1989        castle_db->destroy(castle_db,guild_castle_db_final);
1990        guild_expcache_db->destroy(guild_expcache_db,guild_expcache_db_final);
1991        guild_infoevent_db->destroy(guild_infoevent_db,guild_infoevent_db_final);
1992        guild_castleinfoevent_db->destroy(guild_castleinfoevent_db,guild_infoevent_db_final);
1993        ers_destroy(expcache_ers);
1994}
Note: See TracBrowser for help on using the browser.