summaryrefslogtreecommitdiff
path: root/src/char/int_party.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/char/int_party.c')
-rw-r--r--src/char/int_party.c761
1 files changed, 457 insertions, 304 deletions
diff --git a/src/char/int_party.c b/src/char/int_party.c
index 2ae9e5319..7d0dd0b75 100644
--- a/src/char/int_party.c
+++ b/src/char/int_party.c
@@ -3,11 +3,13 @@
#include "../common/cbasetypes.h"
#include "../common/mmo.h"
+#include "../common/db.h"
#include "../common/malloc.h"
+#include "../common/strlib.h"
#include "../common/socket.h"
-#include "../common/db.h"
-#include "../common/lock.h"
#include "../common/showmsg.h"
+#include "../common/mapindex.h"
+#include "../common/sql.h"
#include "char.h"
#include "inter.h"
#include "int_party.h"
@@ -16,8 +18,6 @@
#include <stdlib.h>
#include <string.h>
-char party_txt[1024] = "save/party.txt";
-#ifndef TXT_SQL_CONVERT
struct party_data {
struct party party;
unsigned int min_lv, max_lv;
@@ -25,11 +25,11 @@ struct party_data {
unsigned char size; //Total size of party.
};
-static DBMap* party_db; // int party_id -> struct party_data*
-static int party_newid = 100;
+static struct party_data *party_pt;
+static DBMap* party_db_; // int party_id -> struct party_data*
-int mapif_party_broken(int party_id, int flag);
-int party_check_empty(struct party *p);
+int mapif_party_broken(int party_id,int flag);
+int party_check_empty(struct party_data *p);
int mapif_parse_PartyLeave(int fd, int party_id, int account_id, int char_id);
int party_check_exp_share(struct party_data *p);
int mapif_party_optionchanged(int fd,struct party *p, int account_id, int flag);
@@ -41,7 +41,10 @@ static int int_party_check_lv(struct party_data *p) {
p->min_lv = UINT_MAX;
p->max_lv = 0;
for(i=0;i<MAX_PARTY;i++){
- if(!p->party.member[i].online)
+ /**
+ * - If not online OR if it's a family party and this is the child (doesn't affect exp range)
+ **/
+ if(!p->party.member[i].online || p->party.member[i].char_id == p->family )
continue;
lv=p->party.member[i].lv;
@@ -56,7 +59,6 @@ static int int_party_check_lv(struct party_data *p) {
}
return 1;
}
-
//Calculates the state of a party.
static void int_party_calc_state(struct party_data *p)
{
@@ -68,14 +70,20 @@ static void int_party_calc_state(struct party_data *p)
p->size =
p->family = 0;
- //Check party size.
+ //Check party size
for(i=0;i<MAX_PARTY;i++){
if (!p->party.member[i].lv) continue;
p->size++;
if(p->party.member[i].online)
p->party.count++;
}
- if(p->size == 3) {
+ if( p->size == 2 && ( char_child(p->party.member[0].char_id,p->party.member[1].char_id) || char_child(p->party.member[1].char_id,p->party.member[0].char_id) ) ) {
+ //Child should be able to share with either of their parents [RoM]
+ if(p->party.member[0].class_&0x2000) //first slot is the child?
+ p->family = p->party.member[0].char_id;
+ else
+ p->family = p->party.member[1].char_id;
+ } else if( p->size == 3 ) {
//Check Family State.
p->family = char_family(
p->party.member[0].char_id,
@@ -103,212 +111,244 @@ static void int_party_calc_state(struct party_data *p)
return;
}
-// パ?ティデ?タの文字列への?換
-int inter_party_tostr(char *str, struct party *p) {
- int i, len;
+// Save party to mysql
+int inter_party_tosql(struct party *p, int flag, int index)
+{
+ // 'party' ('party_id','name','exp','item','leader_id','leader_char')
+ char esc_name[NAME_LENGTH*2+1];// escaped party name
+ int party_id;
- len = sprintf(str, "%d\t%s\t%d,%d\t", p->party_id, p->name, p->exp, p->item);
- for(i = 0; i < MAX_PARTY; i++) {
- struct party_member *m = &p->member[i];
- len += sprintf(str + len, "%d,%d,%d\t", m->account_id, m->char_id, m->leader);
- }
+ if( p == NULL || p->party_id == 0 )
+ return 0;
+ party_id = p->party_id;
- return 0;
-}
-#endif //TXT_SQL_CONVERT
-// パ?ティデ?タの文字列からの?換
-int inter_party_fromstr(char *str, struct party *p) {
- int i, j;
- int tmp_int[16];
- char tmp_str[256];
-#ifndef TXT_SQL_CONVERT
- struct mmo_charstatus* status;
+#ifdef NOISY
+ ShowInfo("Save party request ("CL_BOLD"%d"CL_RESET" - %s).\n", party_id, p->name);
#endif
-
- memset(p, 0, sizeof(struct party));
-
- if (sscanf(str, "%d\t%255[^\t]\t%d,%d\t", &tmp_int[0], tmp_str, &tmp_int[1], &tmp_int[2]) != 4)
+ Sql_EscapeStringLen(sql_handle, esc_name, p->name, strnlen(p->name, NAME_LENGTH));
+
+ if( flag & PS_BREAK )
+ {// Break the party
+ // we'll skip name-checking and just reset everyone with the same party id [celest]
+ if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d'", char_db, party_id) )
+ Sql_ShowDebug(sql_handle);
+ if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `party_id`='%d'", party_db, party_id) )
+ Sql_ShowDebug(sql_handle);
+ //Remove from memory
+ idb_remove(party_db_, party_id);
return 1;
+ }
- p->party_id = tmp_int[0];
- memcpy(p->name, tmp_str, NAME_LENGTH);
- p->exp = tmp_int[1]?1:0;
- p->item = tmp_int[2];
-
- for(j = 0; j < 3 && str != NULL; j++)
- str = strchr(str + 1, '\t');
-
- for(i = 0; i < MAX_PARTY; i++) {
- struct party_member *m = &p->member[i];
- if (str == NULL)
- return 1;
+ if( flag & PS_CREATE )
+ {// Create party
+ if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` "
+ "(`name`, `exp`, `item`, `leader_id`, `leader_char`) "
+ "VALUES ('%s', '%d', '%d', '%d', '%d')",
+ party_db, esc_name, p->exp, p->item, p->member[index].account_id, p->member[index].char_id) )
+ {
+ Sql_ShowDebug(sql_handle);
+ return 0;
+ }
+ party_id = p->party_id = (int)Sql_LastInsertId(sql_handle);
+ }
- if (sscanf(str + 1, "%d,%d,%d\t", &tmp_int[0], &tmp_int[1], &tmp_int[2]) != 3)
- return 1;
+ if( flag & PS_BASIC )
+ {// Update party info.
+ if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `name`='%s', `exp`='%d', `item`='%d' WHERE `party_id`='%d'",
+ party_db, esc_name, p->exp, p->item, party_id) )
+ Sql_ShowDebug(sql_handle);
+ }
- m->account_id = tmp_int[0];
- m->char_id = tmp_int[1];
- m->leader = tmp_int[2]?1:0;
+ if( flag & PS_LEADER )
+ {// Update leader
+ if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `leader_id`='%d', `leader_char`='%d' WHERE `party_id`='%d'",
+ party_db, p->member[index].account_id, p->member[index].char_id, party_id) )
+ Sql_ShowDebug(sql_handle);
+ }
+
+ if( flag & PS_ADDMEMBER )
+ {// Add one party member.
+ if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='%d' WHERE `account_id`='%d' AND `char_id`='%d'",
+ char_db, party_id, p->member[index].account_id, p->member[index].char_id) )
+ Sql_ShowDebug(sql_handle);
+ }
- str = strchr(str + 1, '\t');
-#ifndef TXT_SQL_CONVERT
- if (!m->account_id) continue;
- //Lookup player for rest of data.
- status = search_character(m->account_id, m->char_id);
- if (!status) continue;
-
- memcpy(m->name, status->name, NAME_LENGTH);
- m->class_ = status->class_;
- m->map = status->last_point.map;
- m->lv = status->base_level;
-#endif //TXT_SQL_CONVERT
+ if( flag & PS_DELMEMBER )
+ {// Remove one party member.
+ 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'",
+ char_db, party_id, p->member[index].account_id, p->member[index].char_id) )
+ Sql_ShowDebug(sql_handle);
}
- return 0;
+ if( save_log )
+ ShowInfo("Party Saved (%d - %s)\n", party_id, p->name);
+ return 1;
}
-#ifndef TXT_SQL_CONVERT
-// パ?ティデ?タのロ?ド
-int inter_party_init() {
- char line[8192];
- struct party_data *p;
- FILE *fp;
- int c = 0;
- int i, j;
- party_db = idb_alloc(DB_OPT_RELEASE_DATA);
+// Read party from mysql
+struct party_data *inter_party_fromsql(int party_id)
+{
+ int leader_id = 0;
+ int leader_char = 0;
+ struct party_data* p;
+ struct party_member* m;
+ char* data;
+ size_t len;
+ int i;
- if ((fp = fopen(party_txt, "r")) == NULL)
- return 1;
+#ifdef NOISY
+ ShowInfo("Load party request ("CL_BOLD"%d"CL_RESET")\n", party_id);
+#endif
+ if( party_id <= 0 )
+ return NULL;
+
+ //Load from memory
+ p = (struct party_data*)idb_get(party_db_, party_id);
+ if( p != NULL )
+ return p;
- while(fgets(line, sizeof(line), fp))
- {
- j = 0;
- if (sscanf(line, "%d\t%%newid%%\n%n", &i, &j) == 1 && j > 0 && party_newid <= i) {
- party_newid = i;
- continue;
- }
+ p = party_pt;
+ memset(p, 0, sizeof(struct party_data));
- p = (struct party_data*)aCalloc(sizeof(struct party_data), 1);
- if (p == NULL){
- ShowFatalError("int_party: out of memory!\n");
- exit(EXIT_FAILURE);
- }
- memset(p, 0, sizeof(struct party_data));
- if (inter_party_fromstr(line, &p->party) == 0 && p->party.party_id > 0) {
- int_party_calc_state(p);
- if (p->party.party_id >= party_newid)
- party_newid = p->party.party_id + 1;
- idb_put(party_db, p->party.party_id, p);
- party_check_empty(&p->party);
- } else {
- ShowError("int_party: broken data [%s] line %d\n", party_txt, c + 1);
- aFree(p);
- }
- c++;
+ 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) )
+ {
+ Sql_ShowDebug(sql_handle);
+ return NULL;
}
- fclose(fp);
- return 0;
-}
+ if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
+ return NULL;
-void inter_party_final()
-{
- party_db->destroy(party_db, NULL);
- return;
-}
+ p->party.party_id = party_id;
+ Sql_GetData(sql_handle, 1, &data, &len); memcpy(p->party.name, data, min(len, NAME_LENGTH));
+ Sql_GetData(sql_handle, 2, &data, NULL); p->party.exp = (atoi(data) ? 1 : 0);
+ Sql_GetData(sql_handle, 3, &data, NULL); p->party.item = atoi(data);
+ Sql_GetData(sql_handle, 4, &data, NULL); leader_id = atoi(data);
+ Sql_GetData(sql_handle, 5, &data, NULL); leader_char = atoi(data);
+ Sql_FreeResult(sql_handle);
-// パ?ティ?デ?タのセ?ブ用
-int inter_party_save_sub(DBKey key, void *data, va_list ap) {
- char line[8192];
- FILE *fp;
+ // Load members
+ 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) )
+ {
+ Sql_ShowDebug(sql_handle);
+ return NULL;
+ }
+ for( i = 0; i < MAX_PARTY && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i )
+ {
+ m = &p->party.member[i];
+ Sql_GetData(sql_handle, 0, &data, NULL); m->account_id = atoi(data);
+ Sql_GetData(sql_handle, 1, &data, NULL); m->char_id = atoi(data);
+ Sql_GetData(sql_handle, 2, &data, &len); memcpy(m->name, data, min(len, NAME_LENGTH));
+ Sql_GetData(sql_handle, 3, &data, NULL); m->lv = atoi(data);
+ Sql_GetData(sql_handle, 4, &data, NULL); m->map = mapindex_name2id(data);
+ Sql_GetData(sql_handle, 5, &data, NULL); m->online = (atoi(data) ? 1 : 0);
+ Sql_GetData(sql_handle, 6, &data, NULL); m->class_ = atoi(data);
+ m->leader = (m->account_id == leader_id && m->char_id == leader_char ? 1 : 0);
+ }
+ Sql_FreeResult(sql_handle);
+
+ if( save_log )
+ ShowInfo("Party loaded (%d - %s).\n", party_id, p->party.name);
+ //Add party to memory.
+ CREATE(p, struct party_data, 1);
+ memcpy(p, party_pt, sizeof(struct party_data));
+ //init state
+ int_party_calc_state(p);
+ idb_put(party_db_, party_id, p);
+ return p;
+}
- inter_party_tostr(line, &((struct party_data*)data)->party);
- fp = va_arg(ap, FILE *);
- fprintf(fp, "%s\n", line);
+int inter_party_sql_init(void)
+{
+ //memory alloc
+ party_db_ = idb_alloc(DB_OPT_RELEASE_DATA);
+ party_pt = (struct party_data*)aCalloc(sizeof(struct party_data), 1);
+ if (!party_pt) {
+ ShowFatalError("inter_party_sql_init: Out of Memory!\n");
+ exit(EXIT_FAILURE);
+ }
+ /* Uncomment the following if you want to do a party_db cleanup (remove parties with no members) on startup.[Skotlex]
+ ShowStatus("cleaning party table...\n");
+ 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",
+ party_db, party_db, char_db, party_db, char_db, party_db, char_db, char_db) )
+ Sql_ShowDebug(sql_handle);
+ */
return 0;
}
-// パ?ティ?デ?タのセ?ブ
-int inter_party_save() {
- FILE *fp;
- int lock;
-
- if ((fp = lock_fopen(party_txt, &lock)) == NULL) {
- ShowError("int_party: can't write [%s] !!! data is lost !!!\n", party_txt);
- return 1;
- }
- party_db->foreach(party_db, inter_party_save_sub, fp);
- lock_fclose(fp,party_txt, &lock);
- return 0;
+void inter_party_sql_final(void)
+{
+ party_db_->destroy(party_db_, NULL);
+ aFree(party_pt);
+ return;
}
// Search for the party according to its name
-struct party_data* search_partyname(char *str)
+struct party_data* search_partyname(char* str)
{
- struct DBIterator* iter;
- struct party_data* p;
- struct party_data* result = NULL;
-
- iter = party_db->iterator(party_db);
- for( p = (struct party_data*)iter->first(iter,NULL); iter->exists(iter); p = (struct party_data*)iter->next(iter,NULL) )
+ char esc_name[NAME_LENGTH*2+1];
+ char* data;
+ struct party_data* p = NULL;
+
+ Sql_EscapeStringLen(sql_handle, esc_name, str, safestrnlen(str, NAME_LENGTH));
+ if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `party_id` FROM `%s` WHERE `name`='%s'", party_db, esc_name) )
+ Sql_ShowDebug(sql_handle);
+ else if( SQL_SUCCESS == Sql_NextRow(sql_handle) )
{
- if( strncmpi(p->party.name, str, NAME_LENGTH) == 0 )
- {
- result = p;
- break;
- }
+ Sql_GetData(sql_handle, 0, &data, NULL);
+ p = inter_party_fromsql(atoi(data));
}
- iter->destroy(iter);
+ Sql_FreeResult(sql_handle);
- return result;
+ return p;
}
// Returns whether this party can keep having exp share or not.
-int party_check_exp_share(struct party_data *p) {
- return (p->party.count < 2|| p->max_lv - p->min_lv <= party_share_level);
+int party_check_exp_share(struct party_data *p)
+{
+ return (p->party.count < 2 || p->max_lv - p->min_lv <= party_share_level);
}
-// パ?ティが空かどうかチェック
-int party_check_empty(struct party *p) {
+// Is there any member in the party?
+int party_check_empty(struct party_data *p)
+{
int i;
-
- for(i = 0; i < MAX_PARTY; i++) {
- if (p->member[i].account_id > 0) {
- return 0;
- }
- }
- mapif_party_broken(p->party_id, 0);
- idb_remove(party_db, p->party_id);
-
+ if (p==NULL||p->party.party_id==0) return 1;
+ for(i=0;i<MAX_PARTY && !p->party.member[i].account_id;i++);
+ if (i < MAX_PARTY) return 0;
+ // If there is no member, then break the party
+ mapif_party_broken(p->party.party_id,0);
+ inter_party_tosql(&p->party, PS_BREAK, 0);
return 1;
}
//-------------------------------------------------------------------
// map serverへの通信
-// パ?ティ作成可否
-int mapif_party_created(int fd,int account_id, int char_id, struct party *p)
+// パーティ作成可否
+int mapif_party_created(int fd,int account_id,int char_id,struct party *p)
{
WFIFOHEAD(fd, 39);
- WFIFOW(fd,0) = 0x3820;
- WFIFOL(fd,2) = account_id;
- WFIFOL(fd,6) = char_id;
- if (p != NULL) {
- WFIFOB(fd,10) = 0;
- WFIFOL(fd,11) = p->party_id;
- memcpy(WFIFOP(fd,15), p->name, NAME_LENGTH);
- ShowInfo("Created party (%d - %s)\n", p->party_id, p->name);
- } else {
- WFIFOB(fd,10) = 1;
- WFIFOL(fd,11) = 0;
- memset(WFIFOP(fd,15), 0, NAME_LENGTH);
+ WFIFOW(fd,0)=0x3820;
+ WFIFOL(fd,2)=account_id;
+ WFIFOL(fd,6)=char_id;
+ if(p!=NULL){
+ WFIFOB(fd,10)=0;
+ WFIFOL(fd,11)=p->party_id;
+ memcpy(WFIFOP(fd,15),p->name,NAME_LENGTH);
+ ShowInfo("int_party: Party created (%d - %s)\n",p->party_id,p->name);
+ }else{
+ WFIFOB(fd,10)=1;
+ WFIFOL(fd,11)=0;
+ memset(WFIFOP(fd,15),0,NAME_LENGTH);
}
WFIFOSET(fd,39);
+
return 0;
}
-// パ?ティ情報見つからず
+// パーティ情報見つからず
static void mapif_party_noinfo(int fd, int party_id, int char_id)
{
WFIFOHEAD(fd, 12);
@@ -319,8 +359,7 @@ static void mapif_party_noinfo(int fd, int party_id, int char_id)
WFIFOSET(fd,12);
ShowWarning("int_party: info not found (party_id=%d char_id=%d)\n", party_id, char_id);
}
-
-// パ?ティ情報まとめ送り
+// パーティ情報まとめ送り
static void mapif_party_info(int fd, struct party* p, int char_id)
{
unsigned char buf[8 + sizeof(struct party)];
@@ -328,13 +367,13 @@ static void mapif_party_info(int fd, struct party* p, int char_id)
WBUFW(buf,2) = 8 + sizeof(struct party);
WBUFL(buf,4) = char_id;
memcpy(WBUFP(buf,8), p, sizeof(struct party));
- if (fd < 0)
- mapif_sendall(buf, WBUFW(buf,2));
+
+ if(fd<0)
+ mapif_sendall(buf,WBUFW(buf,2));
else
- mapif_send(fd, buf, WBUFW(buf,2));
+ mapif_send(fd,buf,WBUFW(buf,2));
}
-
-// パ?ティメンバ追加可否
+// パーティメンバ追加可否
int mapif_party_memberadded(int fd, int party_id, int account_id, int char_id, int flag) {
WFIFOHEAD(fd, 15);
WFIFOW(fd,0) = 0x3822;
@@ -347,24 +386,24 @@ int mapif_party_memberadded(int fd, int party_id, int account_id, int char_id, i
return 0;
}
-// パ?ティ設定?更通知
-int mapif_party_optionchanged(int fd,struct party *p, int account_id, int flag) {
- unsigned char buf[15];
-
- WBUFW(buf,0) = 0x3823;
- WBUFL(buf,2) = p->party_id;
- WBUFL(buf,6) = account_id;
- WBUFW(buf,10) = p->exp;
- WBUFW(buf,12) = p->item;
- WBUFB(buf,14) = flag;
- if (flag == 0)
- mapif_sendall(buf, 15);
+// パーティ設定変更通知
+int mapif_party_optionchanged(int fd,struct party *p,int account_id,int flag)
+{
+ unsigned char buf[16];
+ WBUFW(buf,0)=0x3823;
+ WBUFL(buf,2)=p->party_id;
+ WBUFL(buf,6)=account_id;
+ WBUFW(buf,10)=p->exp;
+ WBUFW(buf,12)=p->item;
+ WBUFB(buf,14)=flag;
+ if(flag==0)
+ mapif_sendall(buf,15);
else
- mapif_send(fd, buf, 15);
+ mapif_send(fd,buf,15);
return 0;
}
-// パ?ティ?退通知
+// パーティ脱退通知
int mapif_party_withdraw(int party_id,int account_id, int char_id) {
unsigned char buf[16];
@@ -376,8 +415,9 @@ int mapif_party_withdraw(int party_id,int account_id, int char_id) {
return 0;
}
-// パ?ティマップ更新通知
-int mapif_party_membermoved(struct party *p, int idx) {
+// パーティマップ更新通知
+int mapif_party_membermoved(struct party *p,int idx)
+{
unsigned char buf[20];
WBUFW(buf,0) = 0x3825;
@@ -391,29 +431,27 @@ int mapif_party_membermoved(struct party *p, int idx) {
return 0;
}
-// パ?ティ解散通知
-int mapif_party_broken(int party_id, int flag) {
- unsigned char buf[7];
- WBUFW(buf,0) = 0x3826;
- WBUFL(buf,2) = party_id;
- WBUFB(buf,6) = flag;
- mapif_sendall(buf, 7);
- ShowInfo("Party broken (%d)\n", party_id);
-
+// パーティ解散通知
+int mapif_party_broken(int party_id,int flag)
+{
+ unsigned char buf[16];
+ WBUFW(buf,0)=0x3826;
+ WBUFL(buf,2)=party_id;
+ WBUFB(buf,6)=flag;
+ mapif_sendall(buf,7);
+ //printf("int_party: broken %d\n",party_id);
return 0;
}
-
-// パ?ティ??言
-int mapif_party_message(int party_id, int account_id, char *mes, int len, int sfd) {
- unsigned char buf[2048];
-
- WBUFW(buf,0) = 0x3827;
- WBUFW(buf,2) = len + 12;
- WBUFL(buf,4) = party_id;
- WBUFL(buf,8) = account_id;
- memcpy(WBUFP(buf,12), mes, len);
- mapif_sendallwos(sfd, buf,len + 12);
-
+// パーティ内発言
+int mapif_party_message(int party_id,int account_id,char *mes,int len, int sfd)
+{
+ unsigned char buf[512];
+ WBUFW(buf,0)=0x3827;
+ WBUFW(buf,2)=len+12;
+ WBUFL(buf,4)=party_id;
+ WBUFL(buf,8)=account_id;
+ memcpy(WBUFP(buf,12),mes,len);
+ mapif_sendallwos(sfd, buf,len+12);
return 0;
}
@@ -421,83 +459,72 @@ int mapif_party_message(int party_id, int account_id, char *mes, int len, int sf
// map serverからの通信
-// パ?ティ
+// Create Party
int mapif_parse_CreateParty(int fd, char *name, int item, int item2, struct party_member *leader)
{
struct party_data *p;
int i;
-
- //FIXME: this should be removed once the savefiles can handle all symbols
- for(i = 0; i < NAME_LENGTH && name[i]; i++) {
- if (!(name[i] & 0xe0) || name[i] == 0x7f) {
- ShowInfo("int_party: illegal party name [%s]\n", name);
- mapif_party_created(fd, leader->account_id, leader->char_id, NULL);
- return 0;
- }
- }
-
- if ((p = search_partyname(name)) != NULL) {
- ShowInfo("int_party: same name party exists [%s]\n", name);
- mapif_party_created(fd, leader->account_id, leader->char_id, NULL);
+ if( (p=search_partyname(name))!=NULL){
+ mapif_party_created(fd,leader->account_id,leader->char_id,NULL);
return 0;
}
-
// Check Authorised letters/symbols in the name of the character
if (char_name_option == 1) { // only letters/symbols in char_name_letters are authorised
for (i = 0; i < NAME_LENGTH && name[i]; i++)
if (strchr(char_name_letters, name[i]) == NULL) {
- mapif_party_created(fd, leader->account_id, leader->char_id, NULL);
+ mapif_party_created(fd,leader->account_id,leader->char_id,NULL);
return 0;
}
} else if (char_name_option == 2) { // letters/symbols in char_name_letters are forbidden
for (i = 0; i < NAME_LENGTH && name[i]; i++)
if (strchr(char_name_letters, name[i]) != NULL) {
- mapif_party_created(fd, leader->account_id, leader->char_id, NULL);
+ mapif_party_created(fd,leader->account_id,leader->char_id,NULL);
return 0;
}
}
- p = (struct party_data *) aCalloc(sizeof(struct party_data), 1);
- if (p == NULL) {
- ShowFatalError("int_party: out of memory !\n");
- mapif_party_created(fd,leader->account_id,leader->char_id,NULL);
- return 0;
- }
- p->party.party_id = party_newid++;
- memcpy(p->party.name, name, NAME_LENGTH);
- p->party.exp = 0;
+ p = (struct party_data*)aCalloc(1, sizeof(struct party_data));
+
+ memcpy(p->party.name,name,NAME_LENGTH);
+ p->party.exp=0;
p->party.item=(item?1:0)|(item2?2:0);
+
memcpy(&p->party.member[0], leader, sizeof(struct party_member));
- p->party.member[0].leader = 1;
- int_party_calc_state(p);
- idb_put(party_db, p->party.party_id, p);
+ p->party.member[0].leader=1;
+ p->party.member[0].online=1;
- mapif_party_info(fd, &p->party, 0);
- mapif_party_created(fd, leader->account_id, leader->char_id, &p->party);
+ p->party.party_id=-1;//New party.
+ if (inter_party_tosql(&p->party,PS_CREATE|PS_ADDMEMBER,0)) {
+ //Add party to db
+ int_party_calc_state(p);
+ idb_put(party_db_, p->party.party_id, p);
+ mapif_party_info(fd, &p->party, 0);
+ mapif_party_created(fd,leader->account_id,leader->char_id,&p->party);
+ } else { //Failed to create party.
+ aFree(p);
+ mapif_party_created(fd,leader->account_id,leader->char_id,NULL);
+ }
return 0;
}
-
-// パ?ティ情報要求
+// パーティ情報要求
static void mapif_parse_PartyInfo(int fd, int party_id, int char_id)
{
struct party_data *p;
+ p = inter_party_fromsql(party_id);
- p = (struct party_data*)idb_get(party_db, party_id);
- if (p != NULL)
+ if (p)
mapif_party_info(fd, &p->party, char_id);
- else {
+ else
mapif_party_noinfo(fd, party_id, char_id);
- }
}
-
-// パーティ追加要求
+// パーティ追加要求
int mapif_parse_PartyAddMember(int fd, int party_id, struct party_member *member)
{
struct party_data *p;
int i;
- p = (struct party_data*)idb_get(party_db, party_id);
+ p = inter_party_fromsql(party_id);
if( p == NULL || p->size == MAX_PARTY ) {
mapif_party_memberadded(fd, party_id, member->account_id, member->char_id, 1);
return 0;
@@ -514,7 +541,7 @@ int mapif_parse_PartyAddMember(int fd, int party_id, struct party_member *member
p->party.member[i].leader = 0;
if (p->party.member[i].online) p->party.count++;
p->size++;
- if (p->size == 3) //Check family state.
+ if (p->size == 2 || p->size == 3) // Check family state. And also accept either of their Parents. [RoM]
int_party_calc_state(p);
else //Check even share range.
if (member->lv < p->min_lv || member->lv > p->max_lv || p->family) {
@@ -524,67 +551,89 @@ int mapif_parse_PartyAddMember(int fd, int party_id, struct party_member *member
mapif_party_info(-1, &p->party, 0);
mapif_party_memberadded(fd, party_id, member->account_id, member->char_id, 0);
+ inter_party_tosql(&p->party, PS_ADDMEMBER, i);
return 0;
}
-// パ?ティ?設定?更要求
-int mapif_parse_PartyChangeOption(int fd, int party_id, int account_id, int exp, int item)
+// パーティー設定変更要求
+int mapif_parse_PartyChangeOption(int fd,int party_id,int account_id,int exp,int item)
{
struct party_data *p;
int flag = 0;
+ p = inter_party_fromsql(party_id);
- p = (struct party_data*)idb_get(party_db, party_id);
- if (p == NULL)
+ if(!p)
return 0;
- p->party.exp = exp;
- if (exp>0 && !party_check_exp_share(p)) {
- flag |= 0x01;
- p->party.exp = 0;
+ p->party.exp=exp;
+ if( exp && !party_check_exp_share(p) ){
+ flag|=0x01;
+ p->party.exp=0;
}
- p->party.item = item&0x3;
- mapif_party_optionchanged(fd, &p->party, account_id, flag);
+ p->party.item = item&0x3; //Filter out invalid values.
+ mapif_party_optionchanged(fd,&p->party,account_id,flag);
+ inter_party_tosql(&p->party, PS_BASIC, 0);
return 0;
}
-
-// パ?ティ?退要求
+// パーティ脱退要求
int mapif_parse_PartyLeave(int fd, int party_id, int account_id, int char_id)
{
struct party_data *p;
- int i,lv;
+ int i,j=-1;
- p = (struct party_data*)idb_get(party_db, party_id);
- if (!p) return 0;
+ p = inter_party_fromsql(party_id);
+ if( p == NULL )
+ {// Party does not exists?
+ if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d'", char_db, party_id) )
+ Sql_ShowDebug(sql_handle);
+ return 0;
+ }
- for(i = 0; i < MAX_PARTY; i++) {
+ for (i = 0; i < MAX_PARTY; i++) {
if(p->party.member[i].account_id == account_id &&
- p->party.member[i].char_id == char_id)
+ p->party.member[i].char_id == char_id) {
+ break;
+ }
+ }
+ if (i >= MAX_PARTY)
+ return 0; //Member not found?
+
+ mapif_party_withdraw(party_id, account_id, char_id);
+
+ if (p->party.member[i].leader){
+ p->party.member[i].account_id = 0;
+ for (j = 0; j < MAX_PARTY; j++) {
+ if (!p->party.member[j].account_id)
+ continue;
+ mapif_party_withdraw(party_id, p->party.member[j].account_id, p->party.member[j].char_id);
+ p->party.member[j].account_id = 0;
+ }
+ //Party gets deleted on the check_empty call below.
+ } else {
+ inter_party_tosql(&p->party,PS_DELMEMBER,i);
+ j = p->party.member[i].lv;
+ if(p->party.member[i].online) p->party.count--;
+ memset(&p->party.member[i], 0, sizeof(struct party_member));
+ p->size--;
+ if (j == p->min_lv || j == p->max_lv || p->family)
{
- mapif_party_withdraw(party_id, account_id, char_id);
- lv = p->party.member[i].lv;
- if(p->party.member[i].online) p->party.count--;
- memset(&p->party.member[i], 0, sizeof(struct party_member));
- p->size--;
- if (lv == p->min_lv || lv == p->max_lv || p->family)
- {
- if(p->family) p->family = 0; //Family state broken.
- int_party_check_lv(p);
- }
- if (party_check_empty(&p->party) == 0)
- mapif_party_info(-1, &p->party, 0);
- return 0;
+ if(p->family) p->family = 0; //Family state broken.
+ int_party_check_lv(p);
}
}
+
+ if (party_check_empty(p) == 0)
+ mapif_party_info(-1, &p->party, 0);
return 0;
}
-
+// When member goes to other map or levels up.
int mapif_parse_PartyChangeMap(int fd, int party_id, int account_id, int char_id, unsigned short map, int online, unsigned int lv)
{
struct party_data *p;
int i;
- p = (struct party_data*)idb_get(party_db, party_id);
+ p = inter_party_fromsql(party_id);
if (p == NULL)
return 0;
@@ -615,6 +664,7 @@ int mapif_parse_PartyChangeMap(int fd, int party_id, int account_id, int char_id
//Send online/offline update.
mapif_party_membermoved(&p->party, i);
}
+
if (p->party.member[i].lv != lv) {
if(p->party.member[i].lv == p->min_lv ||
p->party.member[i].lv == p->max_lv)
@@ -626,6 +676,7 @@ int mapif_parse_PartyChangeMap(int fd, int party_id, int account_id, int char_id
//There is no need to send level update to map servers
//since they do nothing with it.
}
+
if (p->party.member[i].map != map) {
p->party.member[i].map = map;
mapif_party_membermoved(&p->party, i);
@@ -633,19 +684,23 @@ int mapif_parse_PartyChangeMap(int fd, int party_id, int account_id, int char_id
return 0;
}
-// パ?ティ解散要求
-int mapif_parse_BreakParty(int fd, int party_id) {
+// パーティ解散要求
+int mapif_parse_BreakParty(int fd,int party_id)
+{
+ struct party_data *p;
- idb_remove(party_db, party_id);
- mapif_party_broken(fd, party_id);
+ p = inter_party_fromsql(party_id);
+ if(!p)
+ return 0;
+ inter_party_tosql(&p->party,PS_BREAK,0);
+ mapif_party_broken(fd,party_id);
return 0;
}
-
-// パ?ティメッセ?ジ送信
-int mapif_parse_PartyMessage(int fd, int party_id, int account_id, char *mes, int len)
+// パーティメッセージ送信
+int mapif_parse_PartyMessage(int fd,int party_id,int account_id,char *mes,int len)
{
- return mapif_party_message(party_id, account_id, mes, len, fd);
+ return mapif_party_message(party_id,account_id,mes,len, fd);
}
int mapif_parse_PartyLeaderChange(int fd,int party_id,int account_id,int char_id)
@@ -653,8 +708,9 @@ int mapif_parse_PartyLeaderChange(int fd,int party_id,int account_id,int char_id
struct party_data *p;
int i;
- p = (struct party_data*)idb_get(party_db, party_id);
- if (p == NULL)
+ p = inter_party_fromsql(party_id);
+
+ if(!p)
return 0;
for (i = 0; i < MAX_PARTY; i++)
@@ -663,17 +719,21 @@ int mapif_parse_PartyLeaderChange(int fd,int party_id,int account_id,int char_id
p->party.member[i].leader = 0;
if(p->party.member[i].account_id == account_id &&
p->party.member[i].char_id == char_id)
+ {
p->party.member[i].leader = 1;
+ inter_party_tosql(&p->party,PS_LEADER, i);
+ }
}
return 1;
}
// map server からの通信
-// ?1パケットのみ解析すること
-// ?パケット長デ?タはinter.cにセットしておくこと
-// ?パケット長チェックや、RFIFOSKIPは呼び出し元で行われるので行ってはならない
-// ?エラ?なら0(false)、そうでないなら1(true)をかえさなければならない
-int inter_party_parse_frommap(int fd) {
+// ・1パケットのみ解析すること
+// ・パケット長データはinter.cにセットしておくこと
+// ・パケット長チェックや、RFIFOSKIPは呼び出し元で行われるので行ってはならない
+// ・エラーなら0(false)、そうでないなら1(true)をかえさなければならない
+int inter_party_parse_frommap(int fd)
+{
RFIFOHEAD(fd);
switch(RFIFOW(fd,0)) {
case 0x3020: mapif_parse_CreateParty(fd, (char*)RFIFOP(fd,4), RFIFOB(fd,28), RFIFOB(fd,29), (struct party_member*)RFIFOP(fd,30)); break;
@@ -688,12 +748,105 @@ int inter_party_parse_frommap(int fd) {
default:
return 0;
}
+ return 1;
+}
+
+// サーバーから脱退要求(キャラ削除用)
+int inter_party_leave(int party_id,int account_id, int char_id)
+{
+ return mapif_parse_PartyLeave(-1,party_id,account_id, char_id);
+}
+
+int inter_party_CharOnline(int char_id, int party_id)
+{
+ struct party_data* p;
+ int i;
+
+ if( party_id == -1 )
+ {// Get party_id from the database
+ char* data;
+
+ if( SQL_ERROR == Sql_Query(sql_handle, "SELECT party_id FROM `%s` WHERE char_id='%d'", char_db, char_id) )
+ {
+ Sql_ShowDebug(sql_handle);
+ return 0;
+ }
+ if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
+ return 0; //Eh? No party?
+
+ Sql_GetData(sql_handle, 0, &data, NULL);
+ party_id = atoi(data);
+ Sql_FreeResult(sql_handle);
+ }
+ if (party_id == 0)
+ return 0; //No party...
+
+ p = inter_party_fromsql(party_id);
+ if(!p) {
+ ShowError("Character %d's party %d not found!\n", char_id, party_id);
+ return 0;
+ }
+
+ //Set member online
+ for(i=0; i<MAX_PARTY; i++) {
+ if (p->party.member[i].char_id == char_id) {
+ if (!p->party.member[i].online) {
+ p->party.member[i].online = 1;
+ p->party.count++;
+ if (p->party.member[i].lv < p->min_lv ||
+ p->party.member[i].lv > p->max_lv)
+ int_party_check_lv(p);
+ }
+ break;
+ }
+ }
return 1;
}
-// サ?バ?から?退要求(キャラ削除用)
-int inter_party_leave(int party_id, int account_id, int char_id) {
- return mapif_parse_PartyLeave(-1, party_id, account_id, char_id);
+int inter_party_CharOffline(int char_id, int party_id) {
+ struct party_data *p=NULL;
+ int i;
+
+ if( party_id == -1 )
+ {// Get guild_id from the database
+ char* data;
+
+ if( SQL_ERROR == Sql_Query(sql_handle, "SELECT party_id FROM `%s` WHERE char_id='%d'", char_db, char_id) )
+ {
+ Sql_ShowDebug(sql_handle);
+ return 0;
+ }
+
+ if( SQL_SUCCESS != Sql_NextRow(sql_handle) )
+ return 0; //Eh? No party?
+
+ Sql_GetData(sql_handle, 0, &data, NULL);
+ party_id = atoi(data);
+ Sql_FreeResult(sql_handle);
+ }
+ if (party_id == 0)
+ return 0; //No party...
+
+ //Character has a party, set character offline and check if they were the only member online
+ if ((p = inter_party_fromsql(party_id)) == NULL)
+ return 0;
+
+ //Set member offline
+ for(i=0; i< MAX_PARTY; i++) {
+ if(p->party.member[i].char_id == char_id)
+ {
+ p->party.member[i].online = 0;
+ p->party.count--;
+ if(p->party.member[i].lv == p->min_lv ||
+ p->party.member[i].lv == p->max_lv)
+ int_party_check_lv(p);
+ break;
+ }
+ }
+
+ if(!p->party.count)
+ //Parties don't have any data that needs be saved at this point... so just remove it from memory.
+ idb_remove(party_db_, party_id);
+ return 1;
}
-#endif //TXT_SQL_CONVERT