root/src/char_sql/int_guild.c @ 1

Revision 1, 61.8 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/mmo.h"
6#include "../common/malloc.h"
7#include "../common/socket.h"
8#include "../common/db.h"
9#include "../common/showmsg.h"
10#include "../common/strlib.h"
11#include "../common/timer.h"
12#include "char.h"
13#include "inter.h"
14#include "int_guild.h"
15
16#include <string.h>
17#include <stdio.h>
18#include <stdlib.h>
19
20#define GS_MEMBER_UNMODIFIED 0x00
21#define GS_MEMBER_MODIFIED 0x01
22#define GS_MEMBER_NEW 0x02
23
24#define GS_POSITION_UNMODIFIED 0x00
25#define GS_POSITION_MODIFIED 0x01
26
27// LSB = 0 => Alliance, LSB = 1 => Opposition
28#define GUILD_ALLIANCE_TYPE_MASK 0x01
29#define GUILD_ALLIANCE_REMOVE 0x08
30
31static const char dataToHex[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
32
33#ifndef TXT_SQL_CONVERT
34//Guild cache
35static DBMap* guild_db_; // int guild_id -> struct guild*
36
37struct guild_castle castles[MAX_GUILDCASTLE];
38
39static unsigned int guild_exp[100];
40
41int mapif_parse_GuildLeave(int fd,int guild_id,int account_id,int char_id,int flag,const char *mes);
42int mapif_guild_broken(int guild_id,int flag);
43static bool guild_check_empty(struct guild *g);
44int guild_calcinfo(struct guild *g);
45int mapif_guild_basicinfochanged(int guild_id,int type,const void *data,int len);
46int mapif_guild_info(int fd,struct guild *g);
47int guild_break_sub(int key,void *data,va_list ap);
48int inter_guild_tosql(struct guild *g,int flag);
49
50static int guild_save_timer(int tid, unsigned int tick, int id, intptr data)
51{
52        static int last_id = 0; //To know in which guild we were.
53        int state = 0; //0: Have not reached last guild. 1: Reached last guild, ready for save. 2: Some guild saved, don't do further saving.
54        DBIterator* iter;
55        DBKey key;
56        struct guild* g;
57
58        if( last_id == 0 ) //Save the first guild in the list.
59                state = 1;
60
61        iter = guild_db_->iterator(guild_db_);
62        for( g = (struct guild*)iter->first(iter,&key); iter->exists(iter); g = (struct guild*)iter->next(iter,&key) )
63        {
64                if( state == 0 && g->guild_id == last_id )
65                        state++; //Save next guild in the list.
66                else
67                if( state == 1 && g->save_flag&GS_MASK )
68                {
69                        inter_guild_tosql(g, g->save_flag&GS_MASK);
70                        g->save_flag &= ~GS_MASK;
71
72                        //Some guild saved.
73                        last_id = g->guild_id;
74                        state++;
75                }
76
77                if( g->save_flag == GS_REMOVE )
78                {// Nothing to save, guild is ready for removal.
79                        if (save_log)
80                                ShowInfo("Guild Unloaded (%d - %s)\n", g->guild_id, g->name);
81                        db_remove(guild_db_, key);
82                }
83        }
84        iter->destroy(iter);
85
86        if( state != 2 ) //Reached the end of the guild db without saving.
87                last_id = 0; //Reset guild saved, return to beginning.
88
89        state = guild_db_->size(guild_db_);
90        if( state < 1 ) state = 1; //Calculate the time slot for the next save.
91        add_timer(tick  + autosave_interval/state, guild_save_timer, 0, 0);
92        return 0;
93}
94
95int inter_guild_removemember_tosql(int account_id, int char_id)
96{
97        if( SQL_ERROR == Sql_Query(sql_handle, "DELETE from `%s` where `account_id` = '%d' and `char_id` = '%d'", guild_member_db, account_id, char_id) )
98                Sql_ShowDebug(sql_handle);
99        if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `guild_id` = '0' WHERE `char_id` = '%d'", char_db, char_id) )
100                Sql_ShowDebug(sql_handle);
101        return 0;
102}
103#endif //TXT_SQL_CONVERT
104
105// Save guild into sql
106int inter_guild_tosql(struct guild *g,int flag)
107{
108        // Table guild (GS_BASIC_MASK)
109        // GS_EMBLEM `emblem_len`,`emblem_id`,`emblem_data`
110        // GS_CONNECT `connect_member`,`average_lv`
111        // GS_MES `mes1`,`mes2`
112        // GS_LEVEL `guild_lv`,`max_member`,`exp`,`next_exp`,`skill_point`
113        // GS_BASIC `name`,`master`,`char_id`
114
115        // GS_MEMBER `guild_member` (`guild_id`,`account_id`,`char_id`,`hair`,`hair_color`,`gender`,`class`,`lv`,`exp`,`exp_payper`,`online`,`position`,`name`)
116        // GS_POSITION `guild_position` (`guild_id`,`position`,`name`,`mode`,`exp_mode`)
117        // GS_ALLIANCE `guild_alliance` (`guild_id`,`opposition`,`alliance_id`,`name`)
118        // GS_EXPULSION `guild_expulsion` (`guild_id`,`account_id`,`name`,`mes`)
119        // GS_SKILL `guild_skill` (`guild_id`,`id`,`lv`)
120
121        // temporary storage for str convertion. They must be twice the size of the
122        // original string to ensure no overflows will occur. [Skotlex]
123        char t_info[256];
124        char esc_name[NAME_LENGTH*2+1];
125        char esc_master[NAME_LENGTH*2+1];
126        char new_guild = 0;
127        int i=0;
128
129        if (g->guild_id<=0 && g->guild_id != -1) return 0;
130       
131#ifdef NOISY
132        ShowInfo("Save guild request ("CL_BOLD"%d"CL_RESET" - flag 0x%x).",g->guild_id, flag);
133#endif
134
135        Sql_EscapeStringLen(sql_handle, esc_name, g->name, strnlen(g->name, NAME_LENGTH));
136        Sql_EscapeStringLen(sql_handle, esc_master, g->master, strnlen(g->master, NAME_LENGTH));
137        *t_info = '\0';
138
139#ifndef TXT_SQL_CONVERT
140        // Insert a new guild the guild
141        if (flag&GS_BASIC && g->guild_id == -1)
142        {
143                strcat(t_info, " guild_create");
144
145                // Create a new guild
146                if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` "
147                        "(`name`,`master`,`guild_lv`,`max_member`,`average_lv`,`char_id`) "
148                        "VALUES ('%s', '%s', '%d', '%d', '%d', '%d')",
149                        guild_db, esc_name, esc_master, g->guild_lv, g->max_member, g->average_lv, g->member[0].char_id) )
150                {
151                        Sql_ShowDebug(sql_handle);
152                        if (g->guild_id == -1)
153                                return 0; //Failed to create guild!
154                }
155                else
156                {
157                        g->guild_id = (int)Sql_LastInsertId(sql_handle);
158                        new_guild = 1;
159                }
160        }
161#else
162        // Insert a new guild the guild
163        if (flag&GS_BASIC)
164        {
165                strcat(t_info, " guild_create");
166                // Since the PK is guild id + master id, a replace will not be enough if we are overwriting data, we need to wipe the previous guild.
167                if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` where `guild_id` = '%d'", guild_db, g->guild_id) )
168                        Sql_ShowDebug(sql_handle);
169                // Create a new guild
170                if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` "
171                        "(`guild_id`,`name`,`master`,`guild_lv`,`max_member`,`average_lv`,`char_id`) "
172                        "VALUES ('%d', '%s', '%s', '%d', '%d', '%d', '%d')",
173                        guild_db, g->guild_id, esc_name, esc_master, g->guild_lv, g->max_member, g->average_lv, g->member[0].char_id) )
174                {
175                        Sql_ShowDebug(sql_handle);
176                        return 0; //Failed to create guild.
177                }
178        }
179#endif //TXT_SQL_CONVERT
180        // If we need an update on an existing guild or more update on the new guild
181        if (((flag & GS_BASIC_MASK) && !new_guild) || ((flag & (GS_BASIC_MASK & ~GS_BASIC)) && new_guild))
182        {
183                StringBuf buf;
184                bool add_comma = false;
185
186                StringBuf_Init(&buf);
187                StringBuf_Printf(&buf, "UPDATE `%s` SET ", guild_db);
188
189                if (flag & GS_EMBLEM)
190                {
191                        char emblem_data[sizeof(g->emblem_data)*2+1];
192                        char* pData = emblem_data;
193
194                        strcat(t_info, " emblem");
195                        // Convert emblem_data to hex
196                        //TODO: why not use binary directly? [ultramage]
197                        for(i=0; i<g->emblem_len; i++){
198                                *pData++ = dataToHex[(g->emblem_data[i] >> 4) & 0x0F];
199                                *pData++ = dataToHex[g->emblem_data[i] & 0x0F];
200                        }
201                        *pData = 0;
202                        StringBuf_Printf(&buf, "`emblem_len`=%d, `emblem_id`=%d, `emblem_data`='%s'", g->emblem_len, g->emblem_id, emblem_data);
203                        add_comma = true;
204                }
205                if (flag & GS_BASIC) 
206                {
207                        strcat(t_info, " basic");
208                        if( add_comma )
209                                StringBuf_AppendStr(&buf, ", ");
210                        else
211                                add_comma = true;
212                        StringBuf_Printf(&buf, "`name`='%s', `master`='%s', `char_id`=%d", esc_name, esc_master, g->member[0].char_id);
213                }
214                if (flag & GS_CONNECT)
215                {
216                        strcat(t_info, " connect");
217                        if( add_comma )
218                                StringBuf_AppendStr(&buf, ", ");
219                        else
220                                add_comma = true;
221                        StringBuf_Printf(&buf, "`connect_member`=%d, `average_lv`=%d", g->connect_member, g->average_lv);
222                }
223                if (flag & GS_MES)
224                {
225                        char esc_mes1[sizeof(g->mes1)*2+1];
226                        char esc_mes2[sizeof(g->mes2)*2+1];
227
228                        strcat(t_info, " mes");
229                        if( add_comma )
230                                StringBuf_AppendStr(&buf, ", ");
231                        else
232                                add_comma = true;
233                        Sql_EscapeStringLen(sql_handle, esc_mes1, g->mes1, strnlen(g->mes1, sizeof(g->mes1)));
234                        Sql_EscapeStringLen(sql_handle, esc_mes2, g->mes2, strnlen(g->mes2, sizeof(g->mes2)));
235                        StringBuf_Printf(&buf, "`mes1`='%s', `mes2`='%s'", esc_mes1, esc_mes2);
236                }
237                if (flag & GS_LEVEL)
238                {
239                        strcat(t_info, " level");
240                        if( add_comma )
241                                StringBuf_AppendStr(&buf, ", ");
242                        else
243                                add_comma = true;
244                        StringBuf_Printf(&buf, "`guild_lv`=%d, `skill_point`=%d, `exp`=%u, `next_exp`=%u, `max_member`=%d", g->guild_lv, g->skill_point, g->exp, g->next_exp, g->max_member);
245                }
246                StringBuf_Printf(&buf, " WHERE `guild_id`=%d", g->guild_id);
247                if( SQL_ERROR == Sql_Query(sql_handle, "%s", StringBuf_Value(&buf)) )
248                        Sql_ShowDebug(sql_handle);
249                StringBuf_Destroy(&buf);
250        }
251
252        if (flag&GS_MEMBER)
253        {
254                struct guild_member *m;
255
256                strcat(t_info, " members");
257                // Update only needed players
258                for(i=0;i<g->max_member;i++){
259                        m = &g->member[i];
260#ifndef TXT_SQL_CONVERT
261                        if (!m->modified)
262                                continue;
263#endif
264                        if(m->account_id) {
265                                //Since nothing references guild member table as foreign keys, it's safe to use REPLACE INTO
266                                Sql_EscapeStringLen(sql_handle, esc_name, m->name, strnlen(m->name, NAME_LENGTH));
267                                if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`guild_id`,`account_id`,`char_id`,`hair`,`hair_color`,`gender`,`class`,`lv`,`exp`,`exp_payper`,`online`,`position`,`name`) "
268                                        "VALUES ('%d','%d','%d','%d','%d','%d','%d','%d','%u','%d','%d','%d','%s')",
269                                        guild_member_db, g->guild_id, m->account_id, m->char_id,
270                                        m->hair, m->hair_color, m->gender,
271                                        m->class_, m->lv, m->exp, m->exp_payper, m->online, m->position, esc_name) )
272                                        Sql_ShowDebug(sql_handle);
273                                if (m->modified & GS_MEMBER_NEW)
274                                {
275                                        if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `guild_id` = '%d' WHERE `char_id` = '%d'",
276                                                char_db, g->guild_id, m->char_id) )
277                                                Sql_ShowDebug(sql_handle);
278                                }
279                                m->modified = GS_MEMBER_UNMODIFIED;
280                        }
281                }
282        }
283
284        if (flag&GS_POSITION){
285                strcat(t_info, " positions");
286                //printf("- Insert guild %d to guild_position\n",g->guild_id);
287                for(i=0;i<MAX_GUILDPOSITION;i++){
288                        struct guild_position *p = &g->position[i];
289#ifndef TXT_SQL_CONVERT
290                        if (!p->modified)
291                                continue;
292#endif
293                        Sql_EscapeStringLen(sql_handle, esc_name, p->name, strnlen(p->name, NAME_LENGTH));
294                        if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`guild_id`,`position`,`name`,`mode`,`exp_mode`) VALUES ('%d','%d','%s','%d','%d')",
295                                guild_position_db, g->guild_id, i, esc_name, p->mode, p->exp_mode) )
296                                Sql_ShowDebug(sql_handle);
297                        p->modified = GS_POSITION_UNMODIFIED;
298                }
299        }
300
301        if (flag&GS_ALLIANCE)
302        {
303                // Delete current alliances
304                // NOTE: no need to do it on both sides since both guilds in memory had
305                // their info changed, not to mention this would also mess up oppositions!
306                // [Skotlex]
307                //if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id`='%d' OR `alliance_id`='%d'", guild_alliance_db, g->guild_id, g->guild_id) )
308                if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id`='%d'", guild_alliance_db, g->guild_id) )
309                {
310                        Sql_ShowDebug(sql_handle);
311                }
312                else
313                {
314                        //printf("- Insert guild %d to guild_alliance\n",g->guild_id);
315                        for(i=0;i<MAX_GUILDALLIANCE;i++)
316                        {
317                                struct guild_alliance *a=&g->alliance[i];
318                                if(a->guild_id>0)
319                                {
320                                        Sql_EscapeStringLen(sql_handle, esc_name, a->name, strnlen(a->name, NAME_LENGTH));
321                                        if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`guild_id`,`opposition`,`alliance_id`,`name`) "
322                                                "VALUES ('%d','%d','%d','%s')",
323                                                guild_alliance_db, g->guild_id, a->opposition, a->guild_id, esc_name) )
324                                                Sql_ShowDebug(sql_handle);
325                                }
326                        }
327                }
328        }
329
330        if (flag&GS_EXPULSION){
331                strcat(t_info, " expulsions");
332                //printf("- Insert guild %d to guild_expulsion\n",g->guild_id);
333                for(i=0;i<MAX_GUILDEXPULSION;i++){
334                        struct guild_expulsion *e=&g->expulsion[i];
335                        if(e->account_id>0){
336                                char esc_mes[sizeof(e->mes)*2+1];
337
338                                Sql_EscapeStringLen(sql_handle, esc_name, e->name, strnlen(e->name, NAME_LENGTH));
339                                Sql_EscapeStringLen(sql_handle, esc_mes, e->mes, strnlen(e->mes, sizeof(e->mes)));
340                                if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`guild_id`,`account_id`,`name`,`mes`) "
341                                        "VALUES ('%d','%d','%s','%s')", guild_expulsion_db, g->guild_id, e->account_id, esc_name, esc_mes) )
342                                        Sql_ShowDebug(sql_handle);
343                        }
344                }
345        }
346
347        if (flag&GS_SKILL){
348                strcat(t_info, " skills");
349                //printf("- Insert guild %d to guild_skill\n",g->guild_id);
350                for(i=0;i<MAX_GUILDSKILL;i++){
351                        if (g->skill[i].id>0 && g->skill[i].lv>0){
352                                if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`guild_id`,`id`,`lv`) VALUES ('%d','%d','%d')",
353                                        guild_skill_db, g->guild_id, g->skill[i].id, g->skill[i].lv) )
354                                        Sql_ShowDebug(sql_handle);
355                        }
356                }
357        }
358
359        if (save_log)
360                ShowInfo("Saved guild (%d - %s):%s\n",g->guild_id,g->name,t_info);
361        return 1;
362}
363
364#ifndef TXT_SQL_CONVERT
365// Read guild from sql
366struct guild * inter_guild_fromsql(int guild_id)
367{
368        struct guild *g;
369        char* data;
370        size_t len;
371        char* p;
372        int i;
373
374        if( guild_id <= 0 )
375                return NULL;
376
377        g = (struct guild*)idb_get(guild_db_, guild_id);
378        if( g )
379                return g;
380
381#ifdef NOISY
382        ShowInfo("Guild load request (%d)...\n", guild_id);
383#endif
384
385        if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `name`,`master`,`guild_lv`,`connect_member`,`max_member`,`average_lv`,`exp`,`next_exp`,`skill_point`,`mes1`,`mes2`,`emblem_len`,`emblem_id`,`emblem_data` "
386                "FROM `%s` WHERE `guild_id`='%d'", guild_db, guild_id) )
387        {
388                Sql_ShowDebug(sql_handle);
389                return NULL;
390        }
391
392        if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
393                return NULL;// Guild does not exists.
394
395        CREATE(g, struct guild, 1);
396
397        g->guild_id = guild_id;
398        Sql_GetData(sql_handle,  0, &data, &len); memcpy(g->name, data, min(len, NAME_LENGTH));
399        Sql_GetData(sql_handle,  1, &data, &len); memcpy(g->master, data, min(len, NAME_LENGTH));
400        Sql_GetData(sql_handle,  2, &data, NULL); g->guild_lv = atoi(data);
401        Sql_GetData(sql_handle,  3, &data, NULL); g->connect_member = atoi(data);
402        Sql_GetData(sql_handle,  4, &data, NULL); g->max_member = atoi(data);
403        if( g->max_member > MAX_GUILD )
404        {       // Fix reduction of MAX_GUILD [PoW]
405                ShowWarning("Guild %d:%s specifies higher capacity (%d) than MAX_GUILD (%d)\n", guild_id, g->name, g->max_member, MAX_GUILD);
406                g->max_member = MAX_GUILD;
407        }
408        Sql_GetData(sql_handle,  5, &data, NULL); g->average_lv = atoi(data);
409        Sql_GetData(sql_handle,  6, &data, NULL); g->exp = (unsigned int)strtoul(data, NULL, 10);
410        Sql_GetData(sql_handle,  7, &data, NULL); g->next_exp = (unsigned int)strtoul(data, NULL, 10);
411        Sql_GetData(sql_handle,  8, &data, NULL); g->skill_point = atoi(data);
412        Sql_GetData(sql_handle,  9, &data, &len); memcpy(g->mes1, data, min(len, sizeof(g->mes1)));
413        Sql_GetData(sql_handle, 10, &data, &len); memcpy(g->mes2, data, min(len, sizeof(g->mes2)));
414        Sql_GetData(sql_handle, 11, &data, &len); g->emblem_len = atoi(data);
415        Sql_GetData(sql_handle, 12, &data, &len); g->emblem_id = atoi(data);
416        Sql_GetData(sql_handle, 13, &data, &len);
417        // convert emblem data from hexadecimal to binary
418        //TODO: why not store it in the db as binary directly? [ultramage]
419        for( i = 0, p = g->emblem_data; i < g->emblem_len; ++i, ++p )
420        {
421                if( *data >= '0' && *data <= '9' )
422                        *p = *data - '0';
423                else if( *data >= 'a' && *data <= 'f' )
424                        *p = *data - 'a' + 10;
425                else if( *data >= 'A' && *data <= 'F' )
426                        *p = *data - 'A' + 10;
427                *p <<= 4;
428                ++data;
429
430                if( *data >= '0' && *data <= '9' )
431                        *p |= *data - '0';
432                else if( *data >= 'a' && *data <= 'f' )
433                        *p |= *data - 'a' + 10;
434                else if( *data >= 'A' && *data <= 'F' )
435                        *p |= *data - 'A' + 10;
436                ++data;
437        }
438
439        // load guild member info
440        if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`char_id`,`hair`,`hair_color`,`gender`,`class`,`lv`,`exp`,`exp_payper`,`online`,`position`,`name` "
441                "FROM `%s` WHERE `guild_id`='%d' ORDER BY `position`", guild_member_db, guild_id) )
442        {
443                Sql_ShowDebug(sql_handle);
444                aFree(g);
445                return NULL;
446        }
447        for( i = 0; i < g->max_member && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i )
448        {
449                struct guild_member* m = &g->member[i];
450
451                Sql_GetData(sql_handle,  0, &data, NULL); m->account_id = atoi(data);
452                Sql_GetData(sql_handle,  1, &data, NULL); m->char_id = atoi(data);
453                Sql_GetData(sql_handle,  2, &data, NULL); m->hair = atoi(data);
454                Sql_GetData(sql_handle,  3, &data, NULL); m->hair_color = atoi(data);
455                Sql_GetData(sql_handle,  4, &data, NULL); m->gender = atoi(data);
456                Sql_GetData(sql_handle,  5, &data, NULL); m->class_ = atoi(data);
457                Sql_GetData(sql_handle,  6, &data, NULL); m->lv = atoi(data);
458                Sql_GetData(sql_handle,  7, &data, NULL); m->exp = (unsigned int)strtoul(data, NULL, 10);
459                Sql_GetData(sql_handle,  8, &data, NULL); m->exp_payper = (unsigned int)atoi(data);
460                Sql_GetData(sql_handle,  9, &data, NULL); m->online = atoi(data);
461                Sql_GetData(sql_handle, 10, &data, NULL); m->position = atoi(data);
462                if( m->position >= MAX_GUILDPOSITION ) // Fix reduction of MAX_GUILDPOSITION [PoW]
463                        m->position = MAX_GUILDPOSITION - 1;
464                Sql_GetData(sql_handle, 11, &data, &len); memcpy(m->name, data, min(len, NAME_LENGTH));
465                m->modified = GS_MEMBER_UNMODIFIED;
466        }
467
468        //printf("- Read guild_position %d from sql \n",guild_id);
469        if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `position`,`name`,`mode`,`exp_mode` FROM `%s` WHERE `guild_id`='%d'", guild_position_db, guild_id) )
470        {
471                Sql_ShowDebug(sql_handle);
472                aFree(g);
473                return NULL;
474        }
475        while( SQL_SUCCESS == Sql_NextRow(sql_handle) )
476        {
477                int position;
478                struct guild_position* p;
479
480                Sql_GetData(sql_handle, 0, &data, NULL); position = atoi(data);
481                if( position < 0 || position >= MAX_GUILDPOSITION )
482                        continue;// invalid position
483                p = &g->position[position];
484                Sql_GetData(sql_handle, 1, &data, &len); memcpy(p->name, data, min(len, NAME_LENGTH));
485                Sql_GetData(sql_handle, 2, &data, NULL); p->mode = atoi(data);
486                Sql_GetData(sql_handle, 3, &data, NULL); p->exp_mode = atoi(data);
487                p->modified = GS_POSITION_UNMODIFIED;
488        }
489
490        //printf("- Read guild_alliance %d from sql \n",guild_id);
491        if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `opposition`,`alliance_id`,`name` FROM `%s` WHERE `guild_id`='%d'", guild_alliance_db, guild_id) )
492        {
493                Sql_ShowDebug(sql_handle);
494                aFree(g);
495                return NULL;
496        }
497        for( i = 0; i < MAX_GUILDALLIANCE && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i )
498        {
499                struct guild_alliance* a = &g->alliance[i];
500
501                Sql_GetData(sql_handle, 0, &data, NULL); a->opposition = atoi(data);
502                Sql_GetData(sql_handle, 1, &data, NULL); a->guild_id = atoi(data);
503                Sql_GetData(sql_handle, 2, &data, &len); memcpy(a->name, data, min(len, NAME_LENGTH));
504        }
505
506        //printf("- Read guild_expulsion %d from sql \n",guild_id);
507        if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`name`,`mes` FROM `%s` WHERE `guild_id`='%d'", guild_expulsion_db, guild_id) )
508        {
509                Sql_ShowDebug(sql_handle);
510                aFree(g);
511                return NULL;
512        }
513        for( i = 0; i < MAX_GUILDEXPULSION && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i )
514        {
515                struct guild_expulsion *e = &g->expulsion[i];
516
517                Sql_GetData(sql_handle, 0, &data, NULL); e->account_id = atoi(data);
518                Sql_GetData(sql_handle, 1, &data, &len); memcpy(e->name, data, min(len, NAME_LENGTH));
519                Sql_GetData(sql_handle, 2, &data, &len); memcpy(e->mes, data, min(len, sizeof(e->mes)));
520        }
521
522        //printf("- Read guild_skill %d from sql \n",guild_id);
523        if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `id`,`lv` FROM `%s` WHERE `guild_id`='%d' ORDER BY `id`", guild_skill_db, guild_id) )
524        {
525                Sql_ShowDebug(sql_handle);
526                aFree(g);
527                return NULL;
528        }
529
530        for(i = 0; i < MAX_GUILDSKILL; i++)
531        {       //Skill IDs must always be initialized. [Skotlex]
532                g->skill[i].id = i + GD_SKILLBASE;
533        }
534
535        while( SQL_SUCCESS == Sql_NextRow(sql_handle) )
536        {
537                int id;
538                Sql_GetData(sql_handle, 0, &data, NULL); id = atoi(data) - GD_SKILLBASE;
539                if( id < 0 && id >= MAX_GUILDSKILL )
540                        continue;// invalid guild skill
541                Sql_GetData(sql_handle, 1, &data, NULL); g->skill[id].lv = atoi(data);
542        }
543        Sql_FreeResult(sql_handle);
544
545        idb_put(guild_db_, guild_id, g); //Add to cache
546        g->save_flag |= GS_REMOVE; //But set it to be removed, in case it is not needed for long.
547       
548        if (save_log)
549                ShowInfo("Guild loaded (%d - %s)\n", guild_id, g->name);
550
551        return g;
552}
553#endif //TXT_SQL_CONVERT
554
555int inter_guildcastle_tosql(struct guild_castle *gc)
556{
557        // `guild_castle` (`castle_id`, `guild_id`, `economy`, `defense`, `triggerE`, `triggerD`, `nextTime`, `payTime`, `createTime`, `visibleC`, `visibleG0`, `visibleG1`, `visibleG2`, `visibleG3`, `visibleG4`, `visibleG5`, `visibleG6`, `visibleG7`)
558
559        if (gc==NULL) return 0;
560        #ifdef GUILD_DEBUG
561ShowDebug("Save guild_castle (%d)\n", gc->castle_id);
562        #endif
563
564//      sql_query("DELETE FROM `%s` WHERE `castle_id`='%d'",guild_castle_db, gc->castle_id);
565        if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` "
566                "(`castle_id`, `guild_id`, `economy`, `defense`, `triggerE`, `triggerD`, `nextTime`, `payTime`, `createTime`,"
567                "`visibleC`, `visibleG0`, `visibleG1`, `visibleG2`, `visibleG3`, `visibleG4`, `visibleG5`, `visibleG6`, `visibleG7`)"
568                "VALUES ('%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d')",
569                guild_castle_db, gc->castle_id, gc->guild_id,  gc->economy, gc->defense, gc->triggerE, gc->triggerD, gc->nextTime, gc->payTime, gc->createTime, gc->visibleC,
570                gc->guardian[0].visible, gc->guardian[1].visible, gc->guardian[2].visible, gc->guardian[3].visible, gc->guardian[4].visible, gc->guardian[5].visible, gc->guardian[6].visible, gc->guardian[7].visible) )
571                Sql_ShowDebug(sql_handle);
572
573#ifndef TXT_SQL_CONVERT
574        memcpy(&castles[gc->castle_id],gc,sizeof(struct guild_castle));
575#endif //TXT_SQL_CONVERT
576        return 0;
577}
578
579#ifndef TXT_SQL_CONVERT
580// Read guild_castle from sql
581int inter_guildcastle_fromsql(int castle_id,struct guild_castle *gc)
582{
583        static int castles_init=0;
584        char* data;
585
586        if (gc==NULL) return 0;
587        if (castle_id==-1) return 0;
588
589        if(!castles_init)
590        {
591                int i;
592                for(i=0;i<MAX_GUILDCASTLE;i++)
593                        castles[i].castle_id=-1;
594                castles_init = 1;
595        }
596
597        if(castles[castle_id].castle_id == castle_id)
598        {
599                memcpy(gc,&castles[castle_id],sizeof(struct guild_castle));
600                return 1;
601        }
602
603        memset(gc,0,sizeof(struct guild_castle));
604        if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `castle_id`, `guild_id`, `economy`, `defense`, `triggerE`, `triggerD`, `nextTime`, `payTime`, `createTime`, "
605                "`visibleC`, `visibleG0`, `visibleG1`, `visibleG2`, `visibleG3`, `visibleG4`, `visibleG5`, `visibleG6`, `visibleG7`"
606                " FROM `%s` WHERE `castle_id`='%d'", guild_castle_db, castle_id) )
607        {
608                Sql_ShowDebug(sql_handle);
609                return 0;
610        }
611        // ARU: This needs to be set even if there are no SQL results
612        gc->castle_id=castle_id;
613        if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
614        {
615                Sql_FreeResult(sql_handle);
616                return 1; //Assume empty castle.
617        }
618
619        Sql_GetData(sql_handle,  1, &data, NULL); gc->guild_id =  atoi(data);
620        Sql_GetData(sql_handle,  2, &data, NULL); gc->economy = atoi(data);
621        Sql_GetData(sql_handle,  3, &data, NULL); gc->defense = atoi(data);
622        Sql_GetData(sql_handle,  4, &data, NULL); gc->triggerE = atoi(data);
623        Sql_GetData(sql_handle,  5, &data, NULL); gc->triggerD = atoi(data);
624        Sql_GetData(sql_handle,  6, &data, NULL); gc->nextTime = atoi(data);
625        Sql_GetData(sql_handle,  7, &data, NULL); gc->payTime = atoi(data);
626        Sql_GetData(sql_handle,  8, &data, NULL); gc->createTime = atoi(data);
627        Sql_GetData(sql_handle,  9, &data, NULL); gc->visibleC = atoi(data);
628        Sql_GetData(sql_handle, 10, &data, NULL); gc->guardian[0].visible = atoi(data);
629        Sql_GetData(sql_handle, 11, &data, NULL); gc->guardian[1].visible = atoi(data);
630        Sql_GetData(sql_handle, 12, &data, NULL); gc->guardian[2].visible = atoi(data);
631        Sql_GetData(sql_handle, 13, &data, NULL); gc->guardian[3].visible = atoi(data);
632        Sql_GetData(sql_handle, 14, &data, NULL); gc->guardian[4].visible = atoi(data);
633        Sql_GetData(sql_handle, 15, &data, NULL); gc->guardian[5].visible = atoi(data);
634        Sql_GetData(sql_handle, 16, &data, NULL); gc->guardian[6].visible = atoi(data);
635        Sql_GetData(sql_handle, 17, &data, NULL); gc->guardian[7].visible = atoi(data);
636
637        Sql_FreeResult(sql_handle);
638        memcpy(&castles[castle_id],gc,sizeof(struct guild_castle));
639
640        if( save_log )
641                ShowInfo("Loaded Castle %d (guild %d)\n", castle_id, gc->guild_id);
642
643        return 1;
644}
645
646
647// Read exp_guild.txt
648int inter_guild_ReadEXP(void)
649{
650        int i;
651        FILE *fp;
652        char line[1024];
653        for (i=0;i<100;i++) guild_exp[i]=0;
654
655        sprintf(line, "%s/exp_guild.txt", db_path);
656        fp=fopen(line,"r");
657        if(fp==NULL){
658                ShowError("can't read %s\n", line);
659                return 1;
660        }
661        i=0;
662        while(fgets(line, sizeof(line), fp) && i < 100)
663        {
664                if(line[0]=='/' && line[1]=='/')
665                        continue;
666                guild_exp[i]=(unsigned int)atof(line);
667                i++;
668        }
669        fclose(fp);
670
671        return 0;
672}
673
674
675int inter_guild_CharOnline(int char_id, int guild_id)
676{
677   struct guild *g;
678   int i;
679   
680        if (guild_id == -1) {
681                //Get guild_id from the database
682                if( SQL_ERROR == Sql_Query(sql_handle, "SELECT guild_id FROM `%s` WHERE char_id='%d'", char_db, char_id) )
683                {
684                        Sql_ShowDebug(sql_handle);
685                        return 0;
686                }
687
688                if( SQL_SUCCESS == Sql_NextRow(sql_handle) )
689                {
690                        char* data;
691
692                        Sql_GetData(sql_handle, 0, &data, NULL);
693                        guild_id = atoi(data);
694                }
695                else
696                {
697                        guild_id = 0;
698                }
699                Sql_FreeResult(sql_handle);
700        }
701        if (guild_id == 0)
702                return 0; //No guild...
703       
704        g = inter_guild_fromsql(guild_id);
705        if(!g) {
706                ShowError("Character %d's guild %d not found!\n", char_id, guild_id);
707                return 0;
708        }
709
710        //Member has logged in before saving, tell saver not to delete
711        if(g->save_flag & GS_REMOVE)
712                g->save_flag &= ~GS_REMOVE;
713
714        //Set member online
715        ARR_FIND( 0, g->max_member, i, g->member[i].char_id == char_id );
716        if( i < g->max_member )
717        {
718                g->member[i].online = 1;
719                g->member[i].modified = GS_MEMBER_MODIFIED;
720        }
721
722        return 1;
723}
724
725int inter_guild_CharOffline(int char_id, int guild_id)
726{
727        struct guild *g=NULL;
728        int online_count, i;
729
730        if (guild_id == -1)
731        {
732                //Get guild_id from the database
733                if( SQL_ERROR == Sql_Query(sql_handle, "SELECT guild_id FROM `%s` WHERE char_id='%d'", char_db, char_id) )
734                {
735                        Sql_ShowDebug(sql_handle);
736                        return 0;
737                }
738
739                if( SQL_SUCCESS == Sql_NextRow(sql_handle) )
740                {
741                        char* data;
742
743                        Sql_GetData(sql_handle, 0, &data, NULL);
744                        guild_id = atoi(data);
745                }
746                else
747                {
748                        guild_id = 0;
749                }
750                Sql_FreeResult(sql_handle);
751        }
752        if (guild_id == 0)
753                return 0; //No guild...
754       
755        //Character has a guild, set character offline and check if they were the only member online
756        g = inter_guild_fromsql(guild_id);
757        if (g == NULL) //Guild not found?
758                return 0;
759
760        //Set member offline
761        ARR_FIND( 0, g->max_member, i, g->member[i].char_id == char_id );
762        if( i < g->max_member )
763        {
764                g->member[i].online = 0;
765                g->member[i].modified = GS_MEMBER_MODIFIED;
766        }
767
768        online_count = 0;
769        for( i = 0; i < g->max_member; i++ )
770                if( g->member[i].online )
771                        online_count++;
772
773        // Remove guild from memory if no players online
774        if( online_count == 0 )
775                g->save_flag |= GS_REMOVE;
776
777        return 1;
778}
779
780// Initialize guild sql
781int inter_guild_sql_init(void)
782{
783        //Initialize the guild cache
784        guild_db_= idb_alloc(DB_OPT_RELEASE_DATA);
785
786   //Read exp file
787        inter_guild_ReadEXP();
788   
789        add_timer_func_list(guild_save_timer, "guild_save_timer");
790        add_timer(gettick() + 10000, guild_save_timer, 0, 0);
791        return 0;
792}
793
794static int guild_db_final(DBKey key, void *data, va_list ap)
795{
796        struct guild *g = (struct guild*)data;
797        if (g->save_flag&GS_MASK) {
798                inter_guild_tosql(g, g->save_flag&GS_MASK);
799                return 1;
800        }
801        return 0;
802}
803
804void inter_guild_sql_final(void)
805{
806        guild_db_->destroy(guild_db_, guild_db_final);
807        return;
808}
809
810// Get guild_id by its name. Returns 0 if not found, -1 on error.
811int search_guildname(char *str)
812{
813        int guild_id;
814        char esc_name[NAME_LENGTH*2+1];
815       
816        Sql_EscapeStringLen(sql_handle, esc_name, str, safestrnlen(str, NAME_LENGTH));
817        //Lookup guilds with the same name
818        if( SQL_ERROR == Sql_Query(sql_handle, "SELECT guild_id FROM `%s` WHERE name='%s'", guild_db, esc_name) )
819        {
820                Sql_ShowDebug(sql_handle);
821                return -1;
822        }
823
824        if( SQL_SUCCESS == Sql_NextRow(sql_handle) )
825        {
826                char* data;
827
828                Sql_GetData(sql_handle, 0, &data, NULL);
829                guild_id = atoi(data);
830        }
831        else
832        {
833                guild_id = 0;
834        }
835        Sql_FreeResult(sql_handle);
836        return guild_id;
837}
838
839// Check if guild is empty
840static bool guild_check_empty(struct guild *g)
841{
842        int i;
843        ARR_FIND( 0, g->max_member, i, g->member[i].account_id > 0 );
844        if( i < g->max_member)
845                return false; // not empty
846
847        //Let the calling function handle the guild removal in case they need
848        //to do something else with it before freeing the data. [Skotlex]
849        return true;
850}
851
852unsigned int guild_nextexp(int level)
853{
854        if (level == 0)
855                return 1;
856        if (level < 100 && level > 0) // Change by hack
857                return guild_exp[level-1];
858
859        return 0;
860}
861
862int guild_checkskill(struct guild *g,int id)
863{
864        int idx = id - GD_SKILLBASE;
865
866        if(idx < 0 || idx >= MAX_GUILDSKILL)
867                return 0;
868
869        return g->skill[idx].lv;
870}
871
872int guild_calcinfo(struct guild *g)
873{
874        int i,c;
875        unsigned int nextexp;
876        struct guild before = *g; // Save guild current values
877
878        if(g->guild_lv<=0)
879                g->guild_lv = 1;
880        nextexp = guild_nextexp(g->guild_lv);
881
882        // Consume guild exp and increase guild level
883        while(g->exp >= nextexp && nextexp > 0){        //fixed guild exp overflow [Kevin]
884                g->exp-=nextexp;
885                g->guild_lv++;
886                g->skill_point++;
887                nextexp = guild_nextexp(g->guild_lv);
888        }
889
890        // Save next exp step
891        g->next_exp = nextexp;
892
893        // Set the max number of members, Guild Extention skill - currently adds 6 to max per skill lv.
894        g->max_member = 16 + guild_checkskill(g, GD_EXTENSION) * 6; 
895        if(g->max_member > MAX_GUILD)
896        {       
897                ShowError("Guild %d:%s has capacity for too many guild members (%d), max supported is %d\n", g->guild_id, g->name, g->max_member, MAX_GUILD);
898                g->max_member = MAX_GUILD;
899        }
900       
901        // Compute the guild average level level
902        g->average_lv=0;
903        g->connect_member=0;
904        for(i=c=0;i<g->max_member;i++)
905        {
906                if(g->member[i].account_id>0)
907                {
908                        if (g->member[i].lv >= 0)
909                        {
910                                g->average_lv+=g->member[i].lv;
911                                c++;
912                        }
913                        else
914                        {
915                                ShowWarning("Guild %d:%s, member %d:%s has an invalid level %d\n", g->guild_id, g->name, g->member[i].char_id, g->member[i].name, g->member[i].lv);
916                        }
917
918                        if(g->member[i].online)
919                                g->connect_member++;
920                }
921        }
922        if(c)
923                g->average_lv /= c;
924
925        // Check if guild stats has change
926        if(g->max_member != before.max_member || g->guild_lv != before.guild_lv || g->skill_point != before.skill_point )
927        {
928                g->save_flag |= GS_LEVEL;
929                mapif_guild_info(-1,g);
930                return 1;
931        }
932
933        return 0;
934}
935
936//-------------------------------------------------------------------
937// Packet sent to map server
938
939int mapif_guild_created(int fd,int account_id,struct guild *g)
940{
941        WFIFOHEAD(fd, 10);
942        WFIFOW(fd,0)=0x3830;
943        WFIFOL(fd,2)=account_id;
944        if(g != NULL)
945        {
946                WFIFOL(fd,6)=g->guild_id;
947                ShowInfo("int_guild: Guild created (%d - %s)\n",g->guild_id,g->name);
948        } else
949                WFIFOL(fd,6)=0;
950
951        WFIFOSET(fd,10);
952        return 0;
953}
954
955// Guild not found
956int mapif_guild_noinfo(int fd,int guild_id)
957{
958        unsigned char buf[12];
959        WBUFW(buf,0)=0x3831;
960        WBUFW(buf,2)=8;
961        WBUFL(buf,4)=guild_id;
962        ShowWarning("int_guild: info not found %d\n",guild_id);
963        if(fd<0)
964                mapif_sendall(buf,8);
965        else
966                mapif_send(fd,buf,8);
967        return 0;
968}
969
970// Send guild info
971int mapif_guild_info(int fd,struct guild *g)
972{
973        unsigned char buf[8+sizeof(struct guild)];
974        WBUFW(buf,0)=0x3831;
975        WBUFW(buf,2)=4+sizeof(struct guild);
976        memcpy(buf+4,g,sizeof(struct guild));
977        if(fd<0)
978                mapif_sendall(buf,WBUFW(buf,2));
979        else
980                mapif_send(fd,buf,WBUFW(buf,2));
981        return 0;
982}
983
984// ACK member add
985int mapif_guild_memberadded(int fd,int guild_id,int account_id,int char_id,int flag)
986{
987        WFIFOHEAD(fd, 15);
988        WFIFOW(fd,0)=0x3832;
989        WFIFOL(fd,2)=guild_id;
990        WFIFOL(fd,6)=account_id;
991        WFIFOL(fd,10)=char_id;
992        WFIFOB(fd,14)=flag;
993        WFIFOSET(fd,15);
994        return 0;
995}
996
997// ACK member leave
998int mapif_guild_leaved(int guild_id,int account_id,int char_id,int flag, const char *name, const char *mes)
999{
1000        unsigned char buf[55+NAME_LENGTH];
1001        WBUFW(buf, 0)=0x3834;
1002        WBUFL(buf, 2)=guild_id;
1003        WBUFL(buf, 6)=account_id;
1004        WBUFL(buf,10)=char_id;
1005        WBUFB(buf,14)=flag;
1006        memcpy(WBUFP(buf,15),mes,40);
1007        memcpy(WBUFP(buf,55),name,NAME_LENGTH);
1008        mapif_sendall(buf,55+NAME_LENGTH);
1009        ShowInfo("int_guild: guild leaved (%d - %d: %s - %s)\n",guild_id,account_id,name,mes);
1010        return 0;
1011}
1012
1013// Send short member's info
1014int mapif_guild_memberinfoshort(struct guild *g,int idx)
1015{
1016        unsigned char buf[19];
1017        WBUFW(buf, 0)=0x3835;
1018        WBUFL(buf, 2)=g->guild_id;
1019        WBUFL(buf, 6)=g->member[idx].account_id;
1020        WBUFL(buf,10)=g->member[idx].char_id;
1021        WBUFB(buf,14)=(unsigned char)g->member[idx].online;
1022        WBUFW(buf,15)=g->member[idx].lv;
1023        WBUFW(buf,17)=g->member[idx].class_;
1024        mapif_sendall(buf,19);
1025        return 0;
1026}
1027
1028// Send guild broken
1029int mapif_guild_broken(int guild_id,int flag)
1030{
1031        unsigned char buf[7];
1032        WBUFW(buf,0)=0x3836;
1033        WBUFL(buf,2)=guild_id;
1034        WBUFB(buf,6)=flag;
1035        mapif_sendall(buf,7);
1036        ShowInfo("int_guild: Guild broken (%d)\n",guild_id);
1037        return 0;
1038}
1039
1040// Send guild message
1041int mapif_guild_message(int guild_id,int account_id,char *mes,int len, int sfd)
1042{
1043        unsigned char buf[512];
1044        if (len > 500)
1045                len = 500;
1046        WBUFW(buf,0)=0x3837;
1047        WBUFW(buf,2)=len+12;
1048        WBUFL(buf,4)=guild_id;
1049        WBUFL(buf,8)=account_id;
1050        memcpy(WBUFP(buf,12),mes,len);
1051        mapif_sendallwos(sfd, buf,len+12);
1052        return 0;
1053}
1054
1055// Send basic info
1056int mapif_guild_basicinfochanged(int guild_id,int type,const void *data,int len)
1057{
1058        unsigned char buf[2048];
1059        if (len > 2038)
1060                len = 2038;
1061        WBUFW(buf, 0)=0x3839;
1062        WBUFW(buf, 2)=len+10;
1063        WBUFL(buf, 4)=guild_id;
1064        WBUFW(buf, 8)=type;
1065        memcpy(WBUFP(buf,10),data,len);
1066        mapif_sendall(buf,len+10);
1067        return 0;
1068}
1069
1070// Send member info
1071int mapif_guild_memberinfochanged(int guild_id,int account_id,int char_id, int type,const void *data,int len)
1072{
1073        unsigned char buf[2048];
1074        if (len > 2030)
1075                len = 2030;
1076        WBUFW(buf, 0)=0x383a;
1077        WBUFW(buf, 2)=len+18;
1078        WBUFL(buf, 4)=guild_id;
1079        WBUFL(buf, 8)=account_id;
1080        WBUFL(buf,12)=char_id;
1081        WBUFW(buf,16)=type;
1082        memcpy(WBUFP(buf,18),data,len);
1083        mapif_sendall(buf,len+18);
1084        return 0;
1085}
1086
1087// ACK guild skill up
1088int mapif_guild_skillupack(int guild_id,int skill_num,int account_id)
1089{
1090        unsigned char buf[14];
1091        WBUFW(buf, 0)=0x383c;
1092        WBUFL(buf, 2)=guild_id;
1093        WBUFL(buf, 6)=skill_num;
1094        WBUFL(buf,10)=account_id;
1095        mapif_sendall(buf,14);
1096        return 0;
1097}
1098
1099// ACK guild alliance
1100int mapif_guild_alliance(int guild_id1,int guild_id2,int account_id1,int account_id2,int flag,const char *name1,const char *name2)
1101{
1102        unsigned char buf[19+2*NAME_LENGTH];
1103        WBUFW(buf, 0)=0x383d;
1104        WBUFL(buf, 2)=guild_id1;
1105        WBUFL(buf, 6)=guild_id2;
1106        WBUFL(buf,10)=account_id1;
1107        WBUFL(buf,14)=account_id2;
1108        WBUFB(buf,18)=flag;
1109        memcpy(WBUFP(buf,19),name1,NAME_LENGTH);
1110        memcpy(WBUFP(buf,19+NAME_LENGTH),name2,NAME_LENGTH);
1111        mapif_sendall(buf,19+2*NAME_LENGTH);
1112        return 0;
1113}
1114
1115// Send a guild position desc
1116int mapif_guild_position(struct guild *g,int idx)
1117{
1118        unsigned char buf[12 + sizeof(struct guild_position)];
1119        WBUFW(buf,0)=0x383b;
1120        WBUFW(buf,2)=sizeof(struct guild_position)+12;
1121        WBUFL(buf,4)=g->guild_id;
1122        WBUFL(buf,8)=idx;
1123        memcpy(WBUFP(buf,12),&g->position[idx],sizeof(struct guild_position));
1124        mapif_sendall(buf,WBUFW(buf,2));
1125        return 0;
1126}
1127
1128// Send the guild notice
1129int mapif_guild_notice(struct guild *g)
1130{
1131        unsigned char buf[256];
1132        WBUFW(buf,0)=0x383e;
1133        WBUFL(buf,2)=g->guild_id;
1134        memcpy(WBUFP(buf,6),g->mes1,60);
1135        memcpy(WBUFP(buf,66),g->mes2,120);
1136        mapif_sendall(buf,186);
1137        return 0;
1138}
1139
1140// Send emblem data
1141int mapif_guild_emblem(struct guild *g)
1142{
1143        unsigned char buf[12 + sizeof(g->emblem_data)];
1144        WBUFW(buf,0)=0x383f;
1145        WBUFW(buf,2)=g->emblem_len+12;
1146        WBUFL(buf,4)=g->guild_id;
1147        WBUFL(buf,8)=g->emblem_id;
1148        memcpy(WBUFP(buf,12),g->emblem_data,g->emblem_len);
1149        mapif_sendall(buf,WBUFW(buf,2));
1150        return 0;
1151}
1152
1153int mapif_guild_master_changed(struct guild *g, int aid, int cid)
1154{
1155        unsigned char buf[14];
1156        WBUFW(buf,0)=0x3843;
1157        WBUFL(buf,2)=g->guild_id;
1158        WBUFL(buf,6)=aid;
1159        WBUFL(buf,10)=cid;
1160        mapif_sendall(buf,14);
1161        return 0;
1162}
1163
1164int mapif_guild_castle_dataload(int castle_id,int index,int value)
1165{
1166        unsigned char buf[9];
1167        WBUFW(buf, 0)=0x3840;
1168        WBUFW(buf, 2)=castle_id;
1169        WBUFB(buf, 4)=index;
1170        WBUFL(buf, 5)=value;
1171        mapif_sendall(buf,9);
1172        return 0;
1173}
1174
1175int mapif_guild_castle_datasave(int castle_id,int index,int value)
1176{
1177        unsigned char buf[9];
1178        WBUFW(buf, 0)=0x3841;
1179        WBUFW(buf, 2)=castle_id;
1180        WBUFB(buf, 4)=index;
1181        WBUFL(buf, 5)=value;
1182        mapif_sendall(buf,9);
1183        return 0;
1184}
1185
1186int mapif_guild_castle_alldataload(int fd)
1187{
1188        struct guild_castle s_gc;
1189        struct guild_castle* gc = &s_gc;
1190        int i;
1191        int len;
1192        char* data;
1193
1194        WFIFOHEAD(fd, 4 + MAX_GUILDCASTLE*sizeof(struct guild_castle));
1195        WFIFOW(fd, 0) = 0x3842;
1196        if( SQL_ERROR == Sql_Query(sql_handle,
1197                "SELECT `castle_id`, `guild_id`, `economy`, `defense`, `triggerE`, `triggerD`, `nextTime`, `payTime`, `createTime`,"
1198                " `visibleC`, `visibleG0`, `visibleG1`, `visibleG2`, `visibleG3`, `visibleG4`, `visibleG5`, `visibleG6`, `visibleG7`"
1199                " FROM `%s` ORDER BY `castle_id`", guild_castle_db) )
1200                Sql_ShowDebug(sql_handle);
1201        for( i = 0, len = 4; i < MAX_GUILDCASTLE && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i )
1202        {
1203                memset(gc, 0, sizeof(struct guild_castle));
1204
1205                Sql_GetData(sql_handle,  0, &data, NULL); gc->castle_id = atoi(data);
1206                Sql_GetData(sql_handle,  1, &data, NULL); gc->guild_id = atoi(data);
1207                Sql_GetData(sql_handle,  2, &data, NULL); gc->economy = atoi(data);
1208                Sql_GetData(sql_handle,  3, &data, NULL); gc->defense = atoi(data);
1209                Sql_GetData(sql_handle,  4, &data, NULL); gc->triggerE = atoi(data);
1210                Sql_GetData(sql_handle,  5, &data, NULL); gc->triggerD = atoi(data);
1211                Sql_GetData(sql_handle,  6, &data, NULL); gc->nextTime = atoi(data);
1212                Sql_GetData(sql_handle,  7, &data, NULL); gc->payTime = atoi(data);
1213                Sql_GetData(sql_handle,  8, &data, NULL); gc->createTime = atoi(data);
1214                Sql_GetData(sql_handle,  9, &data, NULL); gc->visibleC = atoi(data);
1215                Sql_GetData(sql_handle, 10, &data, NULL); gc->guardian[0].visible = atoi(data);
1216                Sql_GetData(sql_handle, 11, &data, NULL); gc->guardian[1].visible = atoi(data);
1217                Sql_GetData(sql_handle, 12, &data, NULL); gc->guardian[2].visible = atoi(data);
1218                Sql_GetData(sql_handle, 13, &data, NULL); gc->guardian[3].visible = atoi(data);
1219                Sql_GetData(sql_handle, 14, &data, NULL); gc->guardian[4].visible = atoi(data);
1220                Sql_GetData(sql_handle, 15, &data, NULL); gc->guardian[5].visible = atoi(data);
1221                Sql_GetData(sql_handle, 16, &data, NULL); gc->guardian[6].visible = atoi(data);
1222                Sql_GetData(sql_handle, 17, &data, NULL); gc->guardian[7].visible = atoi(data);
1223
1224                memcpy(WFIFOP(fd, len), gc, sizeof(struct guild_castle));
1225                len += sizeof(struct guild_castle);
1226        }
1227        Sql_FreeResult(sql_handle);
1228        WFIFOW(fd, 2) = len;
1229        WFIFOSET(fd, len);
1230       
1231        return 0;
1232}
1233
1234
1235//-------------------------------------------------------------------
1236// Packet received from map server
1237
1238
1239// ƒMƒ‹ƒhì¬—v‹
1240int mapif_parse_CreateGuild(int fd,int account_id,char *name,struct guild_member *master)
1241{
1242        struct guild *g;
1243        int i=0;
1244#ifdef NOISY
1245        ShowInfo("Creating Guild (%s)\n", name);
1246#endif
1247        if(search_guildname(name) != 0){
1248                ShowInfo("int_guild: guild with same name exists [%s]\n",name);
1249                mapif_guild_created(fd,account_id,NULL);
1250                return 0;
1251        }
1252        // Check Authorised letters/symbols in the name of the character
1253        if (char_name_option == 1) { // only letters/symbols in char_name_letters are authorised
1254                for (i = 0; i < NAME_LENGTH && name[i]; i++)
1255                        if (strchr(char_name_letters, name[i]) == NULL) {
1256                                mapif_guild_created(fd,account_id,NULL);
1257                                return 0;
1258                        }
1259        } else if (char_name_option == 2) { // letters/symbols in char_name_letters are forbidden
1260                for (i = 0; i < NAME_LENGTH && name[i]; i++)
1261                        if (strchr(char_name_letters, name[i]) != NULL) {
1262                                mapif_guild_created(fd,account_id,NULL);
1263                                return 0;
1264                        }
1265        }
1266
1267        g = (struct guild *)aMalloc(sizeof(struct guild));
1268        memset(g,0,sizeof(struct guild));
1269
1270        memcpy(g->name,name,NAME_LENGTH);
1271        memcpy(g->master,master->name,NAME_LENGTH);
1272        memcpy(&g->member[0],master,sizeof(struct guild_member));
1273        g->member[0].modified = GS_MEMBER_MODIFIED;
1274
1275        // Set default positions
1276        g->position[0].mode=0x11;
1277        strcpy(g->position[0].name,"GuildMaster");
1278        strcpy(g->position[MAX_GUILDPOSITION-1].name,"Newbie");
1279        g->position[0].modified = g->position[MAX_GUILDPOSITION-1].modified = GS_POSITION_MODIFIED;
1280        for(i=1;i<MAX_GUILDPOSITION-1;i++) {
1281                sprintf(g->position[i].name,"Position %d",i+1);
1282                g->position[i].modified = GS_POSITION_MODIFIED;
1283        }
1284
1285        // Initialize guild property
1286        g->max_member=16;
1287        g->average_lv=master->lv;
1288        g->connect_member=1;
1289
1290        for(i=0;i<MAX_GUILDSKILL;i++)
1291                g->skill[i].id=i + GD_SKILLBASE;
1292        g->guild_id= -1; //Request to create guild.
1293
1294        // Create the guild
1295        if (!inter_guild_tosql(g,GS_BASIC|GS_POSITION|GS_SKILL)) {
1296                //Failed to Create guild....
1297                ShowError("Failed to create Guild %s (Guild Master: %s)\n", g->name, g->master);
1298                mapif_guild_created(fd,account_id,NULL);
1299                aFree(g);
1300                return 0;
1301        }
1302        ShowInfo("Created Guild %d - %s (Guild Master: %s)\n", g->guild_id, g->name, g->master);
1303       
1304        //Add to cache
1305        idb_put(guild_db_, g->guild_id, g);
1306
1307        // Report to client
1308        mapif_guild_created(fd,account_id,g);
1309        mapif_guild_info(fd,g);
1310
1311        if(log_inter)
1312                inter_log("guild %s (id=%d) created by master %s (id=%d)\n",
1313                        name, g->guild_id, master->name, master->account_id );
1314
1315        return 0;
1316}
1317
1318// Return guild info to client
1319int mapif_parse_GuildInfo(int fd,int guild_id)
1320{
1321        struct guild * g = inter_guild_fromsql(guild_id); //We use this because on start-up the info of castle-owned guilds is requied. [Skotlex]
1322        if(g)
1323        {
1324                if (!guild_calcinfo(g))
1325                        mapif_guild_info(fd,g);
1326        }
1327        else
1328                mapif_guild_noinfo(fd,guild_id); // Failed to load info
1329        return 0;
1330}
1331
1332// Add member to guild
1333int mapif_parse_GuildAddMember(int fd,int guild_id,struct guild_member *m)
1334{
1335        struct guild * g;
1336        int i;
1337
1338        g = inter_guild_fromsql(guild_id);
1339        if(g==NULL){
1340                // Failed to add
1341                mapif_guild_memberadded(fd,guild_id,m->account_id,m->char_id,1);
1342                return 0;
1343        }
1344
1345        // Find an empty slot
1346        for(i=0;i<g->max_member;i++)
1347        {
1348                if(g->member[i].account_id==0)
1349                {
1350                        memcpy(&g->member[i],m,sizeof(struct guild_member));
1351                        g->member[i].modified = (GS_MEMBER_NEW | GS_MEMBER_MODIFIED);
1352                        mapif_guild_memberadded(fd,guild_id,m->account_id,m->char_id,0);
1353                        if (!guild_calcinfo(g)) //Send members if it was not invoked.
1354                                mapif_guild_info(-1,g);
1355
1356                        g->save_flag |= GS_MEMBER;
1357                        if (g->save_flag&GS_REMOVE)
1358                                g->save_flag&=~GS_REMOVE;
1359                        return 0;
1360                }
1361        }
1362
1363        // Failed to add
1364        mapif_guild_memberadded(fd,guild_id,m->account_id,m->char_id,1);
1365        return 0;
1366}
1367
1368// Delete member from guild
1369int mapif_parse_GuildLeave(int fd, int guild_id, int account_id, int char_id, int flag, const char *mes)
1370{
1371        int i, j;
1372
1373        struct guild* g = inter_guild_fromsql(guild_id);
1374        if( g == NULL )
1375        {
1376                // Unknown guild, just update the player
1377                if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `guild_id`='0' WHERE `account_id`='%d' AND `char_id`='%d'", char_db, account_id, char_id) )
1378                        Sql_ShowDebug(sql_handle);
1379                // mapif_guild_leaved(guild_id,account_id,char_id,flag,g->member[i].name,mes);
1380                return 0;
1381        }
1382
1383        // Find the member
1384        ARR_FIND( 0, g->max_member, i, g->member[i].account_id == account_id && g->member[i].char_id == char_id );
1385        if( i == g->max_member )
1386        {
1387                //TODO
1388                return 0;
1389        }
1390
1391        if( flag )
1392        {       // Write expulsion reason
1393                // Find an empty slot
1394                ARR_FIND( 0, MAX_GUILDEXPULSION, j, g->expulsion[j].account_id == 0 );
1395                if( j == MAX_GUILDEXPULSION )
1396                {
1397                        // Expulsion list is full, flush the oldest one
1398                        for( j = 0; j < MAX_GUILDEXPULSION - 1; j++ )
1399                                g->expulsion[j] = g->expulsion[j+1];
1400                        j = MAX_GUILDEXPULSION-1;
1401                }
1402                // Save the expulsion entry
1403                g->expulsion[j].account_id = account_id;
1404                safestrncpy(g->expulsion[j].name, g->member[i].name, NAME_LENGTH);
1405                safestrncpy(g->expulsion[j].mes, mes, 40);
1406        }
1407
1408        mapif_guild_leaved(guild_id,account_id,char_id,flag,g->member[i].name,mes);
1409        inter_guild_removemember_tosql(g->member[i].account_id,g->member[i].char_id);
1410
1411        memset(&g->member[i],0,sizeof(struct guild_member));
1412
1413        if( guild_check_empty(g) )
1414                mapif_parse_BreakGuild(-1,guild_id); //Break the guild.
1415        else {
1416                //Update member info.
1417                if (!guild_calcinfo(g))
1418                        mapif_guild_info(fd,g);
1419                g->save_flag |= GS_EXPULSION;
1420        }
1421
1422        return 0;
1423}
1424
1425// Change member info
1426int mapif_parse_GuildChangeMemberInfoShort(int fd,int guild_id,int account_id,int char_id,int online,int lv,int class_)
1427{
1428        // Could speed up by manipulating only guild_member
1429        struct guild * g;
1430        int i,sum,c;
1431        int prev_count, prev_alv;
1432
1433        g = inter_guild_fromsql(guild_id);
1434        if(g==NULL)
1435                return 0;
1436       
1437        ARR_FIND( 0, g->max_member, i, g->member[i].account_id == account_id && g->member[i].char_id == char_id );
1438        if( i < g->max_member )
1439        {
1440                g->member[i].online = online;
1441                g->member[i].lv = lv;
1442                g->member[i].class_ = class_;
1443                g->member[i].modified = GS_MEMBER_MODIFIED;
1444                mapif_guild_memberinfoshort(g,i);
1445        }
1446
1447        prev_count = g->connect_member;
1448        prev_alv = g->average_lv;
1449
1450        g->average_lv = 0;
1451        g->connect_member = 0;
1452        c = 0;
1453        sum = 0;
1454
1455        for( i = 0; i < g->max_member; i++ )
1456        {
1457                if( g->member[i].account_id > 0 )
1458                {
1459                        sum += g->member[i].lv;
1460                        c++;
1461                }
1462                if( g->member[i].online )
1463                        g->connect_member++;
1464        }
1465
1466        if( c ) // this check should always succeed...
1467        {
1468                g->average_lv = sum / c;
1469                if( g->connect_member != prev_count || g->average_lv != prev_alv )
1470                        g->save_flag |= GS_CONNECT;
1471                if( g->save_flag & GS_REMOVE )
1472                        g->save_flag &= ~GS_REMOVE;
1473        }
1474        g->save_flag |= GS_MEMBER; //Update guild member data
1475        return 0;
1476}
1477
1478// BreakGuild
1479int mapif_parse_BreakGuild(int fd,int guild_id)
1480{
1481        struct guild * g;
1482       
1483        g = inter_guild_fromsql(guild_id);
1484        if(g==NULL)
1485                return 0;
1486
1487        // Delete guild from sql
1488        //printf("- Delete guild %d from guild\n",guild_id);
1489        if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_db, guild_id) )
1490                Sql_ShowDebug(sql_handle);
1491
1492        if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_member_db, guild_id) )
1493                Sql_ShowDebug(sql_handle);
1494
1495        if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_castle_db, guild_id) )
1496                Sql_ShowDebug(sql_handle);
1497
1498        if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_storage_db, guild_id) )
1499                Sql_ShowDebug(sql_handle);
1500
1501        if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d' OR `alliance_id` = '%d'", guild_alliance_db, guild_id, guild_id) )
1502                Sql_ShowDebug(sql_handle);
1503
1504        if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_position_db, guild_id) )
1505                Sql_ShowDebug(sql_handle);
1506
1507        if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_skill_db, guild_id) )
1508                Sql_ShowDebug(sql_handle);
1509
1510        if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_expulsion_db, guild_id) )
1511                Sql_ShowDebug(sql_handle);
1512
1513        //printf("- Update guild %d of char\n",guild_id);
1514        if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `guild_id`='0' WHERE `guild_id`='%d'", char_db, guild_id) )
1515                Sql_ShowDebug(sql_handle);
1516
1517        mapif_guild_broken(guild_id,0);
1518
1519        if(log_inter)
1520                inter_log("guild %s (id=%d) broken\n",g->name,guild_id);
1521
1522        //Remove the guild from memory. [Skotlex]
1523        idb_remove(guild_db_, guild_id);
1524        return 0;
1525}
1526
1527// Forward Guild message to others map servers
1528int mapif_parse_GuildMessage(int fd,int guild_id,int account_id,char *mes,int len)
1529{
1530        return mapif_guild_message(guild_id,account_id,mes,len, fd);
1531}
1532
1533// Modification of the guild
1534int mapif_parse_GuildBasicInfoChange(int fd,int guild_id,int type,const char *data,int len)
1535{
1536        struct guild * g;
1537        short dw=*((short *)data);
1538        g = inter_guild_fromsql(guild_id);
1539        if(g==NULL)
1540                return 0;
1541
1542        switch(type)
1543        {
1544                case GBI_GUILDLV:
1545                        if(dw>0 && g->guild_lv+dw<=50)
1546                        {
1547                                g->guild_lv+=dw;
1548                                g->skill_point+=dw;
1549                        }
1550                        else if(dw<0 && g->guild_lv+dw>=1)
1551                                g->guild_lv+=dw;
1552                        mapif_guild_info(-1,g);
1553                        g->save_flag |= GS_LEVEL;
1554                        return 0;
1555                default:
1556                        ShowError("int_guild: GuildBasicInfoChange: Unknown type %d\n",type);
1557                        break;
1558        }
1559        mapif_guild_basicinfochanged(guild_id,type,data,len);
1560        return 0;
1561}
1562
1563// Modification of the guild
1564int mapif_parse_GuildMemberInfoChange(int fd,int guild_id,int account_id,int char_id,int type,const char *data,int len)
1565{
1566        // Could make some improvement in speed, because only change guild_member
1567        int i;
1568        struct guild * g;
1569
1570        g = inter_guild_fromsql(guild_id);
1571        if(g==NULL)
1572                return 0;
1573
1574        // Search the member
1575        for(i=0;i<g->max_member;i++)
1576                if(     g->member[i].account_id==account_id &&
1577                        g->member[i].char_id==char_id )
1578                                break;
1579
1580        // Not Found
1581        if(i==g->max_member){
1582                ShowWarning("int_guild: GuildMemberChange: Not found %d,%d in guild (%d - %s)\n",
1583                        account_id,char_id,guild_id,g->name);
1584                return 0;
1585        }
1586
1587        switch(type)
1588        {
1589                case GMI_POSITION:
1590                  {
1591                        g->member[i].position=*((int *)data);
1592                        g->member[i].modified = GS_MEMBER_MODIFIED;
1593                        mapif_guild_memberinfochanged(guild_id,account_id,char_id,type,data,len);
1594                        g->save_flag |= GS_MEMBER;
1595                        break;
1596                  }
1597                case GMI_EXP:
1598                {       // EXP
1599                        unsigned int exp, old_exp=g->member[i].exp;
1600                        g->member[i].exp=*((unsigned int *)data);
1601                        g->member[i].modified = GS_MEMBER_MODIFIED;
1602                        if (g->member[i].exp > old_exp)
1603                        {
1604                                exp = g->member[i].exp - old_exp;
1605
1606                                // Compute gained exp
1607                                if (guild_exp_rate != 100)
1608                                        exp = exp*guild_exp_rate/100;
1609
1610                                // Update guild exp
1611                                if (exp > UINT_MAX - g->exp)
1612                                        g->exp = UINT_MAX;
1613                                else
1614                                        g->exp+=exp;
1615
1616                                guild_calcinfo(g);
1617                                mapif_guild_basicinfochanged(guild_id,GBI_EXP,&g->exp,4);
1618                                g->save_flag |= GS_LEVEL;
1619                        }
1620                        mapif_guild_memberinfochanged(guild_id,account_id,char_id,type,data,len);
1621                        g->save_flag |= GS_MEMBER;
1622                        break;
1623                }
1624                case GMI_HAIR:
1625                {
1626                        g->member[i].hair=*((int *)data);
1627                        g->member[i].modified = GS_MEMBER_MODIFIED;
1628                        mapif_guild_memberinfochanged(guild_id,account_id,char_id,type,data,len);
1629                        g->save_flag |= GS_MEMBER; //Save new data.
1630                        break;
1631                }
1632                case GMI_HAIR_COLOR:
1633                {
1634                        g->member[i].hair_color=*((int *)data);
1635                        g->member[i].modified = GS_MEMBER_MODIFIED;
1636                        mapif_guild_memberinfochanged(guild_id,account_id,char_id,type,data,len);
1637                        g->save_flag |= GS_MEMBER; //Save new data.
1638                        break;
1639                }
1640                case GMI_GENDER:
1641                {
1642                        g->member[i].gender=*((int *)data);
1643                        g->member[i].modified = GS_MEMBER_MODIFIED;
1644                        mapif_guild_memberinfochanged(guild_id,account_id,char_id,type,data,len);
1645                        g->save_flag |= GS_MEMBER; //Save new data.
1646                        break;
1647                }
1648                case GMI_CLASS:
1649                {
1650                        g->member[i].class_=*((int *)data);
1651                        g->member[i].modified = GS_MEMBER_MODIFIED;
1652                        mapif_guild_memberinfochanged(guild_id,account_id,char_id,type,data,len);
1653                        g->save_flag |= GS_MEMBER; //Save new data.
1654                        break;
1655                }
1656                case GMI_LEVEL:
1657                {
1658                        g->member[i].lv=*((int *)data);
1659                        g->member[i].modified = GS_MEMBER_MODIFIED;
1660                        mapif_guild_memberinfochanged(guild_id,account_id,char_id,type,data,len);
1661                        g->save_flag |= GS_MEMBER; //Save new data.
1662                        break;
1663                }
1664                default:
1665                  ShowError("int_guild: GuildMemberInfoChange: Unknown type %d\n",type);
1666                  break;
1667        }
1668        return 0;
1669}
1670
1671int inter_guild_sex_changed(int guild_id,int account_id,int char_id, int gender)
1672{
1673        return mapif_parse_GuildMemberInfoChange(0, guild_id, account_id, char_id, GMI_GENDER, (const char*)&gender, sizeof(gender));
1674}
1675
1676// Change a position desc
1677int mapif_parse_GuildPosition(int fd,int guild_id,int idx,struct guild_position *p)
1678{
1679        // Could make some improvement in speed, because only change guild_position
1680        struct guild * g;
1681
1682        g = inter_guild_fromsql(guild_id);
1683        if(g==NULL || idx<0 || idx>=MAX_GUILDPOSITION)
1684                return 0;
1685
1686        memcpy(&g->position[idx],p,sizeof(struct guild_position));
1687        mapif_guild_position(g,idx);
1688        g->position[idx].modified = GS_POSITION_MODIFIED;
1689        g->save_flag |= GS_POSITION; // Change guild_position
1690        return 0;
1691}
1692
1693// Guild Skill UP
1694int mapif_parse_GuildSkillUp(int fd,int guild_id,int skill_num,int account_id)
1695{
1696        struct guild * g;
1697        int idx = skill_num - GD_SKILLBASE;
1698
1699        g = inter_guild_fromsql(guild_id);
1700        if(g == NULL || idx < 0 || idx >= MAX_GUILDSKILL)
1701                return 0;
1702
1703        if(g->skill_point>0 && g->skill[idx].id>0 && g->skill[idx].lv<10 )
1704        {
1705                g->skill[idx].lv++;
1706                g->skill_point--;
1707                if (!guild_calcinfo(g))
1708                        mapif_guild_info(-1,g);
1709                mapif_guild_skillupack(guild_id,skill_num,account_id);
1710                g->save_flag |= (GS_LEVEL|GS_SKILL); // Change guild & guild_skill
1711        }
1712        return 0;
1713}
1714
1715//Manual deletion of an alliance when partnering guild does not exists. [Skotlex]
1716static int mapif_parse_GuildDeleteAlliance(struct guild *g, int guild_id, int account_id1, int account_id2, int flag)
1717{
1718        int i;
1719        char name[NAME_LENGTH];
1720
1721        ARR_FIND( 0, MAX_GUILDALLIANCE, i, g->alliance[i].guild_id == guild_id );
1722        if( i == MAX_GUILDALLIANCE )
1723                return -1;
1724
1725        strcpy(name, g->alliance[i].name);
1726        g->alliance[i].guild_id=0;
1727       
1728        mapif_guild_alliance(g->guild_id,guild_id,account_id1,account_id2,flag,g->name,name);
1729        g->save_flag |= GS_ALLIANCE;
1730        return 0;
1731}
1732
1733// Alliance modification
1734int mapif_parse_GuildAlliance(int fd,int guild_id1,int guild_id2,int account_id1,int account_id2,int flag)
1735{
1736        // Could speed up
1737        struct guild *g[2];
1738        int j,i;
1739        g[0] = inter_guild_fromsql(guild_id1);
1740        g[1] = inter_guild_fromsql(guild_id2);
1741
1742        if(g[0] && g[1]==NULL && (flag & GUILD_ALLIANCE_REMOVE)) //Requested to remove an alliance with a not found guild.
1743                return mapif_parse_GuildDeleteAlliance(g[0], guild_id2, account_id1, account_id2, flag); //Try to do a manual removal of said guild.
1744               
1745        if(g[0]==NULL || g[1]==NULL)
1746                return 0;
1747
1748        if(flag&GUILD_ALLIANCE_REMOVE)
1749        {
1750                // Remove alliance/opposition, in case of alliance, remove on both side
1751                for(i=0;i<2-(flag&GUILD_ALLIANCE_TYPE_MASK);i++)
1752                {
1753                        ARR_FIND( 0, MAX_GUILDALLIANCE, j, g[i]->alliance[j].guild_id == g[1-i]->guild_id && g[i]->alliance[j].opposition == (flag&GUILD_ALLIANCE_TYPE_MASK) );
1754                        if( j < MAX_GUILDALLIANCE )
1755                                g[i]->alliance[j].guild_id = 0;
1756                }
1757        }
1758        else
1759        {
1760                // Add alliance, in case of alliance, add on both side
1761                for(i=0;i<2-(flag&GUILD_ALLIANCE_TYPE_MASK);i++)
1762                {
1763                        // Search an empty slot
1764                        ARR_FIND( 0, MAX_GUILDALLIANCE, j, g[i]->alliance[j].guild_id == 0 );
1765                        if( j < MAX_GUILDALLIANCE )
1766                        {
1767                                g[i]->alliance[j].guild_id=g[1-i]->guild_id;
1768                                memcpy(g[i]->alliance[j].name,g[1-i]->name,NAME_LENGTH);
1769                                // Set alliance type
1770                                g[i]->alliance[j].opposition = flag&GUILD_ALLIANCE_TYPE_MASK;
1771                        }
1772                }
1773        }
1774
1775        // Send on all map the new alliance/opposition
1776        mapif_guild_alliance(guild_id1,guild_id2,account_id1,account_id2,flag,g[0]->name,g[1]->name);
1777
1778        // Mark the two guild to be saved
1779        g[0]->save_flag |= GS_ALLIANCE;
1780        g[1]->save_flag |= GS_ALLIANCE;
1781        return 0;
1782}
1783
1784// Change guild message
1785int mapif_parse_GuildNotice(int fd,int guild_id,const char *mes1,const char *mes2)
1786{
1787        struct guild *g;
1788
1789        g = inter_guild_fromsql(guild_id);
1790        if(g==NULL)
1791                return 0;
1792
1793        memcpy(g->mes1,mes1,60);
1794        memcpy(g->mes2,mes2,120);
1795        g->save_flag |= GS_MES; //Change mes of guild
1796        return mapif_guild_notice(g);
1797}
1798
1799int mapif_parse_GuildEmblem(int fd,int len,int guild_id,int dummy,const char *data)
1800{
1801        struct guild * g;
1802
1803        g = inter_guild_fromsql(guild_id);
1804        if(g==NULL)
1805                return 0;
1806
1807        if (len > sizeof(g->emblem_data))
1808                len = sizeof(g->emblem_data);
1809
1810        memcpy(g->emblem_data,data,len);
1811        g->emblem_len=len;
1812        g->emblem_id++;
1813        g->save_flag |= GS_EMBLEM;      //Change guild
1814        return mapif_guild_emblem(g);
1815}
1816
1817int mapif_parse_GuildCastleDataLoad(int fd,int castle_id,int index)
1818{
1819        struct guild_castle gc;
1820        if (!inter_guildcastle_fromsql(castle_id, &gc)) {
1821                return mapif_guild_castle_dataload(castle_id,0,0);
1822        }
1823        switch(index){
1824        case 1: return mapif_guild_castle_dataload(gc.castle_id,index,gc.guild_id); break;
1825        case 2: return mapif_guild_castle_dataload(gc.castle_id,index,gc.economy); break;
1826        case 3: return mapif_guild_castle_dataload(gc.castle_id,index,gc.defense); break;
1827        case 4: return mapif_guild_castle_dataload(gc.castle_id,index,gc.triggerE); break;
1828        case 5: return mapif_guild_castle_dataload(gc.castle_id,index,gc.triggerD); break;
1829        case 6: return mapif_guild_castle_dataload(gc.castle_id,index,gc.nextTime); break;
1830        case 7: return mapif_guild_castle_dataload(gc.castle_id,index,gc.payTime); break;
1831        case 8: return mapif_guild_castle_dataload(gc.castle_id,index,gc.createTime); break;
1832        case 9: return mapif_guild_castle_dataload(gc.castle_id,index,gc.visibleC); break;
1833        case 10:
1834        case 11:
1835        case 12:
1836        case 13:
1837        case 14:
1838        case 15:
1839        case 16:
1840        case 17:
1841                return mapif_guild_castle_dataload(gc.castle_id,index,gc.guardian[index-10].visible); break;
1842        default:
1843                ShowError("mapif_parse_GuildCastleDataLoad ERROR!! (Not found index=%d)\n", index);
1844                return 0;
1845        }
1846}
1847
1848int mapif_parse_GuildCastleDataSave(int fd,int castle_id,int index,int value)
1849{
1850        struct guild_castle gc;
1851        if(!inter_guildcastle_fromsql(castle_id, &gc))
1852                return mapif_guild_castle_datasave(castle_id,index,value);
1853
1854        switch(index){
1855        case 1:
1856                if( gc.guild_id!=value ){
1857                        int gid=(value)?value:gc.guild_id;
1858                        struct guild *g = (struct guild*)idb_get(guild_db_, gid);
1859                        if(log_inter)
1860                                inter_log("guild %s (id=%d) %s castle id=%d\n",
1861                                        (g)?g->name:"??" ,gid, (value)?"occupy":"abandon", castle_id);
1862                }
1863                gc.guild_id = value;
1864                if(gc.guild_id == 0) {
1865                        //Delete guardians.
1866                        memset(&gc.guardian, 0, sizeof(gc.guardian));
1867                }
1868                break;
1869        case 2: gc.economy = value; break;
1870        case 3: gc.defense = value; break;
1871        case 4: gc.triggerE = value; break;
1872        case 5: gc.triggerD = value; break;
1873        case 6: gc.nextTime = value; break;
1874        case 7: gc.payTime = value; break;
1875        case 8: gc.createTime = value; break;
1876        case 9: gc.visibleC = value; break;
1877        case 10:
1878        case 11:
1879        case 12:
1880        case 13:
1881        case 14:
1882        case 15:
1883        case 16:
1884        case 17:
1885                gc.guardian[index-10].visible = value; break;
1886        default:
1887                ShowError("mapif_parse_GuildCastleDataSave ERROR!! (Not found index=%d)\n", index);
1888                return 0;
1889        }
1890        inter_guildcastle_tosql(&gc);
1891        mapif_guild_castle_datasave(gc.castle_id,index,value);
1892        return 0;
1893}
1894
1895int mapif_parse_GuildMasterChange(int fd, int guild_id, const char* name, int len)
1896{
1897        struct guild * g;
1898        struct guild_member gm;
1899        int pos;
1900
1901        g = inter_guild_fromsql(guild_id);
1902       
1903        if(g==NULL || len > NAME_LENGTH)
1904                return 0;
1905       
1906        // Find member (name)
1907        for (pos = 0; pos < g->max_member && strncmp(g->member[pos].name, name, len); pos++);
1908
1909        if (pos == g->max_member)
1910                return 0; //Character not found??
1911       
1912        // Switch current and old GM
1913        memcpy(&gm, &g->member[pos], sizeof (struct guild_member));
1914        memcpy(&g->member[pos], &g->member[0], sizeof(struct guild_member));
1915        memcpy(&g->member[0], &gm, sizeof(struct guild_member));
1916
1917        // Switch positions
1918        g->member[pos].position = g->member[0].position;
1919        g->member[pos].modified = GS_MEMBER_MODIFIED;
1920        g->member[0].position = 0; //Position 0: guild Master.
1921        g->member[0].modified = GS_MEMBER_MODIFIED;
1922
1923        strncpy(g->master, name, len);
1924        if (len < NAME_LENGTH)
1925                g->master[len] = '\0';
1926
1927        ShowInfo("int_guild: Guildmaster Changed to %s (Guild %d - %s)\n",g->master, guild_id, g->name);
1928        g->save_flag |= (GS_BASIC|GS_MEMBER); //Save main data and member data.
1929        return mapif_guild_master_changed(g, g->member[0].account_id, g->member[0].char_id);
1930}
1931
1932// map server ‚©‚ç‚̒ʐM
1933// E‚PƒpƒPƒbƒg‚̂݉ðÍ‚·‚邱‚Æ
1934// EƒpƒPƒbƒg’·ƒf[ƒ^‚Íinter.c‚ɃZƒbƒg‚µ‚Ä‚š‚­‚±‚Æ
1935// EƒpƒPƒbƒg’·ƒ`ƒFƒbƒN‚âARFIFOSKIP‚͌Ăяo‚µŒ³‚ōs‚í‚ê‚é‚̂ōs‚Á‚Ă͂Ȃç‚È‚¢
1936// EƒGƒ‰[‚È‚ç0(false)A‚»‚€‚łȂ¢‚È‚ç1(true)‚ð‚©‚Š‚³‚È‚¯‚ê‚΂Ȃç‚È‚¢
1937int inter_guild_parse_frommap(int fd)
1938{
1939        RFIFOHEAD(fd);
1940        switch(RFIFOW(fd,0)) {
1941        case 0x3030: mapif_parse_CreateGuild(fd,RFIFOL(fd,4),(char*)RFIFOP(fd,8),(struct guild_member *)RFIFOP(fd,32)); break;
1942        case 0x3031: mapif_parse_GuildInfo(fd,RFIFOL(fd,2)); break;
1943        case 0x3032: mapif_parse_GuildAddMember(fd,RFIFOL(fd,4),(struct guild_member *)RFIFOP(fd,8)); break;
1944        case 0x3033: mapif_parse_GuildMasterChange(fd,RFIFOL(fd,4),(const char*)RFIFOP(fd,8),RFIFOW(fd,2)-8); break;
1945        case 0x3034: mapif_parse_GuildLeave(fd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14),(const char*)RFIFOP(fd,15)); break;
1946        case 0x3035: mapif_parse_GuildChangeMemberInfoShort(fd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14),RFIFOW(fd,15),RFIFOW(fd,17)); break;
1947        case 0x3036: mapif_parse_BreakGuild(fd,RFIFOL(fd,2)); break;
1948        case 0x3037: mapif_parse_GuildMessage(fd,RFIFOL(fd,4),RFIFOL(fd,8),(char*)RFIFOP(fd,12),RFIFOW(fd,2)-12); break;
1949        case 0x3039: mapif_parse_GuildBasicInfoChange(fd,RFIFOL(fd,4),RFIFOW(fd,8),(const char*)RFIFOP(fd,10),RFIFOW(fd,2)-10); break;
1950        case 0x303A: mapif_parse_GuildMemberInfoChange(fd,RFIFOL(fd,4),RFIFOL(fd,8),RFIFOL(fd,12),RFIFOW(fd,16),(const char*)RFIFOP(fd,18),RFIFOW(fd,2)-18); break;
1951        case 0x303B: mapif_parse_GuildPosition(fd,RFIFOL(fd,4),RFIFOL(fd,8),(struct guild_position *)RFIFOP(fd,12)); break;
1952        case 0x303C: mapif_parse_GuildSkillUp(fd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); break;
1953        case 0x303D: mapif_parse_GuildAlliance(fd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOL(fd,14),RFIFOB(fd,18)); break;
1954        case 0x303E: mapif_parse_GuildNotice(fd,RFIFOL(fd,2),(const char*)RFIFOP(fd,6),(const char*)RFIFOP(fd,66)); break;
1955        case 0x303F: mapif_parse_GuildEmblem(fd,RFIFOW(fd,2)-12,RFIFOL(fd,4),RFIFOL(fd,8),(const char*)RFIFOP(fd,12)); break;
1956        case 0x3040: mapif_parse_GuildCastleDataLoad(fd,RFIFOW(fd,2),RFIFOB(fd,4)); break;
1957        case 0x3041: mapif_parse_GuildCastleDataSave(fd,RFIFOW(fd,2),RFIFOB(fd,4),RFIFOL(fd,5)); break;
1958
1959        default:
1960                return 0;
1961        }
1962
1963        return 1;
1964}
1965
1966// processes a mapserver connection event
1967int inter_guild_mapif_init(int fd)
1968{
1969        return mapif_guild_castle_alldataload(fd);
1970}
1971
1972// ƒT[ƒo[‚©‚ç’E‘Þ—v‹iƒLƒƒƒ‰íœ—pj
1973int inter_guild_leave(int guild_id, int account_id, int char_id)
1974{
1975        return mapif_parse_GuildLeave(-1, guild_id, account_id, char_id, 0, "** Character Deleted **");
1976}
1977
1978int inter_guild_broken(int guild_id)
1979{
1980        return mapif_guild_broken(guild_id, 0);
1981}
1982#endif //TXT_SQL_CONVERT
Note: See TracBrowser for help on using the browser.