- Modified the party_data structure on the map server to remove some redundant data. Added a party_data structure on the char-server to hold a more complete set of information about parties. Added to the party_member structure the class of each member so that the map server can do the appropiate checks even if the character is on another mapserver/offline. Due to the format changes in the party structure, txt servers will have to wipe their party file... (sql save format has not been changed)

- Added function char_family to check if there's a family state given the three character ids, instead of doing individual checks all the time.


git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@7553 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
skotlex 2006-07-06 23:39:24 +00:00
parent a4d0df735d
commit b7fa70b741
15 changed files with 612 additions and 377 deletions

View File

@ -4,6 +4,16 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
2006/07/06
* Modified the party_data structure on the map server to remove some
redundant data. Added a party_data structure on the char-server to hold a
more complete set of information about parties. Added to the party_member
structure the class of each member so that the map server can do the
appropiate checks even if the character is on another mapserver/offline.
Due to the format changes in the party structure, txt servers will have to
wipe their party file... (sql save format has not been changed) [Skotlex]
* Added function char_family to check if there's a family state given the
three character ids, instead of doing individual checks all the time.
[Skotlex]
* Rewrote all the item restriction functions so that they will take into
account slotted card restrictions as well. [Skotlex]
* Added no_skill_delay setting, when set, affected object types will have

View File

@ -905,7 +905,7 @@
//-- NJ_HYOUSENSOU
537,700:1400:2100:2800:3500:4200:4900:5600:6300:7000,0,0,0,0
//-- NJ_SUITON
538,3300:3200:3100:3000:2900:2800:2700:2600:2500:2400:2300,0,0,15000:20000:25000:30000:35000:40000:45000:50000:55000:60000,0
538,3300:3200:3100:3000:2900:2800:2700:2600:2500:2400,0,0,15000:20000:25000:30000:35000:40000:45000:50000:55000:60000,0
//-- NJ_HYOUSYOURAKU
539,0,0,0,0,10000
//-- NJ_HUUJIN

View File

@ -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);

View File

@ -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, ...);

View File

@ -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->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);
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);
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--;
}
mapif_party_membermoved(p, 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)
{
p->party.member[i].lv = lv;
int_party_check_lv(p);
} else
p->party.member[i].lv = lv;
}
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;

View File

@ -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,

View File

@ -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;
}

View File

@ -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);

View File

@ -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);
memcpy(p->party.name,name,NAME_LENGTH);
p->party.exp=0;
p->party.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;
memcpy(&p->party.member[0], leader, sizeof(struct party_member));
p->party.member[0].leader=1;
p->party.member[0].online=1;
p->party_id=-1;//New party.
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;
if(p->party.member[i].account_id)
continue;
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);
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);
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;
}
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--;
}
mapif_party_membermoved(p, 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)
{
p->party.member[i].lv = lv;
int_party_check_lv(p);
} else
p->party.member[i].lv = lv;
}
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;

View File

@ -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,

View File

@ -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];

View File

@ -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;
}
// パーティ設定変更

View File

@ -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);

View File

@ -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;
}
/*==========================================
* <EFBFBD>I¹
*------------------------------------------
@ -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;
}

View File

@ -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) &&