- 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:
parent
a4d0df735d
commit
b7fa70b741
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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, ...);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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];
|
||||
|
@ -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;
|
||||
}
|
||||
// パーティ設定変更
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) &&
|
||||
|
Loading…
x
Reference in New Issue
Block a user