summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/char/char.c47
-rw-r--r--src/char/char.h2
-rw-r--r--src/char/int_party.c368
-rw-r--r--src/char/inter.c2
-rw-r--r--src/char_sql/char.c45
-rw-r--r--src/char_sql/char.h1
-rw-r--r--src/char_sql/int_party.c415
-rw-r--r--src/char_sql/inter.c2
-rw-r--r--src/common/mmo.h2
-rw-r--r--src/map/intif.c32
-rw-r--r--src/map/intif.h5
-rw-r--r--src/map/party.c64
-rw-r--r--src/map/skill.c2
13 files changed, 606 insertions, 381 deletions
diff --git a/src/char/char.c b/src/char/char.c
index c2e80ae8a..774554037 100644
--- a/src/char/char.c
+++ b/src/char/char.c
@@ -205,6 +205,16 @@ int isGM(int account_id) {
return 0;
}
+//Search character data from the aid/cid givem
+struct mmo_charstatus* search_character(int aid, int cid) {
+ int i;
+ for (i = 0; i < char_num; i++) {
+ if (char_dat[i].status.char_id == cid && char_dat[i].status.account_id == aid)
+ return &char_dat[i].status;
+ }
+ return NULL;
+}
+
//----------------------------------------------
// Search an character id
// (return character index or -1 (if not found))
@@ -1695,6 +1705,35 @@ int char_child(int parent_id, int child_id) {
(char_dat[parent_id].status.char_id == char_dat[child_id].status.mother)));
}
+int char_family(int cid1, int cid2, int cid3) {
+ int i, idx1 = -1, idx2 =-1;//, idx3 =-1;
+ for(i = 0; i < char_num && (idx1 == -1 || idx2 == -1/* || idx3 == 1*/); i++)
+ {
+ if (char_dat[i].status.char_id == cid1)
+ idx1 = i;
+ if (char_dat[i].status.char_id == cid2)
+ idx2 = i;
+// if (char_dat[i].status.char_id == cid2)
+// idx3 = i;
+ }
+ if (idx1 == -1 || idx2 == -1/* || idx3 == -1*/)
+ return 0; //Some character not found??
+
+ //Unless the dbs are corrupted, these 3 checks should suffice, even though
+ //we could do a lot more checks and force cross-reference integrity.
+ if(char_dat[idx1].status.partner_id == cid2 &&
+ char_dat[idx1].status.child == cid3)
+ return 1; //cid1/cid2 parents. cid3 child.
+
+ if(char_dat[idx1].status.partner_id == cid3 &&
+ char_dat[idx1].status.child == cid2)
+ return 1; //cid1/cid3 parents. cid2 child.
+
+ if(char_dat[idx2].status.partner_id == cid3 &&
+ char_dat[idx2].status.child == cid1)
+ return 1; //cid2/cid3 parents. cid1 child.
+ return 0;
+}
//------------------------------------------------------------
// E-mail check: return 0 (not correct) or 1 (valid). by [Yor]
//------------------------------------------------------------
@@ -2636,8 +2675,6 @@ int parse_frommap(int fd) {
data = status_search_scdata(aid, cid);
if (data->count > 0)
{ //Deliver status change data.
- int i;
-
WFIFOW(fd,0) = 0x2b1d;
WFIFOW(fd,2) = 14 + data->count*sizeof(struct status_change_data);
WFIFOL(fd,4) = aid;
@@ -2739,7 +2776,7 @@ int parse_frommap(int fd) {
return 0;
{
unsigned short name;
- int map_id, map_fd = -1, i;
+ int map_id, map_fd = -1;
struct online_char_data* data;
struct mmo_charstatus* char_data;
@@ -2948,7 +2985,7 @@ int parse_frommap(int fd) {
if (RFIFOREST(fd) < 12)
return 0;
{
- int i, j;
+ int j;
int id = RFIFOL(fd, 2);
int fame = RFIFOL(fd, 6);
char type = RFIFOB(fd, 10);
@@ -3054,7 +3091,7 @@ int parse_frommap(int fd) {
return 0;
{
#ifdef ENABLE_SC_SAVING
- int count, aid, cid, i;
+ int count, aid, cid;
struct scdata *data;
aid = RFIFOL(fd, 4);
cid = RFIFOL(fd, 8);
diff --git a/src/char/char.h b/src/char/char.h
index 773532035..780e8ba6e 100644
--- a/src/char/char.h
+++ b/src/char/char.h
@@ -23,6 +23,7 @@ struct mmo_map_server{
unsigned short map[MAX_MAP_PER_SERVER];
};
+struct mmo_charstatus* search_character(int aid, int cid);
int search_character_index(char* character_name);
char * search_character_name(int index);
@@ -32,6 +33,7 @@ int mapif_send(int fd,unsigned char *buf, unsigned int len);
int char_married(int pl1,int pl2);
int char_child(int parent_id, int child_id);
+int char_family(int cid1, int cid2, int cid3);
int char_log(char *fmt, ...);
diff --git a/src/char/int_party.c b/src/char/int_party.c
index a16735b64..0c1608361 100644
--- a/src/char/int_party.c
+++ b/src/char/int_party.c
@@ -4,6 +4,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
#include "../common/mmo.h"
#include "../common/socket.h"
@@ -16,12 +17,81 @@
char party_txt[1024] = "save/party.txt";
+struct party_data {
+ struct party party;
+ unsigned int min_lv, max_lv;
+ unsigned char size; //Total size of party.
+ unsigned family :1; //Is this party a family?
+};
+
static struct dbt *party_db;
static int party_newid = 100;
int mapif_party_broken(int party_id, int flag);
int party_check_empty(struct party *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);
+
+//Updates party's level range and unsets even share if broken.
+static int int_party_check_lv(struct party_data *p) {
+ int i,lv;
+ p->min_lv = UINT_MAX;
+ p->max_lv = 0;
+ for(i=0;i<MAX_PARTY;i++){
+ if(!p->party.member[i].online)
+ continue;
+
+ lv=p->party.member[i].lv;
+ if (lv < p->min_lv) p->min_lv = lv;
+ if (lv > p->max_lv) p->max_lv = lv;
+ }
+
+ if (p->party.exp && !party_check_exp_share(p)) {
+ p->party.exp = 0;
+ mapif_party_optionchanged(0, &p->party, 0, 0);
+ return 0;
+ }
+ return 1;
+}
+
+//Calculates the state of a party.
+static void int_party_calc_state(struct party_data *p)
+{
+ int i, lv;
+ p->min_lv = UINT_MAX;
+ p->max_lv = 0;
+ p->party.count =
+ p->size =
+ p->family = 0;
+
+ //Check party size, max/min levels.
+ for(i=0;i<MAX_PARTY;i++){
+ lv=p->party.member[i].lv;
+ if (!lv) continue;
+ p->size++;
+ if(p->party.member[i].online)
+ {
+ if( lv < p->min_lv ) p->min_lv=lv;
+ if( p->max_lv < lv ) p->max_lv=lv;
+ p->party.count++;
+ }
+ }
+ if(p->size == 3) {
+ //Check Family State.
+ p->family = char_family(
+ p->party.member[0].char_id,
+ p->party.member[1].char_id,
+ p->party.member[2].char_id
+ );
+ }
+
+ if (p->party.exp && !party_check_exp_share(p)) {
+ p->party.exp = 0; //Set off even share.
+ mapif_party_optionchanged(0, &p->party, 0, 0);
+ }
+ return;
+}
// パ?ティデ?タの文字列への?換
int inter_party_tostr(char *str, struct party *p) {
@@ -30,7 +100,7 @@ int inter_party_tostr(char *str, struct party *p) {
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%s\t", m->account_id, m->char_id, m->leader, ((m->account_id > 0) ? m->name : "NoMember"));
+ len += sprintf(str + len, "%d,%d,%d\t", m->account_id, m->char_id, m->leader);
}
return 0;
@@ -41,7 +111,8 @@ int inter_party_fromstr(char *str, struct party *p) {
int i, j;
int tmp_int[16];
char tmp_str[256];
-
+ struct mmo_charstatus* status;
+
memset(p, 0, sizeof(struct party));
// printf("sscanf party main info\n");
@@ -63,17 +134,24 @@ int inter_party_fromstr(char *str, struct party *p) {
return 1;
// printf("sscanf party member info %d\n", i);
- if (sscanf(str + 1, "%d,%d,%d\t%255[^\t]\t", &tmp_int[0], &tmp_int[1], &tmp_int[2], tmp_str) != 4)
+ if (sscanf(str + 1, "%d,%d,%d\t", &tmp_int[0], &tmp_int[1], &tmp_int[2]) != 3)
return 1;
m->account_id = tmp_int[0];
m->char_id = tmp_int[1];
m->leader = tmp_int[2]?1:0;
- memcpy(m->name, tmp_str, NAME_LENGTH-1);
-// printf(" %d %d [%s]\n", tmp_int[0], tmp_int[1], tmp_str);
- for(j = 0; j < 2 && str != NULL; j++)
- str = strchr(str + 1, '\t');
+ str = strchr(str + 1, '\t');
+
+ 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;
}
return 0;
@@ -82,7 +160,7 @@ int inter_party_fromstr(char *str, struct party *p) {
// パ?ティデ?タのロ?ド
int inter_party_init() {
char line[8192];
- struct party *p;
+ struct party_data *p;
FILE *fp;
int c = 0;
int i, j;
@@ -99,17 +177,18 @@ int inter_party_init() {
continue;
}
- p = (struct party*)aCalloc(sizeof(struct party), 1);
+ p = (struct party_data*)aCalloc(sizeof(struct party_data), 1);
if (p == NULL){
ShowFatalError("int_party: out of memory!\n");
exit(0);
}
- memset(p, 0, sizeof(struct party));
- if (inter_party_fromstr(line, p) == 0 && p->party_id > 0) {
- if (p->party_id >= party_newid)
- party_newid = p->party_id + 1;
- idb_put(party_db, p->party_id, p);
- party_check_empty(p);
+ 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);
@@ -132,7 +211,7 @@ int inter_party_save_sub(DBKey key, void *data, va_list ap) {
char line[8192];
FILE *fp;
- inter_party_tostr(line, (struct party *)data);
+ inter_party_tostr(line, &((struct party_data*)data)->party);
fp = va_arg(ap, FILE *);
fprintf(fp, "%s" RETCODE, line);
@@ -155,56 +234,29 @@ int inter_party_save() {
// パ?ティ名?索用
int search_partyname_sub(DBKey key,void *data,va_list ap) {
- struct party *p = (struct party *)data,**dst;
+ struct party_data *p = (struct party_data *)data,**dst;
char *str;
str = va_arg(ap, char *);
- dst = va_arg(ap, struct party **);
- if (strncmpi(p->name, str, NAME_LENGTH) == 0)
+ dst = va_arg(ap, struct party_data **);
+ if (strncmpi(p->party.name, str, NAME_LENGTH) == 0)
*dst = p;
return 0;
}
// パ?ティ名?索
-struct party* search_partyname(char *str) {
- struct party *p = NULL;
+struct party_data* search_partyname(char *str) {
+ struct party_data *p = NULL;
party_db->foreach(party_db, search_partyname_sub, str, &p);
return p;
}
// EXP公平分配できるかチェック
-int party_check_exp_share(struct party *p) {
- int i, oi[MAX_PARTY], dudes=0;
- int maxlv = 0, minlv = 0x7fffffff;
-
- for(i = 0; i < MAX_PARTY; i++) {
- int lv = p->member[i].lv;
- if (p->member[i].online) {
- if (lv < minlv)
- minlv = lv;
- if (maxlv < lv)
- maxlv = lv;
- if( lv >= 70 )
- dudes+=1000;
- oi[dudes%1000] = i;
- dudes++;
- }
- }
- if((dudes/1000 >= 2) && (dudes%1000 == 3) && maxlv-minlv>party_share_level) {
- int pl1=0,pl2=0,pl3=0;
- pl1=search_character_index(p->member[oi[0]].name);
- pl2=search_character_index(p->member[oi[1]].name);
- pl3=search_character_index(p->member[oi[2]].name);
- ShowDebug("PARTY: group of 3 Id1 %d lv %d name %s Id2 %d lv %d name %s Id3 %d lv %d name %s\n",pl1,p->member[oi[0]].lv,p->member[oi[0]].name,pl2,p->member[oi[1]].lv,p->member[oi[1]].name,pl3,p->member[oi[2]].lv,p->member[oi[2]].name);
- if (char_married(pl1,pl2) && char_child(pl1,pl3))
- return 1;
- if (char_married(pl1,pl3) && char_child(pl1,pl2))
- return 1;
- if (char_married(pl2,pl3) && char_child(pl2,pl1))
- return 1;
- }
- return (maxlv==0 || maxlv-minlv<=party_share_level);
+int party_check_exp_share(struct party_data *p) {
+ return (p->party.count == 0 || //If noone is online, don't mess with the share type.
+ (p->family && p->party.count == 3) || //All 3 MUST be online for share to trigger.
+ p->max_lv - p->min_lv <= party_share_level);
}
// パ?ティが空かどうかチェック
@@ -224,20 +276,22 @@ int party_check_empty(struct party *p) {
// キャラの競合がないかチェック用
int party_check_conflict_sub(DBKey key, void *data, va_list ap) {
- struct party *p = (struct party *)data;
+ struct party_data *p = (struct party_data *)data;
int party_id, account_id, char_id, i;
party_id=va_arg(ap, int);
account_id=va_arg(ap, int);
char_id=va_arg(ap, int);
- if (p->party_id == party_id) //No conflict to check
+ if (p->party.party_id == party_id) //No conflict to check
return 0;
for(i = 0; i < MAX_PARTY; i++) {
- if (p->member[i].account_id == account_id && p->member[i].char_id == char_id) {
- ShowWarning("int_party: party conflict! %d %d %d\n", account_id, party_id, p->party_id);
- mapif_parse_PartyLeave(-1, p->party_id, account_id, char_id);
+ if(p->party.member[i].account_id == account_id &&
+ p->party.member[i].char_id == char_id)
+ {
+ ShowWarning("int_party: party conflict! %d %d %d\n", account_id, party_id, p->party.party_id);
+ mapif_parse_PartyLeave(-1, p->party.party_id, account_id, char_id);
}
}
@@ -332,7 +386,7 @@ int mapif_party_optionchanged(int fd,struct party *p, int account_id, int flag)
//Checks whether the even-share setting of a party is broken when a character logs in. [Skotlex]
int inter_party_logged(int party_id, int account_id, int char_id)
{
- struct party *p;
+ struct party_data *p;
int i;
if (!party_id)
return 0;
@@ -341,17 +395,16 @@ int inter_party_logged(int party_id, int account_id, int char_id)
if(p==NULL)
return 0;
for (i = 0; i < MAX_PARTY; i++)
- if (p->member[i].account_id == account_id && p->member[i].char_id == char_id)
+ if(p->party.member[i].account_id == account_id &&
+ p->party.member[i].char_id == char_id)
{
- p->member[i].online = 1;
+ 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;
}
- if(p->exp && !party_check_exp_share(p))
- {
- p->exp=0;
- mapif_party_optionchanged(0,p,0,0);
- return 1;
- }
return 0;
}
@@ -413,21 +466,21 @@ int mapif_party_message(int party_id, int account_id, char *mes, int len, int sf
// パ?ティ
-int mapif_parse_CreateParty(int fd, int account_id, int char_id, char *name, char *nick, unsigned short map, int lv, int item, int item2) {
- struct party *p;
+int mapif_parse_CreateParty(int fd, char *name, int item, int item2, struct party_member *leader) {
+ struct party_data *p;
int i;
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, account_id, char_id, NULL);
+ 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, account_id, char_id, NULL);
+ mapif_party_created(fd, leader->account_id, leader->char_id, NULL);
return 0;
}
@@ -435,51 +488,45 @@ int mapif_parse_CreateParty(int fd, int account_id, int char_id, char *name, cha
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, account_id, 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, account_id, char_id, NULL);
+ mapif_party_created(fd, leader->account_id, leader->char_id, NULL);
return 0;
}
}
- p = (struct party *) aCalloc(sizeof(struct party), 1);
+ p = (struct party_data *) aCalloc(sizeof(struct party_data), 1);
if (p == NULL) {
ShowFatalError("int_party: out of memory !\n");
- mapif_party_created(fd,account_id,char_id,NULL);
+ mapif_party_created(fd,leader->account_id,leader->char_id,NULL);
return 0;
}
- p->party_id = party_newid++;
- memcpy(p->name, name, NAME_LENGTH);
- p->exp = 0;
- p->item=(item?1:0)|(item2?2:0);
-
- p->member[0].account_id = account_id;
- p->member[0].char_id = char_id;
- memcpy(p->member[0].name, nick, NAME_LENGTH);
- p->member[0].map = map;
- p->member[0].leader = 1;
- p->member[0].online = 1;
- p->member[0].lv = lv;
-
- idb_put(party_db, p->party_id, p);
-
- mapif_party_created(fd, account_id, char_id, p);
- mapif_party_info(fd, p);
+ p->party.party_id = party_newid++;
+ 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);
+
+ mapif_party_created(fd, leader->account_id, leader->char_id, &p->party);
+ mapif_party_info(fd, &p->party);
return 0;
}
// パ?ティ情報要求
int mapif_parse_PartyInfo(int fd, int party_id) {
- struct party *p;
+ struct party_data *p;
p = idb_get(party_db, party_id);
if (p != NULL)
- mapif_party_info(fd, p);
+ mapif_party_info(fd, &p->party);
else
mapif_party_noinfo(fd, party_id);
@@ -487,47 +534,41 @@ int mapif_parse_PartyInfo(int fd, int party_id) {
}
// パ?ティ追加要求
-int mapif_parse_PartyAddMember(int fd, int party_id, int account_id, int char_id, char *nick, unsigned short map, int lv) {
- struct party *p;
+int mapif_parse_PartyAddMember(int fd, int party_id, struct party_member *member) {
+ struct party_data *p;
int i;
p = idb_get(party_db, party_id);
- if (p == NULL) {
- mapif_party_memberadded(fd, party_id, account_id, char_id, 1);
+ if (p == NULL || p->size == MAX_PARTY) {
+ mapif_party_memberadded(fd, party_id, member->account_id, member->char_id, 1);
return 0;
}
for(i = 0; i < MAX_PARTY; i++) {
- if (p->member[i].account_id == 0) {
- int flag = 0;
-
- p->member[i].account_id = account_id;
- p->member[i].char_id = char_id;
- memcpy(p->member[i].name, nick, NAME_LENGTH);
- p->member[i].map = map;
- p->member[i].leader = 0;
- p->member[i].online = 1;
- p->member[i].lv = lv;
- mapif_party_memberadded(fd, party_id, account_id, char_id, 0);
- mapif_party_info(-1, p);
-
- if (p->exp && !party_check_exp_share(p)) {
- p->exp = 0;
- flag = 0x01;
- }
- if (flag)
- mapif_party_optionchanged(fd, p, 0, 0);
+ if (p->party.member[i].account_id == 0) {
+ memcpy(&p->party.member[i], member, sizeof(struct party_member));
+ p->party.member[i].leader = 0;
+ if (p->party.member[i].online) p->party.count++;
+ p->size++;
+ if (member->lv < p->min_lv || member->lv > p->max_lv || p->family)
+ {
+ if (p->family) p->family = 0; //Family state broken.
+ int_party_check_lv(p);
+ } else if (p->size == 3) //Check family state.
+ int_party_calc_state(p);
+ mapif_party_memberadded(fd, party_id, member->account_id, member->char_id, 0);
+ mapif_party_info(-1, &p->party);
return 0;
}
}
- mapif_party_memberadded(fd, party_id, account_id, char_id, 1);
+ mapif_party_memberadded(fd, party_id, member->account_id, member->char_id, 1);
return 0;
}
// パ?ティ?設定?更要求
int mapif_parse_PartyChangeOption(int fd, int party_id, int account_id, int exp, int flag) {
- struct party *p;
+ struct party_data *p;
//NOTE: No clue what that flag is about, in all observations so far it always comes as 0. [Skotlex]
flag = 0;
@@ -535,47 +576,49 @@ int mapif_parse_PartyChangeOption(int fd, int party_id, int account_id, int exp,
if (p == NULL)
return 0;
- p->exp = exp;
+ p->party.exp = exp;
if (exp>0 && !party_check_exp_share(p)) {
flag |= 0x01;
- p->exp = 0;
+ p->party.exp = 0;
}
- mapif_party_optionchanged(fd, p, account_id, flag);
+ mapif_party_optionchanged(fd, &p->party, account_id, flag);
return 0;
}
// パ?ティ?退要求
int mapif_parse_PartyLeave(int fd, int party_id, int account_id, int char_id) {
- struct party *p;
- int i;
+ struct party_data *p;
+ int i,lv;
p = idb_get(party_db, party_id);
- if (p != NULL) {
- for(i = 0; i < MAX_PARTY; i++) {
- if (p->member[i].account_id == account_id && p->member[i].char_id == char_id)
+ if (!p) return 0;
+
+ for(i = 0; i < MAX_PARTY; i++) {
+ if(p->party.member[i].account_id == account_id &&
+ p->party.member[i].char_id == char_id)
+ {
+ mapif_party_leaved(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)
{
- mapif_party_leaved(party_id, account_id, char_id);
- memset(&p->member[i], 0, sizeof(struct party_member));
- //Normally unneeded except when a family is even-sharing
- //and one of the three leaves the party.
- if(p->exp && !party_check_exp_share(p)){
- p->exp=0;
- mapif_party_optionchanged(fd,p,0,0);
- }
- if (party_check_empty(p) == 0)
- mapif_party_info(-1, p);// まだ人がいるのでデ?タ送信
- return 0;
+ 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);
+ return 0;
}
}
-
return 0;
}
// パ?ティマップ更新要求
int mapif_parse_PartyChangeMap(int fd, int party_id, int account_id, int char_id, unsigned short map, int online, int lv) {
- struct party *p;
+ struct party_data *p;
int i;
p = idb_get(party_db, party_id);
@@ -583,18 +626,25 @@ int mapif_parse_PartyChangeMap(int fd, int party_id, int account_id, int char_id
return 0;
for(i = 0; i < MAX_PARTY; i++) {
- if (p->member[i].account_id == account_id && p->member[i].char_id == char_id)
+ if(p->party.member[i].account_id == account_id &&
+ p->party.member[i].char_id == char_id)
{
- p->member[i].map = map;
- p->member[i].online = online;
- if (p->member[i].lv != lv) {
- p->member[i].lv = lv;
- if (p->exp && !party_check_exp_share(p)) {
- p->exp = 0;
- mapif_party_optionchanged(fd, p, 0, 0);
- }
+ p->party.member[i].map = map;
+ if (p->party.member[i].online != online) {
+ p->party.member[i].online = online;
+ if (online) p->party.count++;
+ else p->party.count--;
+ }
+ if (p->party.member[i].lv != lv) {
+ if(p->party.member[i].lv == p->min_lv ||
+ p->party.member[i].lv == p->max_lv)
+ {
+ p->party.member[i].lv = lv;
+ int_party_check_lv(p);
+ } else
+ p->party.member[i].lv = lv;
}
- mapif_party_membermoved(p, i);
+ mapif_party_membermoved(&p->party, i);
break;
}
}
@@ -604,11 +654,6 @@ int mapif_parse_PartyChangeMap(int fd, int party_id, int account_id, int char_id
// パ?ティ解散要求
int mapif_parse_BreakParty(int fd, int party_id) {
- struct party *p;
-
- p = idb_get(party_db, party_id);
- if (p == NULL)
- return 0;
idb_remove(party_db, party_id);
mapif_party_broken(fd, party_id);
@@ -627,7 +672,7 @@ int mapif_parse_PartyCheck(int fd, int party_id, int account_id, int char_id) {
int mapif_parse_PartyLeaderChange(int fd,int party_id,int account_id,int char_id)
{
- struct party *p;
+ struct party_data *p;
int i;
p = idb_get(party_db, party_id);
@@ -636,10 +681,11 @@ int mapif_parse_PartyLeaderChange(int fd,int party_id,int account_id,int char_id
for (i = 0; i < MAX_PARTY; i++)
{
- if(p->member[i].leader)
- p->member[i].leader = 0;
- if(p->member[i].account_id == account_id && p->member[i].char_id == char_id)
- p->member[i].leader = 1;
+ if(p->party.member[i].leader)
+ 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;
}
return 1;
}
@@ -652,9 +698,9 @@ int mapif_parse_PartyLeaderChange(int fd,int party_id,int account_id,int char_id
int inter_party_parse_frommap(int fd) {
RFIFOHEAD(fd);
switch(RFIFOW(fd,0)) {
- case 0x3020: mapif_parse_CreateParty(fd, RFIFOL(fd,2), RFIFOL(fd,6),(char*)RFIFOP(fd,10), (char*)RFIFOP(fd,34), RFIFOW(fd,58), RFIFOW(fd,60), RFIFOB(fd,62), RFIFOB(fd,63)); break;
+ case 0x3020: mapif_parse_CreateParty(fd, (char*)RFIFOP(fd,4), RFIFOB(fd,28), RFIFOB(fd,29), (struct party_member*)RFIFOP(fd,30)); break;
case 0x3021: mapif_parse_PartyInfo(fd, RFIFOL(fd,2)); break;
- case 0x3022: mapif_parse_PartyAddMember(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), (char*)RFIFOP(fd,14), RFIFOW(fd,38), RFIFOW(fd,40)); break;
+ case 0x3022: mapif_parse_PartyAddMember(fd, RFIFOL(fd,4), (struct party_member*)RFIFOP(fd,8)); break;
case 0x3023: mapif_parse_PartyChangeOption(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOW(fd,10), RFIFOW(fd,12)); break;
case 0x3024: mapif_parse_PartyLeave(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)); break;
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;
diff --git a/src/char/inter.c b/src/char/inter.c
index 491eb8f3a..c3940765e 100644
--- a/src/char/inter.c
+++ b/src/char/inter.c
@@ -55,7 +55,7 @@ int inter_send_packet_length[] = {
int inter_recv_packet_length[] = {
-1,-1, 7,-1, -1,13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3000-0x300f
6,-1, 0, 0, 0, 0, 0, 0, 10,-1, 0, 0, 0, 0, 0, 0, //0x3010-0x301f
- 64, 6,42,14, 14,19, 6,-1, 14,14, 0, 0, 0, 0, 0, 0, //0x3020-0x302f
+ -1, 6,-1,14, 14,19, 6,-1, 14,14, 0, 0, 0, 0, 0, 0, //0x3020-0x302f
-1, 6,-1,-1, 55,19, 6,-1, 14,-1,-1,-1, 14,19,186,-1, //0x3030-0x303f
5, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
diff --git a/src/char_sql/char.c b/src/char_sql/char.c
index a158bec01..58fa10784 100644
--- a/src/char_sql/char.c
+++ b/src/char_sql/char.c
@@ -4408,3 +4408,48 @@ int char_married(int pl1,int pl2) {
else
return 0;
}
+
+int char_family(int pl1,int pl2,int pl3) {
+ int charid, partnerid, childid;
+ sprintf (tmp_sql, "SELECT `char_id`,`partner_id`,`child` FROM `%s` WHERE `char_id` IN ('%d','%d','%d')", char_db, pl1, pl2, pl3);
+ if (mysql_query (&mysql_handle, tmp_sql)) {
+ ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
+ ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
+ return 0;
+ }
+ sql_res = mysql_store_result (&mysql_handle);
+ if (!sql_res) return 0;
+
+ while((sql_row = mysql_fetch_row(sql_res)))
+ {
+ charid = atoi(sql_row[0]);
+ partnerid = atoi(sql_row[1]);
+ childid = atoi(sql_row[2]);
+ if (charid == pl1) {
+ if ((pl2 == partnerid && pl3 == childid) ||
+ (pl3 == partnerid && pl2 == childid)
+ ) {
+ mysql_free_result (sql_res);
+ return 1;
+ }
+ }
+ if(charid == pl2) {
+ if ((pl1 == partnerid && pl3 == childid) ||
+ (pl3 == partnerid && pl1 == childid)
+ ) {
+ mysql_free_result (sql_res);
+ return 1;
+ }
+ }
+ if(charid == pl3) {
+ if ((pl1 == partnerid && pl2 == childid) ||
+ (pl2 == partnerid && pl1 == childid)
+ ) {
+ mysql_free_result (sql_res);
+ return 1;
+ }
+ }
+ }
+ mysql_free_result (sql_res);
+ return 0;
+}
diff --git a/src/char_sql/char.h b/src/char_sql/char.h
index e6215765c..343d04b4e 100644
--- a/src/char_sql/char.h
+++ b/src/char_sql/char.h
@@ -54,6 +54,7 @@ int mapif_send(int fd,unsigned char *buf,unsigned int len);
int char_married(int pl1,int pl2);
int char_child(int parent_id, int child_id);
+int char_family(int pl1,int pl2,int pl3);
int char_loadName(int char_id, char* name);
diff --git a/src/char_sql/int_party.c b/src/char_sql/int_party.c
index fa0d3efb4..3a2bfa094 100644
--- a/src/char_sql/int_party.c
+++ b/src/char_sql/int_party.c
@@ -7,18 +7,28 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <limits.h>
#include "char.h"
#include "../common/db.h"
#include "../common/strlib.h"
#include "../common/socket.h"
#include "../common/showmsg.h"
-static struct party *party_pt;
+struct party_data {
+ struct party party;
+ unsigned int min_lv, max_lv;
+ unsigned char size; //Total size of party.
+ unsigned family :1; //Is this party a family?
+};
+
+static struct party_data *party_pt;
static struct dbt *party_db_;
int mapif_party_broken(int party_id,int flag);
-int party_check_empty(struct party *p);
+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);
#ifndef SQL_DEBUG
@@ -43,15 +53,76 @@ int mapif_parse_PartyLeave(int fd, int party_id, int account_id, int char_id);
#define PS_DELMEMBER 0x10
//Specify that this party must be deleted.
#define PS_BREAK 0x20
+
+//Updates party's level range and unsets even share if broken.
+static int int_party_check_lv(struct party_data *p) {
+ int i,lv;
+ p->min_lv = UINT_MAX;
+ p->max_lv = 0;
+ for(i=0;i<MAX_PARTY;i++){
+ if(!p->party.member[i].online)
+ continue;
+
+ lv=p->party.member[i].lv;
+ if (lv < p->min_lv) p->min_lv = lv;
+ if (lv > p->max_lv) p->max_lv = lv;
+ }
+
+ if (p->party.exp && !party_check_exp_share(p)) {
+ p->party.exp = 0;
+ mapif_party_optionchanged(0, &p->party, 0, 0);
+ return 0;
+ }
+ return 1;
+}
+//Calculates the state of a party.
+static void int_party_calc_state(struct party_data *p)
+{
+ int i, lv;
+ p->min_lv = UINT_MAX;
+ p->max_lv = 0;
+ p->party.count =
+ p->size =
+ p->family = 0;
+
+ //Check party size, max/min levels.
+ for(i=0;i<MAX_PARTY;i++){
+ lv=p->party.member[i].lv;
+ if (!lv) continue;
+ p->size++;
+ if(p->party.member[i].online)
+ {
+ if( lv < p->min_lv ) p->min_lv=lv;
+ if( p->max_lv < lv ) p->max_lv=lv;
+ p->party.count++;
+ }
+ }
+ if(p->size == 3) {
+ //Check Family State.
+ p->family = char_family(
+ p->party.member[0].char_id,
+ p->party.member[1].char_id,
+ p->party.member[2].char_id
+ );
+ }
+
+ if (p->party.exp && !party_check_exp_share(p)) {
+ p->party.exp = 0; //Set off even share.
+ mapif_party_optionchanged(0, &p->party, 0, 0);
+ }
+ return;
+}
// Save party to mysql
-int inter_party_tosql(struct party *p, int flag, int index)
+int inter_party_tosql(struct party_data *party, int flag, int index)
{
// 'party' ('party_id','name','exp','item','leader_id','leader_char')
char t_name[NAME_LENGTH*2]; //Required for jstrescapecpy [Skotlex]
+ struct party *p;
int party_id;
- if (p == NULL || p->party_id == 0)
+ if (party == NULL || party->party.party_id == 0)
return 0;
+ p = &party->party;
party_id = p->party_id;
#ifdef NOISY
@@ -84,18 +155,19 @@ int inter_party_tosql(struct party *p, int flag, int index)
if (mysql_query(&mysql_handle, tmp_sql)) {
ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
ShowDebug("at %s:%d - %s\n", __FILE__,__LINE__,tmp_sql);
- aFree(p); //Free party, couldn't create it.
+ aFree(party); //Free party, couldn't create it.
return 0;
}
if(mysql_field_count(&mysql_handle) == 0 &&
mysql_insert_id(&mysql_handle) != 0)
party_id = p->party_id = (int)mysql_insert_id(&mysql_handle);
else { //Failed to retrieve ID??
- aFree(p); //Free party, couldn't create it.
+ aFree(party); //Free party, couldn't create it.
return 0;
}
//Add party to db
- idb_put(party_db_, party_id, p);
+ int_party_calc_state(party);
+ idb_put(party_db_, party_id, party);
}
if (flag&PS_BASIC) {
@@ -144,10 +216,10 @@ int inter_party_tosql(struct party *p, int flag, int index)
}
// Read party from mysql
-struct party *inter_party_fromsql(int party_id)
+struct party_data *inter_party_fromsql(int party_id)
{
int leader_id = 0, leader_char = 0;
- struct party *p;
+ struct party_data *p;
#ifdef NOISY
ShowInfo("Load party request ("CL_BOLD"%d"CL_RESET")\n", party_id);
#endif
@@ -159,7 +231,7 @@ struct party *inter_party_fromsql(int party_id)
return p;
p = party_pt;
- memset(p, 0, sizeof(struct party));
+ memset(p, 0, sizeof(struct party_data));
sprintf(tmp_sql, "SELECT `party_id`, `name`,`exp`,`item`, `leader_id`, `leader_char` FROM `%s` WHERE `party_id`='%d'",
party_db, party_id); // TBR
@@ -177,16 +249,16 @@ struct party *inter_party_fromsql(int party_id)
mysql_free_result(sql_res);
return NULL;
}
- p->party_id = party_id;
- memcpy(p->name, sql_row[1], NAME_LENGTH-1);
- p->exp = atoi(sql_row[2])?1:0;
- p->item = atoi(sql_row[3]);
+ p->party.party_id = party_id;
+ memcpy(&p->party.name, sql_row[1], NAME_LENGTH-1);
+ p->party.exp = atoi(sql_row[2])?1:0;
+ p->party.item = atoi(sql_row[3]);
leader_id = atoi(sql_row[4]);
leader_char = atoi(sql_row[5]);
mysql_free_result(sql_res);
// Load members
- sprintf(tmp_sql,"SELECT `account_id`,`char_id`,`name`,`base_level`,`last_map`,`online` FROM `%s` WHERE `party_id`='%d'",
+ sprintf(tmp_sql,"SELECT `account_id`,`char_id`,`name`,`base_level`,`last_map`,`online`,`class` FROM `%s` WHERE `party_id`='%d'",
char_db, party_id); // TBR
if (mysql_query(&mysql_handle, tmp_sql)) {
ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
@@ -196,8 +268,8 @@ struct party *inter_party_fromsql(int party_id)
sql_res = mysql_store_result(&mysql_handle);
if (sql_res) {
int i;
- for (i = 0; (sql_row = mysql_fetch_row(sql_res)); i++) {
- struct party_member *m = &p->member[i];
+ for (i = 0; i<MAX_PARTY && (sql_row = mysql_fetch_row(sql_res)); i++) {
+ struct party_member *m = &p->party.member[i];
m->account_id = atoi(sql_row[0]);
m->char_id = atoi(sql_row[1]);
m->leader = (m->account_id == leader_id && m->char_id == leader_char)?1:0;
@@ -205,15 +277,18 @@ struct party *inter_party_fromsql(int party_id)
m->lv = atoi(sql_row[3]);
m->map = mapindex_name2id(sql_row[4]);
m->online = atoi(sql_row[5])?1:0;
+ m->class_ = atoi(sql_row[6]);
}
mysql_free_result(sql_res);
}
if (save_log)
- ShowInfo("Party loaded (%d - %s).\n",party_id, p->name);
+ ShowInfo("Party loaded (%d - %s).\n",party_id, p->party.name);
//Add party to memory.
- p = aCalloc(1, sizeof(struct party));
- memcpy(p, party_pt, sizeof(struct party));
+ p = aCalloc(1, sizeof(struct party_data));
+ memcpy(p, party_pt, sizeof(struct party_data));
+ //init state
+ int_party_calc_state(p);
idb_put(party_db_, party_id, p);
return p;
}
@@ -221,7 +296,7 @@ struct party *inter_party_fromsql(int party_id)
int inter_party_sql_init(void){
//memory alloc
party_db_ = db_alloc(__FILE__,__LINE__,DB_INT,DB_OPT_RELEASE_DATA,sizeof(int));
- party_pt = (struct party*)aCalloc(sizeof(struct party), 1);
+ party_pt = (struct party_data*)aCalloc(sizeof(struct party_data), 1);
if (!party_pt) {
ShowFatalError("inter_party_sql_init: Out of Memory!\n");
exit(1);
@@ -248,7 +323,7 @@ void inter_party_sql_final(void)
}
// Search for the party according to its name
-struct party* search_partyname(char *str)
+struct party_data* search_partyname(char *str)
{
char t_name[NAME_LENGTH*2];
int party_id;
@@ -271,51 +346,23 @@ struct party* search_partyname(char *str)
return inter_party_fromsql(party_id);
}
-// EXP公平分配できるかチェック
-int party_check_exp_share(struct party *p)
+// Returns whether this party can keep having exp share or not.
+int party_check_exp_share(struct party_data *p)
{
- int i, oi[MAX_PARTY], dudes=0;
- int maxlv=0,minlv=0x7fffffff;
-
- for(i=0;i<MAX_PARTY;i++){
- int lv=p->member[i].lv;
- if (!lv) continue;
- if( p->member[i].online ){
- if( lv < minlv ) minlv=lv;
- if( maxlv < lv ) maxlv=lv;
- if( lv >= 70 ) dudes+=1000;
- oi[dudes%1000] = i;
- dudes++;
- }
- }
- if((dudes/1000 >= 2) && (dudes%1000 == 3) && maxlv-minlv>party_share_level)
- {
- int pl1=0,pl2=0,pl3=0;
- pl1=p->member[oi[0]].char_id;
- pl2=p->member[oi[1]].char_id;
- pl3=p->member[oi[2]].char_id;
- if (char_married(pl1,pl2) && char_child(pl1,pl3))
- return 1;
- if (char_married(pl1,pl3) && char_child(pl1,pl2))
- return 1;
- if (char_married(pl2,pl3) && char_child(pl2,pl1))
- return 1;
- }
- return (maxlv==0 || maxlv-minlv<=party_share_level);
+ return (p->party.count == 0 || //If noone is online, don't mess with the share type.
+ (p->family && p->party.count == 3) || //All 3 MUST be online for share to trigger.
+ p->max_lv - p->min_lv <= party_share_level);
}
// Is there any member in the party?
-int party_check_empty(struct party *p)
+int party_check_empty(struct party_data *p)
{
int i;
- if (p==NULL||p->party_id==0) return 1;
- for(i=0;i<MAX_PARTY;i++){
- if(p->member[i].account_id>0){
- return 0;
- }
- }
+ 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_id,0);
+ mapif_party_broken(p->party.party_id,0);
inter_party_tosql(p, PS_BREAK, 0);
return 1;
}
@@ -364,10 +411,11 @@ int mapif_party_noinfo(int fd,int party_id)
// パーティ情報まとめ送り
int mapif_party_info(int fd,struct party *p)
{
- unsigned char buf[10+sizeof(struct party)];
+ unsigned char buf[5+sizeof(struct party)];
WBUFW(buf,0)=0x3821;
- memcpy(buf+4,p,sizeof(struct party));
WBUFW(buf,2)=4+sizeof(struct party);
+ memcpy(buf+4,p,sizeof(struct party));
+
if(fd<0)
mapif_sendall(buf,WBUFW(buf,2));
else
@@ -407,7 +455,7 @@ int mapif_party_optionchanged(int fd,struct party *p,int account_id,int flag)
//Checks whether the even-share setting of a party is broken when a character logs in. [Skotlex]
int inter_party_logged(int party_id, int account_id, int char_id)
{
- struct party *p;
+ struct party_data *p;
int i;
if (party_id <= 0)
@@ -420,17 +468,19 @@ int inter_party_logged(int party_id, int account_id, int char_id)
return 0;
for(i = 0; i < MAX_PARTY; i++)
- if (p->member[i].account_id==account_id && p->member[i].char_id==char_id) {
- p->member[i].online = 1;
+ if(p->party.member[i].account_id==account_id &&
+ 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;
}
- if(p->exp && !party_check_exp_share(p))
- {
- p->exp=0;
- mapif_party_optionchanged(0,p,0,0);
- return 1;
- }
return 0;
}
@@ -491,108 +541,100 @@ int mapif_party_message(int party_id,int account_id,char *mes,int len, int sfd)
// Create Party
-int mapif_parse_CreateParty(int fd, int account_id, int char_id, char *name, char *nick, unsigned short map, int lv, int item, int item2)
+int mapif_parse_CreateParty(int fd, char *name, int item, int item2, struct party_member *leader)
{
- struct party *p;
+ struct party_data *p;
int i;
if( (p=search_partyname(name))!=NULL){
- mapif_party_created(fd,account_id,char_id,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,account_id,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,account_id,char_id,NULL);
+ mapif_party_created(fd,leader->account_id,leader->char_id,NULL);
return 0;
}
}
- p= aCalloc(1, sizeof(struct party));
+ p= aCalloc(1, sizeof(struct party_data));
- memcpy(p->name,name,NAME_LENGTH);
- p->exp=0;
- p->item=(item?1:0)|(item2?2:0);
-
- p->member[0].account_id=account_id;
- p->member[0].char_id =char_id;
- memcpy(p->member[0].name,nick,NAME_LENGTH-1);
- p->member[0].map = map;
- p->member[0].leader=1;
- p->member[0].online=1;
- p->member[0].lv=lv;
-
- p->party_id=-1;//New party.
+ 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;
+ p->party.member[0].online=1;
+
+ p->party.party_id=-1;//New party.
if (inter_party_tosql(p,PS_CREATE|PS_ADDMEMBER,0)) {
- mapif_party_created(fd,account_id,char_id,p);
- mapif_party_info(fd,p);
+ mapif_party_created(fd,leader->account_id,leader->char_id,&p->party);
+ mapif_party_info(fd,&p->party);
} else //Failed to create party.
- mapif_party_created(fd,account_id,char_id,NULL);
+ mapif_party_created(fd,leader->account_id,leader->char_id,NULL);
return 0;
}
// パーティ情報要求
int mapif_parse_PartyInfo(int fd,int party_id)
{
- struct party *p;
+ struct party_data *p;
p = inter_party_fromsql(party_id);
if (p)
- mapif_party_info(fd,p);
+ mapif_party_info(fd,&p->party);
else
mapif_party_noinfo(fd,party_id);
return 0;
}
// パーティ追加要求
-int mapif_parse_PartyAddMember(int fd, int party_id, int account_id, int char_id, char *nick, unsigned short map, int lv) {
- struct party *p;
+int mapif_parse_PartyAddMember(int fd, int party_id, struct party_member *member) {
+ struct party_data *p;
int i;
p = inter_party_fromsql(party_id);
- if(!p){
- mapif_party_memberadded(fd,party_id,account_id,char_id,1);
+ if(!p || p->size == MAX_PARTY){
+ mapif_party_memberadded(fd,party_id,member->account_id,member->char_id,1);
return 0;
}
for(i=0;i<MAX_PARTY;i++){
- if(p->member[i].account_id==0){
- int flag=0;
-
- p->member[i].account_id=account_id;
- p->member[i].char_id=char_id;
- memcpy(p->member[i].name,nick,NAME_LENGTH);
- p->member[i].map = map;
- p->member[i].leader=0;
- p->member[i].online=1;
- p->member[i].lv=lv;
- mapif_party_memberadded(fd,party_id,account_id,char_id,0);
- mapif_party_info(-1,p);
-
- if( p->exp && !party_check_exp_share(p) ){
- p->exp=0;
- flag=0x01;
- }
- if(flag)
- mapif_party_optionchanged(fd,p,0,0);
-
- inter_party_tosql(p, PS_ADDMEMBER, i);
- return 0;
- }
+ if(p->party.member[i].account_id)
+ continue;
+
+ memcpy(&p->party.member[i], member, sizeof(struct party_member));
+ p->party.member[i].leader=0;
+ if (p->party.member[i].online) p->party.count++;
+ p->size++;
+ if (member->lv < p->min_lv || member->lv > p->max_lv || p->family)
+ {
+ if (p->family) p->family = 0; //Family state broken.
+ int_party_check_lv(p);
+ } else if (p->size == 3) //Check family state.
+ int_party_calc_state(p);
+
+ mapif_party_memberadded(fd,party_id,member->account_id,member->char_id,0);
+ mapif_party_info(-1,&p->party);
+ inter_party_tosql(p, PS_ADDMEMBER, i);
+ return 0;
}
- mapif_party_memberadded(fd,party_id,account_id,char_id,1);
+ //Party full
+ mapif_party_memberadded(fd,party_id,member->account_id,member->char_id,1);
return 0;
}
// パーティー設定変更要求
int mapif_parse_PartyChangeOption(int fd,int party_id,int account_id,int exp,int flag)
{
- struct party *p;
+ struct party_data *p;
//NOTE: No clue what that flag is about, in all observations so far it always comes as 0. [Skotlex]
flag = 0;
p = inter_party_fromsql(party_id);
@@ -600,20 +642,20 @@ int mapif_parse_PartyChangeOption(int fd,int party_id,int account_id,int exp,int
if(!p)
return 0;
- p->exp=exp;
+ p->party.exp=exp;
if( exp && !party_check_exp_share(p) ){
flag|=0x01;
- p->exp=0;
+ p->party.exp=0;
}
- mapif_party_optionchanged(fd,p,account_id,flag);
+ mapif_party_optionchanged(fd,&p->party,account_id,flag);
inter_party_tosql(p, PS_BASIC, 0);
return 0;
}
// パーティ脱退要求
int mapif_parse_PartyLeave(int fd, int party_id, int account_id, int char_id)
{
- struct party *p;
- int i;
+ struct party_data *p;
+ int i,j=-1;
p = inter_party_fromsql(party_id);
if (!p) { //Party does not exists?
@@ -626,43 +668,46 @@ int mapif_parse_PartyLeave(int fd, int party_id, int account_id, int char_id)
}
for (i = 0; i < MAX_PARTY; i++) {
- if (p->member[i].account_id == account_id && p->member[i].char_id == char_id)
+ if(p->party.member[i].account_id == account_id &&
+ p->party.member[i].char_id == char_id) {
break;
+ }
}
- if (i>= MAX_PARTY)
+ if (i >= MAX_PARTY)
return 0; //Member not found?
mapif_party_leaved(party_id, account_id, char_id);
- if (p->member[i].leader){
- int j;
+ if (p->party.member[i].leader){
+ p->party.member[i].account_id = 0;
for (j = 0; j < MAX_PARTY; j++) {
- if (p->member[j].account_id > 0 && j != i) {
- mapif_party_leaved(party_id, p->member[j].account_id, p->member[j].char_id);
- p->member[j].account_id = 0;
- }
- p->member[i].account_id = 0;
+ if (!p->party.member[j].account_id)
+ continue;
+ mapif_party_leaved(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,PS_DELMEMBER,i);
- memset(&p->member[i], 0, sizeof(struct party_member));
- //Normally unneeded except when a family is even-sharing
- //and one of the three leaves the party.
- if(p->exp && !party_check_exp_share(p) ){
- p->exp=0;
- mapif_party_optionchanged(fd,p,0,0);
+ 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)
+ {
+ 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);
+ mapif_party_info(-1,&p->party);
return 0;
}
// When member goes to other map
int mapif_parse_PartyChangeMap(int fd, int party_id, int account_id, int char_id, unsigned short map, int online, int lv)
{
- struct party *p;
+ struct party_data *p;
int i;
p = inter_party_fromsql(party_id);
@@ -670,18 +715,25 @@ int mapif_parse_PartyChangeMap(int fd, int party_id, int account_id, int char_id
return 0;
for(i = 0; i < MAX_PARTY; i++) {
- if (p->member[i].account_id == account_id && p->member[i].char_id == char_id)
+ if(p->party.member[i].account_id == account_id &&
+ p->party.member[i].char_id == char_id)
{
- p->member[i].map = map;
- p->member[i].online = online;
- if (p->member[i].lv != lv) {
- p->member[i].lv = lv;
- if (p->exp && !party_check_exp_share(p)) {
- p->exp = 0;
- mapif_party_optionchanged(fd, p, 0, 0);
- }
+ p->party.member[i].map = map;
+ if (p->party.member[i].online != online) {
+ p->party.member[i].online = online;
+ if (online) p->party.count++;
+ else p->party.count--;
+ }
+ if (p->party.member[i].lv != lv) {
+ if(p->party.member[i].lv == p->min_lv ||
+ p->party.member[i].lv == p->max_lv)
+ {
+ p->party.member[i].lv = lv;
+ int_party_check_lv(p);
+ } else
+ p->party.member[i].lv = lv;
}
- mapif_party_membermoved(p, i);
+ mapif_party_membermoved(&p->party, i);
break;
}
}
@@ -690,7 +742,7 @@ int mapif_parse_PartyChangeMap(int fd, int party_id, int account_id, int char_id
// パーティ解散要求
int mapif_parse_BreakParty(int fd,int party_id)
{
- struct party *p;
+ struct party_data *p;
p = inter_party_fromsql(party_id);
@@ -713,7 +765,7 @@ int mapif_parse_PartyCheck(int fd,int party_id,int account_id,int char_id)
int mapif_parse_PartyLeaderChange(int fd,int party_id,int account_id,int char_id)
{
- struct party *p;
+ struct party_data *p;
int i;
p = inter_party_fromsql(party_id);
@@ -723,10 +775,12 @@ int mapif_parse_PartyLeaderChange(int fd,int party_id,int account_id,int char_id
for (i = 0; i < MAX_PARTY; i++)
{
- if(p->member[i].leader)
- p->member[i].leader = 0;
- if(p->member[i].account_id == account_id && p->member[i].char_id == char_id) {
- p->member[i].leader = 1;
+ if(p->party.member[i].leader)
+ 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,PS_LEADER, i);
}
}
@@ -742,9 +796,9 @@ int inter_party_parse_frommap(int fd)
{
RFIFOHEAD(fd);
switch(RFIFOW(fd,0)) {
- case 0x3020: mapif_parse_CreateParty(fd, RFIFOL(fd,2), RFIFOL(fd,6),(char*)RFIFOP(fd,10), (char*)RFIFOP(fd,34), RFIFOW(fd,58), RFIFOW(fd,60), RFIFOB(fd,62), RFIFOB(fd,63)); break;
+ case 0x3020: mapif_parse_CreateParty(fd, (char*)RFIFOP(fd,4), RFIFOB(fd,28), RFIFOB(fd,29), (struct party_member*)RFIFOP(fd,30)); break;
case 0x3021: mapif_parse_PartyInfo(fd, RFIFOL(fd,2)); break;
- case 0x3022: mapif_parse_PartyAddMember(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), (char*)RFIFOP(fd,14), RFIFOW(fd,38), RFIFOW(fd,40)); break;
+ case 0x3022: mapif_parse_PartyAddMember(fd, RFIFOL(fd,4), (struct party_member*)RFIFOP(fd,8)); break;
case 0x3023: mapif_parse_PartyChangeOption(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOW(fd,10), RFIFOW(fd,12)); break;
case 0x3024: mapif_parse_PartyLeave(fd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)); break;
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;
@@ -765,11 +819,11 @@ int inter_party_leave(int party_id,int account_id, int char_id)
}
int inter_party_CharOnline(int char_id, int party_id) {
- struct party *p;
+ struct party_data *p;
int i;
if (party_id == -1) {
- //Get guild_id from the database
+ //Get party_id from the database
sprintf (tmp_sql , "SELECT party_id FROM `%s` WHERE char_id='%d'",char_db,char_id);
if(mysql_query(&mysql_handle, tmp_sql) ) {
ShowSQL("DB error - %s\n",mysql_error(&mysql_handle));
@@ -796,8 +850,14 @@ int inter_party_CharOnline(int char_id, int party_id) {
//Set member online
for(i=0; i<MAX_PARTY; i++) {
- if (p->member[i].char_id == char_id) {
- p->member[i].online = 1;
+ 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;
}
}
@@ -805,8 +865,8 @@ int inter_party_CharOnline(int char_id, int party_id) {
}
int inter_party_CharOffline(int char_id, int party_id) {
- struct party *p=NULL;
- int online_count=0, i;
+ struct party_data *p=NULL;
+ int i;
if (party_id == -1) {
//Get guild_id from the database
@@ -834,13 +894,18 @@ int inter_party_CharOffline(int char_id, int party_id) {
//Set member offline
for(i=0; i< MAX_PARTY; i++) {
- if(p->member[i].char_id == char_id)
- p->member[i].online = 0;
- if(p->member[i].online)
- online_count++;
+ 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(online_count == 0)
+ 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;
diff --git a/src/char_sql/inter.c b/src/char_sql/inter.c
index f2e00c671..1097cd552 100644
--- a/src/char_sql/inter.c
+++ b/src/char_sql/inter.c
@@ -73,7 +73,7 @@ int inter_send_packet_length[]={
int inter_recv_packet_length[]={
-1,-1, 7,-1, -1,13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //0x3000-0x300f
6,-1, 0, 0, 0, 0, 0, 0, 10,-1, 0, 0, 0, 0, 0, 0, //0x3010-0x301f
- 64, 6,42,14, 14,19, 6,-1, 14,14, 0, 0, 0, 0, 0, 0, //0x3020-0x302f
+ -1, 6,-1,14, 14,19, 6,-1, 14,14, 0, 0, 0, 0, 0, 0, //0x3020-0x302f
-1, 6,-1,-1, 55,19, 6,-1, 14,-1,-1,-1, 14,19,186,-1, //0x3030-0x303f
5, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
diff --git a/src/common/mmo.h b/src/common/mmo.h
index 3509692a3..4f6a92b11 100644
--- a/src/common/mmo.h
+++ b/src/common/mmo.h
@@ -244,6 +244,7 @@ struct party_member {
int account_id;
int char_id;
char name[NAME_LENGTH];
+ unsigned short class_;
unsigned short map;
unsigned short lv;
unsigned leader : 1,
@@ -253,6 +254,7 @@ struct party_member {
struct party {
int party_id;
char name[NAME_LENGTH];
+ unsigned char count; //Count of online characters.
unsigned exp : 1,
item : 2; //&1: Party-Share (round-robin), &2: pickup style: shared.
struct party_member member[MAX_PARTY];
diff --git a/src/map/intif.c b/src/map/intif.c
index 09e83b831..ef616e638 100644
--- a/src/map/intif.c
+++ b/src/map/intif.c
@@ -371,23 +371,20 @@ int intif_send_guild_storage(int account_id,struct guild_storage *gstor)
}
// パーティ作成要求
-int intif_create_party(struct map_session_data *sd,char *name,int item,int item2)
+int intif_create_party(struct party_member *member,char *name,int item,int item2)
{
if (CheckForCharServer())
return 0;
- nullpo_retr(0, sd);
+ nullpo_retr(0, member);
WFIFOHEAD(inter_fd,64);
WFIFOW(inter_fd,0) = 0x3020;
- WFIFOL(inter_fd,2) = sd->status.account_id;
- WFIFOL(inter_fd,6) = sd->status.char_id;
- memcpy(WFIFOP(inter_fd,10),name, NAME_LENGTH);
- memcpy(WFIFOP(inter_fd,34),sd->status.name,NAME_LENGTH);
- WFIFOW(inter_fd,58) = sd->mapindex;
- WFIFOW(inter_fd,60)= sd->status.base_level;
- WFIFOB(inter_fd,62)= item;
- WFIFOB(inter_fd,63)= item2;
- WFIFOSET(inter_fd,64);
+ WFIFOW(inter_fd,2) = 24+2+sizeof(struct party_member);
+ memcpy(WFIFOP(inter_fd,4),name, NAME_LENGTH);
+ WFIFOB(inter_fd,28)= item;
+ WFIFOB(inter_fd,29)= item2;
+ memcpy(WFIFOP(inter_fd,30), member, sizeof(struct party_member));
+ WFIFOSET(inter_fd,WFIFOW(inter_fd, 2));
return 0;
}
// パーティ情報要求
@@ -404,20 +401,17 @@ int intif_request_partyinfo(int party_id)
return 0;
}
// パーティ追加要求
-int intif_party_addmember(int party_id,struct map_session_data *sd)
+int intif_party_addmember(int party_id,struct party_member *member)
{
if (CheckForCharServer())
return 0;
WFIFOHEAD(inter_fd,42);
WFIFOW(inter_fd,0)=0x3022;
- WFIFOL(inter_fd,2)=party_id;
- WFIFOL(inter_fd,6)=sd->status.account_id;
- WFIFOL(inter_fd,10)=sd->status.char_id;
- memcpy(WFIFOP(inter_fd,14),sd->status.name,NAME_LENGTH);
- WFIFOW(inter_fd,38) = sd->mapindex;
- WFIFOW(inter_fd,40)=sd->status.base_level;
- WFIFOSET(inter_fd,42);
+ WFIFOW(inter_fd,2)=8+sizeof(struct party_member);
+ WFIFOL(inter_fd,4)=party_id;
+ memcpy(WFIFOP(inter_fd,8),member,sizeof(struct party_member));
+ WFIFOSET(inter_fd,WFIFOW(inter_fd, 2));
return 1;
}
// パーティ設定変更
diff --git a/src/map/intif.h b/src/map/intif.h
index 43a6c17a2..38a2cace7 100644
--- a/src/map/intif.h
+++ b/src/map/intif.h
@@ -21,9 +21,10 @@ int intif_request_guild_storage(int account_id, int guild_id);
int intif_send_guild_storage(int account_id, struct guild_storage *gstor);
-int intif_create_party(struct map_session_data *sd,char *name,int item,int item2);
+int intif_create_party(struct party_member *member,char *name,int item,int item2);
int intif_request_partyinfo(int party_id);
-int intif_party_addmember(int party_id, struct map_session_data *sd);
+
+int intif_party_addmember(int party_id,struct party_member *member);
int intif_party_changeoption(int party_id, int account_id, int exp, int item);
int intif_party_leave(int party_id,int account_id, int char_id);
int intif_party_changemap(struct map_session_data *sd, int online);
diff --git a/src/map/party.c b/src/map/party.c
index 4afb69411..24f29a603 100644
--- a/src/map/party.c
+++ b/src/map/party.c
@@ -28,6 +28,23 @@ static struct dbt* party_db;
static struct party_data* party_cache = NULL; //party in cache for skipping consecutive lookups. [Skotlex]
int party_share_level = 10;
int party_send_xy_timer(int tid,unsigned int tick,int id,int data);
+
+/*==========================================
+ * Fills the given party_member structure according to the sd provided.
+ * Used when creating/adding people to a party. [Skotlex]
+ *------------------------------------------
+ */
+static void party_fill_member(struct party_member *member, struct map_session_data *sd) {
+ member->account_id = sd->status.account_id;
+ member->char_id = sd->status.char_id;
+ memcpy(member->name,sd->status.name,NAME_LENGTH);
+ member->class_ = sd->status.class_;
+ member->map = sd->mapindex;
+ member->lv = sd->status.base_level;
+ member->online = 1;
+ member->leader = 0;
+}
+
/*==========================================
* 終了
*------------------------------------------
@@ -74,12 +91,18 @@ struct party_data* party_searchname(char *str)
int party_create(struct map_session_data *sd,char *name,int item,int item2)
{
+ struct party_member leader;
nullpo_retr(0, sd);
- if(sd->status.party_id==0)
- intif_create_party(sd,name,item,item2);
- else
+ if(sd->status.party_id) {
clif_party_created(sd,2);
+ return 0;
+ }
+
+ party_fill_member(&leader, sd);
+ leader.leader = 1;
+
+ intif_create_party(&leader,name,item,item2);
return 0;
}
@@ -176,21 +199,27 @@ static void party_check_state(struct party_data *p)
memset(&p->state, 0, sizeof(p->state));
for (i = 0; i < MAX_PARTY; i ++)
{
- if (!p->data[i].sd) continue;
- if ((p->data[i].sd->class_&MAPID_UPPERMASK) == MAPID_MONK)
+ if (!p->party.member[i].online) continue; //Those not online shouldn't aport to skill usage and all that.
+ switch (p->party.member[i].class_) {
+ case JOB_MONK:
+ case JOB_BABY_MONK:
+ case JOB_CHAMPION:
p->state.monk = 1;
- else
- if ((p->data[i].sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR)
+ break;
+ case JOB_STAR_GLADIATOR:
p->state.sg = 1;
- else
- if ((p->data[i].sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE)
+ break;
+ case JOB_SUPER_NOVICE:
+ case JOB_SUPER_BABY:
p->state.snovice = 1;
- else
- if ((p->data[i].sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON)
+ break;
+ case JOB_TAEKWON:
p->state.tk = 1;
+ break;
+ }
}
- //TODO: Family state check.
}
+
int party_recv_info(struct party *sp)
{
struct map_session_data *sd;
@@ -271,11 +300,12 @@ int party_invite(struct map_session_data *sd,struct map_session_data *tsd)
int party_reply_invite(struct map_session_data *sd,int account_id,int flag)
{
struct map_session_data *tsd= map_id2sd(account_id);
-
+ struct party_member member;
nullpo_retr(0, sd);
if(flag==1){
- intif_party_addmember( sd->party_invite, sd);
+ party_fill_member(&member, sd);
+ intif_party_addmember(sd->party_invite, &member);
return 0;
}
sd->party_invite=0;
@@ -308,7 +338,6 @@ int party_member_added(int party_id,int account_id,int char_id, int flag)
return 0;
}
- sd2=map_id2sd(sd->party_invite_account);
if(!flag) {
sd->state.party_sent=0;
sd->status.party_id=party_id;
@@ -316,6 +345,8 @@ int party_member_added(int party_id,int account_id,int char_id, int flag)
clif_party_join_info(&p->party,sd);
clif_charnameupdate(sd); //Update char name's display [Skotlex]
}
+
+ sd2=map_id2sd(sd->party_invite_account);
if (sd2)
clif_party_inviteack(sd2,sd->status.name,flag?2:0);
return 0;
@@ -387,6 +418,8 @@ int party_member_leaved(int party_id,int account_id,int char_id)
clif_party_leaved(p,sd,account_id,p->party.member[i].name,0x00);
memset(&p->party.member[i], 0, sizeof(p->party.member[0]));
memset(&p->data[i], 0, sizeof(p->data[0]));
+ p->party.count--;
+ party_check_state(p);
break;
}
}
@@ -394,7 +427,6 @@ int party_member_leaved(int party_id,int account_id,int char_id)
sd->status.party_id=0;
sd->state.party_sent=0;
clif_charnameupdate(sd); //Update name display [Skotlex]
- party_check_state(p);
}
return 0;
}
diff --git a/src/map/skill.c b/src/map/skill.c
index cfc4ccd4b..1aac9f22c 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -3546,7 +3546,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in
}
// 100% success rate at lv4 & 5, but lasts longer at lv5
i = skilllv <4?(60+skilllv*10):100;
- i = sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv));
+ i = sc_start(bl,type,i,skilllv,skill_get_time(skillid,skilllv));
if(!i) {
if (sd) clif_skill_fail(sd,skillid,0,0);
if (skill_break_equip(bl, EQP_WEAPON, 10000, BCT_PARTY) &&