root/src/char_sql/int_party.c @ 18

Revision 1, 25.1 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/db.h"
7#include "../common/malloc.h"
8#include "../common/strlib.h"
9#include "../common/socket.h"
10#include "../common/showmsg.h"
11#include "../common/mapindex.h"
12#include "../common/sql.h"
13#include "char.h"
14#include "inter.h"
15#include "int_party.h"
16
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20
21#ifndef TXT_SQL_CONVERT
22struct party_data {
23        struct party party;
24        unsigned int min_lv, max_lv;
25        int family; //Is this party a family? if so, this holds the child id.
26        unsigned char size; //Total size of party.
27};
28
29static struct party_data *party_pt;
30static DBMap* party_db_; // int party_id -> struct party_data*
31
32int mapif_party_broken(int party_id,int flag);
33int party_check_empty(struct party_data *p);
34int mapif_parse_PartyLeave(int fd, int party_id, int account_id, int char_id);
35int party_check_exp_share(struct party_data *p);
36int mapif_party_optionchanged(int fd,struct party *p, int account_id, int flag);
37
38//Updates party's level range and unsets even share if broken.
39static int int_party_check_lv(struct party_data *p) {
40        int i;
41        unsigned int lv;
42        p->min_lv = UINT_MAX;
43        p->max_lv = 0;
44        for(i=0;i<MAX_PARTY;i++){
45                if(!p->party.member[i].online)
46                        continue;
47
48                lv=p->party.member[i].lv;
49                if (lv < p->min_lv) p->min_lv = lv;
50                if (lv > p->max_lv) p->max_lv = lv;
51        }
52
53        if (p->party.exp && !party_check_exp_share(p)) {
54                p->party.exp = 0;
55                mapif_party_optionchanged(0, &p->party, 0, 0);
56                return 0;
57        }
58        return 1;
59}
60//Calculates the state of a party.
61static void int_party_calc_state(struct party_data *p)
62{
63        int i;
64        unsigned int lv;
65        p->min_lv = UINT_MAX;
66        p->max_lv = 0;
67        p->party.count =
68        p->size =
69        p->family = 0;
70
71        //Check party size
72        for(i=0;i<MAX_PARTY;i++){
73                if (!p->party.member[i].lv) continue;
74                p->size++;
75                if(p->party.member[i].online)
76                        p->party.count++;
77        }
78        if(p->size == 3) {
79                //Check Family State.
80                p->family = char_family(
81                        p->party.member[0].char_id,
82                        p->party.member[1].char_id,
83                        p->party.member[2].char_id
84                );
85        }
86        //max/min levels.
87        for(i=0;i<MAX_PARTY;i++){
88                lv=p->party.member[i].lv;
89                if (!lv) continue;
90                if(p->party.member[i].online &&
91                        //On families, the kid is not counted towards exp share rules.
92                        p->party.member[i].char_id != p->family)
93                {
94                        if( lv < p->min_lv ) p->min_lv=lv;
95                        if( p->max_lv < lv ) p->max_lv=lv;
96                }
97        }
98
99        if (p->party.exp && !party_check_exp_share(p)) {
100                p->party.exp = 0; //Set off even share.
101                mapif_party_optionchanged(0, &p->party, 0, 0);
102        }
103        return;
104}
105#endif //TXT_SQL_CONVERT
106// Save party to mysql
107int inter_party_tosql(struct party *p, int flag, int index)
108{
109        // 'party' ('party_id','name','exp','item','leader_id','leader_char')
110        char esc_name[NAME_LENGTH*2+1];// escaped party name
111        int party_id;
112
113        if( p == NULL || p->party_id == 0 )
114                return 0;
115        party_id = p->party_id;
116
117#ifdef NOISY
118        ShowInfo("Save party request ("CL_BOLD"%d"CL_RESET" - %s).\n", party_id, p->name);
119#endif
120        Sql_EscapeStringLen(sql_handle, esc_name, p->name, strnlen(p->name, NAME_LENGTH));
121
122#ifndef TXT_SQL_CONVERT
123        if( flag & PS_BREAK )
124        {// Break the party
125                // we'll skip name-checking and just reset everyone with the same party id [celest]
126                if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d'", char_db, party_id) )
127                        Sql_ShowDebug(sql_handle);
128                if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `party_id`='%d'", party_db, party_id) )
129                        Sql_ShowDebug(sql_handle);
130                //Remove from memory
131                idb_remove(party_db_, party_id);
132                return 1;
133        }
134#endif //TXT_SQL_CONVERT
135        if( flag & PS_CREATE )
136        {// Create party
137#ifndef TXT_SQL_CONVERT
138                if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` "
139                        "(`name`, `exp`, `item`, `leader_id`, `leader_char`) "
140                        "VALUES ('%s', '%d', '%d', '%d', '%d')",
141                        party_db, esc_name, p->exp, p->item, p->member[index].account_id, p->member[index].char_id) )
142                {
143                        Sql_ShowDebug(sql_handle);
144                        return 0;
145                }
146                party_id = p->party_id = (int)Sql_LastInsertId(sql_handle);
147#else
148                //During conversion, you want to specify the id, and allow overwriting
149                //(in case someone is re-running the process.
150
151                if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` "
152                        "(`party_id`, `name`, `exp`, `item`, `leader_id`, `leader_char`) "
153                        "VALUES ('%d', '%s', '%d', '%d', '%d', '%d')",
154                        party_db, p->party_id, esc_name, p->exp, p->item, p->member[index].account_id, p->member[index].char_id) )
155                {
156                        Sql_ShowDebug(sql_handle);
157                        return 0;
158                }
159#endif
160        }
161
162#ifndef TXT_SQL_CONVERT
163        if( flag & PS_BASIC )
164        {// Update party info.
165                if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `name`='%s', `exp`='%d', `item`='%d' WHERE `party_id`='%d'",
166                        party_db, esc_name, p->exp, p->item, party_id) )
167                        Sql_ShowDebug(sql_handle);
168        }
169
170        if( flag & PS_LEADER )
171        {// Update leader
172                if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s`  SET `leader_id`='%d', `leader_char`='%d' WHERE `party_id`='%d'",
173                        party_db, p->member[index].account_id, p->member[index].char_id, party_id) )
174                        Sql_ShowDebug(sql_handle);
175        }
176       
177        if( flag & PS_ADDMEMBER )
178        {// Add one party member.
179                if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='%d' WHERE `account_id`='%d' AND `char_id`='%d'",
180                        char_db, party_id, p->member[index].account_id, p->member[index].char_id) )
181                        Sql_ShowDebug(sql_handle);
182        }
183
184        if( flag & PS_DELMEMBER )
185        {// Remove one party member.
186                if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d' AND `account_id`='%d' AND `char_id`='%d'",
187                        char_db, party_id, p->member[index].account_id, p->member[index].char_id) )
188                        Sql_ShowDebug(sql_handle);
189        }
190#endif //TXT_SQL_CONVERT
191        if( save_log )
192                ShowInfo("Party Saved (%d - %s)\n", party_id, p->name);
193        return 1;
194}
195#ifndef TXT_SQL_CONVERT
196// Read party from mysql
197struct party_data *inter_party_fromsql(int party_id)
198{
199        int leader_id = 0;
200        int leader_char = 0;
201        struct party_data* p;
202        struct party_member* m;
203        char* data;
204        size_t len;
205        int i;
206
207#ifdef NOISY
208        ShowInfo("Load party request ("CL_BOLD"%d"CL_RESET")\n", party_id);
209#endif
210        if( party_id <= 0 )
211                return NULL;
212       
213        //Load from memory
214        p = (struct party_data*)idb_get(party_db_, party_id);
215        if( p != NULL )
216                return p;
217
218        p = party_pt;
219        memset(p, 0, sizeof(struct party_data));
220
221        if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `party_id`, `name`,`exp`,`item`, `leader_id`, `leader_char` FROM `%s` WHERE `party_id`='%d'", party_db, party_id) )
222        {
223                Sql_ShowDebug(sql_handle);
224                return NULL;
225        }
226
227        if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
228                return NULL;
229
230        p->party.party_id = party_id;
231        Sql_GetData(sql_handle, 1, &data, &len); memcpy(p->party.name, data, min(len, NAME_LENGTH));
232        Sql_GetData(sql_handle, 2, &data, NULL); p->party.exp = (atoi(data) ? 1 : 0);
233        Sql_GetData(sql_handle, 3, &data, NULL); p->party.item = atoi(data);
234        Sql_GetData(sql_handle, 4, &data, NULL); leader_id = atoi(data);
235        Sql_GetData(sql_handle, 5, &data, NULL); leader_char = atoi(data);
236        Sql_FreeResult(sql_handle);
237
238        // Load members
239        if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`char_id`,`name`,`base_level`,`last_map`,`online`,`class` FROM `%s` WHERE `party_id`='%d'", char_db, party_id) )
240        {
241                Sql_ShowDebug(sql_handle);
242                return NULL;
243        }
244        for( i = 0; i < MAX_PARTY && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i )
245        {
246                m = &p->party.member[i];
247                Sql_GetData(sql_handle, 0, &data, NULL); m->account_id = atoi(data);
248                Sql_GetData(sql_handle, 1, &data, NULL); m->char_id = atoi(data);
249                Sql_GetData(sql_handle, 2, &data, &len); memcpy(m->name, data, min(len, NAME_LENGTH));
250                Sql_GetData(sql_handle, 3, &data, NULL); m->lv = atoi(data);
251                Sql_GetData(sql_handle, 4, &data, NULL); m->map = mapindex_name2id(data);
252                Sql_GetData(sql_handle, 5, &data, NULL); m->online = (atoi(data) ? 1 : 0);
253                Sql_GetData(sql_handle, 6, &data, NULL); m->class_ = atoi(data);
254                m->leader = (m->account_id == leader_id && m->char_id == leader_char ? 1 : 0);
255        }
256        Sql_FreeResult(sql_handle);
257
258        if( save_log )
259                ShowInfo("Party loaded (%d - %s).\n", party_id, p->party.name);
260        //Add party to memory.
261        CREATE(p, struct party_data, 1);
262        memcpy(p, party_pt, sizeof(struct party_data));
263        //init state
264        int_party_calc_state(p);
265        idb_put(party_db_, party_id, p);
266        return p;
267}
268
269int inter_party_sql_init(void)
270{
271        //memory alloc
272        party_db_ = idb_alloc(DB_OPT_RELEASE_DATA);
273        party_pt = (struct party_data*)aCalloc(sizeof(struct party_data), 1);
274        if (!party_pt) {
275                ShowFatalError("inter_party_sql_init: Out of Memory!\n");
276                exit(EXIT_FAILURE);
277        }
278
279        /* Uncomment the following if you want to do a party_db cleanup (remove parties with no members) on startup.[Skotlex]
280        ShowStatus("cleaning party table...\n");
281        if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` USING `%s` LEFT JOIN `%s` ON `%s`.leader_id =`%s`.account_id AND `%s`.leader_char = `%s`.char_id WHERE `%s`.account_id IS NULL",
282                party_db, party_db, char_db, party_db, char_db, party_db, char_db, char_db) )
283                Sql_ShowDebug(sql_handle);
284        */
285        return 0;
286}
287
288void inter_party_sql_final(void)
289{
290        party_db_->destroy(party_db_, NULL);
291        aFree(party_pt);
292        return;
293}
294
295// Search for the party according to its name
296struct party_data* search_partyname(char* str)
297{
298        char esc_name[NAME_LENGTH*2+1];
299        char* data;
300        struct party_data* p = NULL;
301
302        Sql_EscapeStringLen(sql_handle, esc_name, str, safestrnlen(str, NAME_LENGTH));
303        if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `party_id` FROM `%s` WHERE `name`='%s'", party_db, esc_name) )
304                Sql_ShowDebug(sql_handle);
305        else if( SQL_SUCCESS == Sql_NextRow(sql_handle) )
306        {
307                Sql_GetData(sql_handle, 0, &data, NULL);
308                p = inter_party_fromsql(atoi(data));
309        }
310        Sql_FreeResult(sql_handle);
311
312        return p;
313}
314
315// Returns whether this party can keep having exp share or not.
316int party_check_exp_share(struct party_data *p)
317{
318        return (p->party.count < 2 || p->max_lv - p->min_lv <= party_share_level);
319}
320
321// Is there any member in the party?
322int party_check_empty(struct party_data *p)
323{
324        int i;
325        if (p==NULL||p->party.party_id==0) return 1;
326        for(i=0;i<MAX_PARTY && !p->party.member[i].account_id;i++);
327        if (i < MAX_PARTY) return 0;
328        // If there is no member, then break the party
329        mapif_party_broken(p->party.party_id,0);
330        inter_party_tosql(&p->party, PS_BREAK, 0);
331        return 1;
332}
333
334
335// Check if a member is in two party, not necessary :)
336int party_check_conflict(int party_id,int account_id,int char_id)
337{
338        return 0;
339}
340
341//-------------------------------------------------------------------
342// map server‚ւ̒ʐM
343
344// ƒp[ƒeƒBì¬‰Â”Û
345int mapif_party_created(int fd,int account_id,int char_id,struct party *p)
346{
347        WFIFOHEAD(fd, 39);
348        WFIFOW(fd,0)=0x3820;
349        WFIFOL(fd,2)=account_id;
350        WFIFOL(fd,6)=char_id;
351        if(p!=NULL){
352                WFIFOB(fd,10)=0;
353                WFIFOL(fd,11)=p->party_id;
354                memcpy(WFIFOP(fd,15),p->name,NAME_LENGTH);
355                ShowInfo("int_party: Party created (%d - %s)\n",p->party_id,p->name);
356        }else{
357                WFIFOB(fd,10)=1;
358                WFIFOL(fd,11)=0;
359                memset(WFIFOP(fd,15),0,NAME_LENGTH);
360        }
361        WFIFOSET(fd,39);
362
363        return 0;
364}
365
366// ƒp[ƒeƒBî•ñŒ©‚‚©‚炞
367int mapif_party_noinfo(int fd,int party_id)
368{
369        WFIFOHEAD(fd,8);
370        WFIFOW(fd,0)=0x3821;
371        WFIFOW(fd,2)=8;
372        WFIFOL(fd,4)=party_id;
373        WFIFOSET(fd,8);
374        ShowWarning("int_party: info not found %d\n",party_id);
375        return 0;
376}
377// ƒp[ƒeƒBî•ñ‚܂Ƃߑ—‚è
378int mapif_party_info(int fd,struct party *p)
379{
380        unsigned char buf[5+sizeof(struct party)];
381        WBUFW(buf,0)=0x3821;
382        WBUFW(buf,2)=4+sizeof(struct party);
383        memcpy(buf+4,p,sizeof(struct party));
384
385        if(fd<0)
386                mapif_sendall(buf,WBUFW(buf,2));
387        else
388                mapif_send(fd,buf,WBUFW(buf,2));
389        return 0;
390}
391// ƒp[ƒeƒBƒƒ“ƒo’ljÁ‰Â”Û
392int mapif_party_memberadded(int fd, int party_id, int account_id, int char_id, int flag) {
393        WFIFOHEAD(fd, 15);
394        WFIFOW(fd,0) = 0x3822;
395        WFIFOL(fd,2) = party_id;
396        WFIFOL(fd,6) = account_id;
397        WFIFOL(fd,10) = char_id;
398        WFIFOB(fd,14) = flag;
399        WFIFOSET(fd,15);
400
401        return 0;
402}
403
404// ƒp[ƒeƒBÝ’è•ύX’Ê’m
405int mapif_party_optionchanged(int fd,struct party *p,int account_id,int flag)
406{
407        unsigned char buf[16];
408        WBUFW(buf,0)=0x3823;
409        WBUFL(buf,2)=p->party_id;
410        WBUFL(buf,6)=account_id;
411        WBUFW(buf,10)=p->exp;
412        WBUFW(buf,12)=p->item;
413        WBUFB(buf,14)=flag;
414        if(flag==0)
415                mapif_sendall(buf,15);
416        else
417                mapif_send(fd,buf,15);
418        return 0;
419}
420
421// ƒp[ƒeƒB’E‘Þ’Ê’m
422int mapif_party_leaved(int party_id,int account_id, int char_id) {
423        unsigned char buf[16];
424
425        WBUFW(buf,0) = 0x3824;
426        WBUFL(buf,2) = party_id;
427        WBUFL(buf,6) = account_id;
428        WBUFL(buf,10) = char_id;
429        mapif_sendall(buf, 14);
430        return 0;
431}
432
433// ƒp[ƒeƒBƒ}ƒbƒvXV’Ê’m
434int mapif_party_membermoved(struct party *p,int idx)
435{
436        unsigned char buf[20];
437
438        WBUFW(buf,0) = 0x3825;
439        WBUFL(buf,2) = p->party_id;
440        WBUFL(buf,6) = p->member[idx].account_id;
441        WBUFL(buf,10) = p->member[idx].char_id;
442        WBUFW(buf,14) = p->member[idx].map;
443        WBUFB(buf,16) = p->member[idx].online;
444        WBUFW(buf,17) = p->member[idx].lv;
445        mapif_sendall(buf, 19);
446        return 0;
447}
448
449// ƒp[ƒeƒB‰ðŽU’Ê’m
450int mapif_party_broken(int party_id,int flag)
451{
452        unsigned char buf[16];
453        WBUFW(buf,0)=0x3826;
454        WBUFL(buf,2)=party_id;
455        WBUFB(buf,6)=flag;
456        mapif_sendall(buf,7);
457        //printf("int_party: broken %d\n",party_id);
458        return 0;
459}
460// ƒp[ƒeƒB“à”­ŒŸ
461int mapif_party_message(int party_id,int account_id,char *mes,int len, int sfd)
462{
463        unsigned char buf[512];
464        WBUFW(buf,0)=0x3827;
465        WBUFW(buf,2)=len+12;
466        WBUFL(buf,4)=party_id;
467        WBUFL(buf,8)=account_id;
468        memcpy(WBUFP(buf,12),mes,len);
469        mapif_sendallwos(sfd, buf,len+12);
470        return 0;
471}
472
473//-------------------------------------------------------------------
474// map server‚©‚ç‚̒ʐM
475
476
477// Create Party
478int mapif_parse_CreateParty(int fd, char *name, int item, int item2, struct party_member *leader)
479{
480        struct party_data *p;
481        int i;
482        if( (p=search_partyname(name))!=NULL){
483                mapif_party_created(fd,leader->account_id,leader->char_id,NULL);
484                return 0;
485        }
486        // Check Authorised letters/symbols in the name of the character
487        if (char_name_option == 1) { // only letters/symbols in char_name_letters are authorised
488                for (i = 0; i < NAME_LENGTH && name[i]; i++)
489                        if (strchr(char_name_letters, name[i]) == NULL) {
490                                mapif_party_created(fd,leader->account_id,leader->char_id,NULL);
491                                return 0;
492                        }
493        } else if (char_name_option == 2) { // letters/symbols in char_name_letters are forbidden
494                for (i = 0; i < NAME_LENGTH && name[i]; i++)
495                        if (strchr(char_name_letters, name[i]) != NULL) {
496                                mapif_party_created(fd,leader->account_id,leader->char_id,NULL);
497                                return 0;
498                        }
499        }
500
501        p = (struct party_data*)aCalloc(1, sizeof(struct party_data));
502       
503        memcpy(p->party.name,name,NAME_LENGTH);
504        p->party.exp=0;
505        p->party.item=(item?1:0)|(item2?2:0);
506
507        memcpy(&p->party.member[0], leader, sizeof(struct party_member));
508        p->party.member[0].leader=1;
509        p->party.member[0].online=1;
510
511        p->party.party_id=-1;//New party.
512        if (inter_party_tosql(&p->party,PS_CREATE|PS_ADDMEMBER,0)) {
513                //Add party to db
514                int_party_calc_state(p);
515                idb_put(party_db_, p->party.party_id, p);
516                mapif_party_created(fd,leader->account_id,leader->char_id,&p->party);
517                mapif_party_info(fd,&p->party);
518        } else { //Failed to create party.
519                aFree(p);
520                mapif_party_created(fd,leader->account_id,leader->char_id,NULL);
521        }
522
523        return 0;
524}
525// ƒp[ƒeƒBî•ñ—v‹
526int mapif_parse_PartyInfo(int fd,int party_id)
527{
528        struct party_data *p;
529        p = inter_party_fromsql(party_id);
530
531        if (p)
532                mapif_party_info(fd,&p->party);
533        else
534                mapif_party_noinfo(fd,party_id);
535        return 0;
536}
537// ƒp[ƒeƒB’ljÁ—v‹
538int mapif_parse_PartyAddMember(int fd, int party_id, struct party_member *member)
539{
540        struct party_data *p;
541        int i;
542
543        p = inter_party_fromsql(party_id);
544        if( p == NULL || p->size == MAX_PARTY ) {
545                mapif_party_memberadded(fd, party_id, member->account_id, member->char_id, 1);
546                return 0;
547        }
548
549        ARR_FIND( 0, MAX_PARTY, i, p->party.member[i].account_id == 0 );
550        if( i == MAX_PARTY )
551        {// Party full
552                mapif_party_memberadded(fd, party_id, member->account_id, member->char_id, 1);
553                return 0;
554        }
555
556        memcpy(&p->party.member[i], member, sizeof(struct party_member));
557        p->party.member[i].leader = 0;
558        if (p->party.member[i].online) p->party.count++;
559        p->size++;
560        if (p->size == 3) //Check family state.
561                int_party_calc_state(p);
562        else //Check even share range.
563        if (member->lv < p->min_lv || member->lv > p->max_lv || p->family) {
564                if (p->family) p->family = 0; //Family state broken.
565                int_party_check_lv(p);
566        }
567
568        mapif_party_memberadded(fd, party_id, member->account_id, member->char_id, 0);
569        mapif_party_info(-1, &p->party);
570        inter_party_tosql(&p->party, PS_ADDMEMBER, i);
571
572        return 0;
573}
574
575// ƒp[ƒeƒB[Ý’è•ύX—v‹
576int mapif_parse_PartyChangeOption(int fd,int party_id,int account_id,int exp,int item)
577{
578        struct party_data *p;
579        int flag = 0;
580        p = inter_party_fromsql(party_id);
581
582        if(!p)
583                return 0;
584
585        p->party.exp=exp;
586        if( exp && !party_check_exp_share(p) ){
587                flag|=0x01;
588                p->party.exp=0;
589        }
590        p->party.item = item&0x3; //Filter out invalid values.
591        mapif_party_optionchanged(fd,&p->party,account_id,flag);
592        inter_party_tosql(&p->party, PS_BASIC, 0);
593        return 0;
594}
595// ƒp[ƒeƒB’E‘Þ—v‹
596int mapif_parse_PartyLeave(int fd, int party_id, int account_id, int char_id)
597{
598        struct party_data *p;
599        int i,j=-1;
600
601        p = inter_party_fromsql(party_id);
602        if( p == NULL )
603        {// Party does not exists?
604                if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d'", char_db, party_id) )
605                        Sql_ShowDebug(sql_handle);
606                return 0;
607        }
608
609        for (i = 0; i < MAX_PARTY; i++) {
610                if(p->party.member[i].account_id == account_id &&
611                        p->party.member[i].char_id == char_id) {
612                        break;
613                }
614        }
615        if (i >= MAX_PARTY)
616                return 0; //Member not found?
617
618        mapif_party_leaved(party_id, account_id, char_id);
619
620        if (p->party.member[i].leader){
621                p->party.member[i].account_id = 0;
622                for (j = 0; j < MAX_PARTY; j++) {
623                        if (!p->party.member[j].account_id)
624                                continue;
625                        mapif_party_leaved(party_id, p->party.member[j].account_id, p->party.member[j].char_id);
626                        p->party.member[j].account_id = 0;
627                }
628                //Party gets deleted on the check_empty call below.
629        } else {
630                inter_party_tosql(&p->party,PS_DELMEMBER,i);
631                j = p->party.member[i].lv;
632                if(p->party.member[i].online) p->party.count--;
633                memset(&p->party.member[i], 0, sizeof(struct party_member));
634                p->size--;
635                if (j == p->min_lv || j == p->max_lv || p->family)
636                {
637                        if(p->family) p->family = 0; //Family state broken.
638                        int_party_check_lv(p);
639                }
640        }
641               
642        if (party_check_empty(p) == 0)
643                mapif_party_info(-1,&p->party);
644        return 0;
645}
646// When member goes to other map or levels up.
647int mapif_parse_PartyChangeMap(int fd, int party_id, int account_id, int char_id, unsigned short map, int online, unsigned int lv)
648{
649        struct party_data *p;
650        int i;
651
652        p = inter_party_fromsql(party_id);
653        if (p == NULL)
654                return 0;
655
656        for(i = 0; i < MAX_PARTY && 
657                (p->party.member[i].account_id != account_id ||
658                p->party.member[i].char_id != char_id); i++);
659
660        if (i == MAX_PARTY) return 0;
661
662        if (p->party.member[i].online != online)
663        {
664                p->party.member[i].online = online;
665                if (online)
666                        p->party.count++;
667                else
668                        p->party.count--;
669                // Even share check situations: Family state (always breaks)
670                // character logging on/off is max/min level (update level range)
671                // or character logging on/off has a different level (update level range using new level)
672                if (p->family ||
673                        (p->party.member[i].lv <= p->min_lv || p->party.member[i].lv >= p->max_lv) ||
674                        (p->party.member[i].lv != lv && (lv <= p->min_lv || lv >= p->max_lv))
675                        )
676                {
677                        p->party.member[i].lv = lv;
678                        int_party_check_lv(p);
679                }
680                //Send online/offline update.
681                mapif_party_membermoved(&p->party, i);
682        }
683
684        if (p->party.member[i].lv != lv) {
685                if(p->party.member[i].lv == p->min_lv ||
686                        p->party.member[i].lv == p->max_lv)
687                {
688                        p->party.member[i].lv = lv;
689                        int_party_check_lv(p);
690                } else
691                        p->party.member[i].lv = lv;
692                //There is no need to send level update to map servers
693                //since they do nothing with it.
694        }
695
696        if (p->party.member[i].map != map) {
697                p->party.member[i].map = map;
698                mapif_party_membermoved(&p->party, i);
699        }
700        return 0;
701}
702
703// ƒp[ƒeƒB‰ðŽU—v‹
704int mapif_parse_BreakParty(int fd,int party_id)
705{
706        struct party_data *p;
707
708        p = inter_party_fromsql(party_id);
709
710        if(!p)
711                return 0;
712        inter_party_tosql(&p->party,PS_BREAK,0);
713        mapif_party_broken(fd,party_id);
714        return 0;
715}
716// ƒp[ƒeƒBƒƒbƒZ[ƒW‘—M
717int mapif_parse_PartyMessage(int fd,int party_id,int account_id,char *mes,int len)
718{
719        return mapif_party_message(party_id,account_id,mes,len, fd);
720}
721// ƒp[ƒeƒBƒ`ƒFƒbƒN—v‹
722int mapif_parse_PartyCheck(int fd,int party_id,int account_id,int char_id)
723{
724        return party_check_conflict(party_id,account_id,char_id);
725}
726
727int mapif_parse_PartyLeaderChange(int fd,int party_id,int account_id,int char_id)
728{
729        struct party_data *p;
730        int i;
731
732        p = inter_party_fromsql(party_id);
733
734        if(!p)
735                return 0;
736
737        for (i = 0; i < MAX_PARTY; i++)
738        {
739                if(p->party.member[i].leader) 
740                        p->party.member[i].leader = 0;
741                if(p->party.member[i].account_id == account_id &&
742                        p->party.member[i].char_id == char_id)
743                {
744                        p->party.member[i].leader = 1;
745                        inter_party_tosql(&p->party,PS_LEADER, i);
746                }
747        }
748        return 1;
749}
750
751// map server ‚©‚ç‚̒ʐM
752// E‚PƒpƒPƒbƒg‚̂݉ðÍ‚·‚邱‚Æ
753// EƒpƒPƒbƒg’·ƒf[ƒ^‚Íinter.c‚ɃZƒbƒg‚µ‚Ä‚š‚­‚±‚Æ
754// EƒpƒPƒbƒg’·ƒ`ƒFƒbƒN‚âARFIFOSKIP‚͌Ăяo‚µŒ³‚ōs‚í‚ê‚é‚̂ōs‚Á‚Ă͂Ȃç‚È‚¢
755// EƒGƒ‰[‚È‚ç0(false)A‚»‚€‚łȂ¢‚È‚ç1(true)‚ð‚©‚Š‚³‚È‚¯‚ê‚΂Ȃç‚È‚¢
756int inter_party_parse_frommap(int fd)
757{
758        RFIFOHEAD(fd);
759        switch(RFIFOW(fd,0)) {
760        case 0x3020: mapif_parse_CreateParty(fd, (char*)RFIFOP(fd,4), RFIFOB(fd,28), RFIFOB(fd,29), (struct party_member*)RFIFOP(fd,30)); break;
761        case 0x3021: mapif_parse_PartyInfo(fd, RFIFOL(fd,2)); break;
762        case 0x3022: mapif_parse_PartyAddMember(fd, RFIFOL(fd,4), (struct party_member*)RFIFOP(fd,8)); break;
763        case 0x3023: mapif_parse_PartyChangeOption(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOW(fd,10), RFIFOW(fd,12)); break;
764        case 0x3024: mapif_parse_PartyLeave(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)); break;
765        case 0x3025: mapif_parse_PartyChangeMap(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOW(fd,14), RFIFOB(fd,16), RFIFOW(fd,17)); break;
766        case 0x3026: mapif_parse_BreakParty(fd, RFIFOL(fd,2)); break;
767        case 0x3027: mapif_parse_PartyMessage(fd, RFIFOL(fd,4), RFIFOL(fd,8), (char*)RFIFOP(fd,12), RFIFOW(fd,2)-12); break;
768        case 0x3028: mapif_parse_PartyCheck(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)); break;
769        case 0x3029: mapif_parse_PartyLeaderChange(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)); break;
770        default:
771                return 0;
772        }
773        return 1;
774}
775
776// ƒT[ƒo[‚©‚ç’E‘Þ—v‹iƒLƒƒƒ‰íœ—pj
777int inter_party_leave(int party_id,int account_id, int char_id)
778{
779        return mapif_parse_PartyLeave(-1,party_id,account_id, char_id);
780}
781
782int inter_party_CharOnline(int char_id, int party_id)
783{
784        struct party_data* p;
785        int i;
786
787        if( party_id == -1 )
788        {// Get party_id from the database
789                char* data;
790
791                if( SQL_ERROR == Sql_Query(sql_handle, "SELECT party_id FROM `%s` WHERE char_id='%d'", char_db, char_id) )
792                {
793                        Sql_ShowDebug(sql_handle);
794                        return 0;
795                }
796
797                if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
798                        return 0; //Eh? No party?
799
800                Sql_GetData(sql_handle, 0, &data, NULL);
801                party_id = atoi(data);
802                Sql_FreeResult(sql_handle);
803        }
804        if (party_id == 0)
805                return 0; //No party...
806       
807        p = inter_party_fromsql(party_id);
808        if(!p) {
809                ShowError("Character %d's party %d not found!\n", char_id, party_id);
810                return 0;
811        }
812
813        //Set member online
814        for(i=0; i<MAX_PARTY; i++) {
815                if (p->party.member[i].char_id == char_id) {
816                        if (!p->party.member[i].online) {
817                                p->party.member[i].online = 1;
818                                p->party.count++;
819                                if (p->party.member[i].lv < p->min_lv ||
820                                        p->party.member[i].lv > p->max_lv)
821                                        int_party_check_lv(p);
822                        }
823                        break;
824                }
825        }
826        return 1;
827}
828
829int inter_party_CharOffline(int char_id, int party_id) {
830        struct party_data *p=NULL;
831        int i;
832
833        if( party_id == -1 )
834        {// Get guild_id from the database
835                char* data;
836
837                if( SQL_ERROR == Sql_Query(sql_handle, "SELECT party_id FROM `%s` WHERE char_id='%d'", char_db, char_id) )
838                {
839                        Sql_ShowDebug(sql_handle);
840                        return 0;
841                }
842
843                if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
844                        return 0; //Eh? No party?
845
846                Sql_GetData(sql_handle, 0, &data, NULL);
847                party_id = atoi(data);
848                Sql_FreeResult(sql_handle);
849        }
850        if (party_id == 0)
851                return 0; //No party...
852       
853        //Character has a party, set character offline and check if they were the only member online
854        if ((p = inter_party_fromsql(party_id)) == NULL)
855                return 0;
856
857        //Set member offline
858        for(i=0; i< MAX_PARTY; i++) {
859                if(p->party.member[i].char_id == char_id)
860                {
861                        p->party.member[i].online = 0;
862                        p->party.count--;
863                        if(p->party.member[i].lv == p->min_lv ||
864                                p->party.member[i].lv == p->max_lv)
865                                int_party_check_lv(p);
866                        break;
867                }
868        }
869
870        if(!p->party.count)
871                //Parties don't have any data that needs be saved at this point... so just remove it from memory.
872                idb_remove(party_db_, party_id);
873        return 1;
874}
875#endif //TXT_SQL_CONVERT
Note: See TracBrowser for help on using the browser.