diff options
Diffstat (limited to 'src/map')
-rw-r--r-- | src/map/atcommand.c | 2 | ||||
-rw-r--r-- | src/map/clif.c | 281 | ||||
-rw-r--r-- | src/map/clif.h | 1 | ||||
-rw-r--r-- | src/map/guild.c | 26 | ||||
-rw-r--r-- | src/map/guild.h | 2 | ||||
-rw-r--r-- | src/map/packets_struct.h | 8 | ||||
-rw-r--r-- | src/map/pc.c | 49 | ||||
-rw-r--r-- | src/map/pc.h | 2 | ||||
-rw-r--r-- | src/map/script.c | 198 | ||||
-rw-r--r-- | src/map/script.h | 3 | ||||
-rw-r--r-- | src/map/skill.c | 8 |
11 files changed, 388 insertions, 192 deletions
diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 19a7e360b..872c31330 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -5605,7 +5605,7 @@ ACMD(changegm) { return false; } - guild->gm_change(sd->status.guild_id, pl_sd); + guild->gm_change(sd->status.guild_id, pl_sd->status.char_id); return true; } diff --git a/src/map/clif.c b/src/map/clif.c index 524378439..905b6a3ce 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -2442,7 +2442,9 @@ void clif_addcards2(unsigned short *cards, struct item* item) { /// 02d4 <index>.W <amount>.W <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W <equip location>.W <item type>.B <result>.B <expire time>.L <bindOnEquipType>.W (ZC_ITEM_PICKUP_ACK3) /// 0990 <index>.W <amount>.W <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W <equip location>.L <item type>.B <result>.B <expire time>.L <bindOnEquipType>.W (ZC_ITEM_PICKUP_ACK_V5) /// 0a0c <index>.W <amount>.W <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W <equip location>.L <item type>.B <result>.B <expire time>.L <bindOnEquipType>.W (ZC_ITEM_PICKUP_ACK_V6) -void clif_additem(struct map_session_data *sd, int n, int amount, int fail) { +/// 0a37 <index>.W <amount>.W <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W <equip location>.L <item type>.B <result>.B <expire time>.L <bindOnEquipType>.W <favorite>.B <view id>.W (ZC_ITEM_PICKUP_ACK_V7) +void clif_additem(struct map_session_data *sd, int n, int amount, int fail) +{ struct packet_additem p; nullpo_retv(sd); @@ -2483,6 +2485,10 @@ void clif_additem(struct map_session_data *sd, int n, int amount, int fail) { #if PACKETVER >= 20150226 clif->add_item_options(&p.option_data[0], &sd->status.inventory[n]); #endif +#if PACKETVER >= 20160921 + p.favorite = sd->status.inventory[n].favorite; + p.look = sd->inventory_data[n]->look; +#endif } p.result = (unsigned char)fail; @@ -2978,13 +2984,6 @@ void clif_updatestatus(struct map_session_data *sd,int type) break; case SP_HP: WFIFOL(fd,4)=sd->battle_status.hp; - // TODO: Won't these overwrite the current packet? - if( map->list[sd->bl.m].hpmeter_visible ) - clif->hpmeter(sd); - if( !battle_config.party_hp_mode && sd->status.party_id ) - clif->party_hp(sd); - if( sd->bg_id ) - clif->bg_hp(sd); break; case SP_SP: WFIFOL(fd,4)=sd->battle_status.sp; @@ -3134,6 +3133,21 @@ void clif_updatestatus(struct map_session_data *sd,int type) return; } WFIFOSET(fd,len); + + // Additional update packets that should be sent right after + switch (type) { + case SP_BASELEVEL: + pc->update_job_and_level(sd); + break; + case SP_HP: + if (map->list[sd->bl.m].hpmeter_visible) + clif->hpmeter(sd); + if (!battle_config.party_hp_mode && sd->status.party_id) + clif->party_hp(sd); + if (sd->bg_id) + clif->bg_hp(sd); + break; + } } /// Notifies client of a parameter change of an another player (ZC_PAR_CHANGE_USER). @@ -6345,10 +6359,13 @@ void clif_vendinglist(struct map_session_data* sd, unsigned int id, struct s_ven const int offset = 12; #endif -#if PACKETVER >= 20150226 +#if PACKETVER < 20150226 + const int item_length = 22; +// [4144] date 20160921 not confirmend. Can be bigger or smaller +#elif PACKETVER < 20160921 const int item_length = 47; #else - const int item_length = 22; + const int item_length = 53; #endif nullpo_retv(sd); @@ -6381,6 +6398,11 @@ void clif_vendinglist(struct map_session_data* sd, unsigned int id, struct s_ven #if PACKETVER >= 20150226 clif->add_item_options(WFIFOP(fd, offset + 22 + i * item_length), &vsd->status.cart[index]); #endif +// [4144] date 20160921 not confirmend. Can be bigger or smaller +#if PACKETVER >= 20160921 + WFIFOL(fd, offset + 47 + i * item_length) = pc->item_equippoint(sd, data); + WFIFOW(fd, offset + 51 + i * item_length) = data->look; +#endif } WFIFOSET(fd,WFIFOW(fd,2)); } @@ -6511,6 +6533,7 @@ void clif_party_created(struct map_session_data *sd,int result) /// Adds new member to a party. /// 0104 <account id>.L <role>.L <x>.W <y>.W <state>.B <party name>.24B <char name>.24B <map name>.16B (ZC_ADD_MEMBER_TO_GROUP) /// 01e9 <account id>.L <role>.L <x>.W <y>.W <state>.B <party name>.24B <char name>.24B <map name>.16B <item pickup rule>.B <item share rule>.B (ZC_ADD_MEMBER_TO_GROUP2) +/// 0a43 <account id>.L <role>.L <class>.W <base level>.W <x>.W <y>.W <state>.B <party name>.24B <char name>.24B <map name>.16B <item pickup rule>.B <item share rule>.B (ZC_ADD_MEMBER_TO_GROUP3) /// role: /// 0 = leader /// 1 = normal @@ -6519,35 +6542,50 @@ void clif_party_created(struct map_session_data *sd,int result) /// 1 = disconnected void clif_party_member_info(struct party_data *p, struct map_session_data *sd) { - unsigned char buf[81]; int i; +#if PACKETVER < 20170502 + unsigned char buf[81]; + const int cmd = 0x1e9; + const int offset = 0; +#else + unsigned char buf[85]; +// [4144] probably 0xa43 packet can works on older clients because in client was added in 2015-10-07 + const int cmd = 0xa43; + int offset = 4; +#endif nullpo_retv(p); nullpo_retv(sd); if (!sd) { //Pick any party member (this call is used when changing item share rules) - ARR_FIND( 0, MAX_PARTY, i, p->data[i].sd != 0 ); + ARR_FIND(0, MAX_PARTY, i, p->data[i].sd != 0); } else { - ARR_FIND( 0, MAX_PARTY, i, p->data[i].sd == sd ); + ARR_FIND(0, MAX_PARTY, i, p->data[i].sd == sd); } - if (i >= MAX_PARTY) return; //Should never happen... + if (i >= MAX_PARTY) + return; //Should never happen... sd = p->data[i].sd; - WBUFW(buf, 0) = 0x1e9; + WBUFW(buf, 0) = cmd; WBUFL(buf, 2) = sd->status.account_id; - WBUFL(buf, 6) = (p->party.member[i].leader)?0:1; - WBUFW(buf,10) = sd->bl.x; - WBUFW(buf,12) = sd->bl.y; - WBUFB(buf,14) = (p->party.member[i].online)?0:1; - memcpy(WBUFP(buf,15), p->party.name, NAME_LENGTH); - memcpy(WBUFP(buf,39), sd->status.name, NAME_LENGTH); - mapindex->getmapname_ext(map->list[sd->bl.m].custom_name ? map->list[map->list[sd->bl.m].instance_src_map].name : map->list[sd->bl.m].name, WBUFP(buf,63)); - WBUFB(buf,79) = (p->party.item&1)?1:0; - WBUFB(buf,80) = (p->party.item&2)?1:0; - clif->send(buf,packet_len(0x1e9),&sd->bl,PARTY); + WBUFL(buf, 6) = (p->party.member[i].leader) ? 0 : 1; +#if PACKETVER >= 20170502 + WBUFW(buf, 10) = sd->status.class; + WBUFW(buf, 12) = sd->status.base_level; +#endif + WBUFW(buf, offset + 10) = sd->bl.x; + WBUFW(buf, offset + 12) = sd->bl.y; + WBUFB(buf, offset + 14) = (p->party.member[i].online) ? 0 : 1; + memcpy(WBUFP(buf, offset + 15), p->party.name, NAME_LENGTH); + memcpy(WBUFP(buf, offset + 39), sd->status.name, NAME_LENGTH); + mapindex->getmapname_ext(map->list[sd->bl.m].custom_name ? map->list[map->list[sd->bl.m].instance_src_map].name : map->list[sd->bl.m].name, WBUFP(buf, offset + 63)); + WBUFB(buf, offset + 79) = (p->party.item & 1) ? 1 : 0; + WBUFB(buf, offset + 80) = (p->party.item & 2) ? 1 : 0; + clif->send(buf, packet_len(cmd), &sd->bl, PARTY); } /// Sends party information (ZC_GROUP_LIST). /// 00fb <packet len>.W <party name>.24B { <account id>.L <nick>.24B <map name>.16B <role>.B <state>.B }* +/// 0a44 <packet len>.W <party name>.24B { <account id>.L <nick>.24B <map name>.16B <role>.B <state>.B <class>.W <base level>.W }* <item pickup rule>.B <item share rule>.B <unknown>.L /// role: /// 0 = leader /// 1 = normal @@ -6556,37 +6594,78 @@ void clif_party_member_info(struct party_data *p, struct map_session_data *sd) /// 1 = disconnected void clif_party_info(struct party_data* p, struct map_session_data *sd) { - unsigned char buf[2+2+NAME_LENGTH+(4+NAME_LENGTH+MAP_NAME_LENGTH_EXT+1+1)*MAX_PARTY]; struct map_session_data* party_sd = NULL; int i, c; +#if PACKETVER < 20170502 + const int cmd = 0xfb; + const int size = 46; + unsigned char buf[2 + 2 + NAME_LENGTH + 46 * MAX_PARTY]; +#else +// [4144] probably 0xa44 packet can works on older clients because in client was added in 2015-10-07 + const int cmd = 0xa44; + const int size = 50; + unsigned char buf[2 + 2 + NAME_LENGTH + 50 * MAX_PARTY + 6]; +#endif nullpo_retv(p); - WBUFW(buf,0) = 0xfb; - memcpy(WBUFP(buf,4), p->party.name, NAME_LENGTH); + WBUFW(buf, 0) = cmd; + memcpy(WBUFP(buf, 4), p->party.name, NAME_LENGTH); for(i = 0, c = 0; i < MAX_PARTY; i++) { - struct party_member* m = &p->party.member[i]; - if(!m->account_id) continue; + struct party_member *m = &p->party.member[i]; + if (!m->account_id) + continue; - if(party_sd == NULL) party_sd = p->data[i].sd; + if (party_sd == NULL) + party_sd = p->data[i].sd; - WBUFL(buf,28+c*46) = m->account_id; - memcpy(WBUFP(buf,28+c*46+4), m->name, NAME_LENGTH); - mapindex->getmapname_ext(mapindex_id2name(m->map), WBUFP(buf,28+c*46+28)); - WBUFB(buf,28+c*46+44) = (m->leader) ? 0 : 1; - WBUFB(buf,28+c*46+45) = (m->online) ? 0 : 1; + WBUFL(buf, 28 + c * size) = m->account_id; + memcpy(WBUFP(buf, 28 + c * size + 4), m->name, NAME_LENGTH); + mapindex->getmapname_ext(mapindex_id2name(m->map), WBUFP(buf, 28 + c * size + 28)); + WBUFB(buf, 28 + c * size + 44) = (m->leader) ? 0 : 1; + WBUFB(buf, 28 + c * size + 45) = (m->online) ? 0 : 1; +#if PACKETVER >= 20170502 + WBUFW(buf, 28 + c * size + 46) = m->class; + WBUFW(buf, 28 + c * size + 48) = m->lv; +#endif c++; } - WBUFW(buf,2) = 28+c*46; +#if PACKETVER < 20170502 + WBUFW(buf, 2) = 28 + c * size; +#else + WBUFB(buf, 28 + c * size) = (p->party.item & 1) ? 1 : 0; + WBUFB(buf, 28 + c * size + 1) = (p->party.item & 2) ? 1 : 0; + WBUFL(buf, 28 + c * size + 2) = 0; // unknown + WBUFW(buf, 2) = 28 + c * size + 6; +#endif - if(sd) { // send only to self - clif->send(buf, WBUFW(buf,2), &sd->bl, SELF); + if (sd) { // send only to self + clif->send(buf, WBUFW(buf, 2), &sd->bl, SELF); } else if (party_sd) { // send to whole party - clif->send(buf, WBUFW(buf,2), &party_sd->bl, PARTY); + clif->send(buf, WBUFW(buf, 2), &party_sd->bl, PARTY); } } +/// Updates the job and level of a party member +/// 0abd <account id>.L <job>.W <level>.W +void clif_party_job_and_level(struct map_session_data *sd) +{ +// [4144] packet 0xabd added in client in 2017-02-15 because this probably it can works for clients older than 20170502 +#if PACKETVER >= 20170502 + unsigned char buf[10]; + + nullpo_retv(sd); + + WBUFW(buf, 0) = 0xabd; + WBUFL(buf, 2) = sd->status.account_id; + WBUFW(buf, 6) = sd->status.class; + WBUFW(buf, 8) = sd->status.base_level; + + clif_send(buf, packet_len(0xabd), &sd->bl, PARTY); +#endif +} + /// The player's 'party invite' state, sent during login (ZC_PARTY_CONFIG). /// 02c9 <flag>.B /// flag: @@ -7433,36 +7512,48 @@ void clif_guild_masterormember(struct map_session_data *sd) /// Guild basic information (Territories [Valaris]) /// 0150 <guild id>.L <level>.L <member num>.L <member max>.L <exp>.L <max exp>.L <points>.L <honor>.L <virtue>.L <emblem id>.L <name>.24B <master name>.24B <manage land>.16B (ZC_GUILD_INFO) /// 01b6 <guild id>.L <level>.L <member num>.L <member max>.L <exp>.L <max exp>.L <points>.L <honor>.L <virtue>.L <emblem id>.L <name>.24B <master name>.24B <manage land>.16B <zeny>.L (ZC_GUILD_INFO2) -void clif_guild_basicinfo(struct map_session_data *sd) { +void clif_guild_basicinfo(struct map_session_data *sd) +{ int fd; struct guild *g; +#if PACKETVER < 20160622 + const int cmd = 0x1b6; //0x150; [4144] this is packet for older versions? +#else + const int cmd = 0xa84; +#endif + nullpo_retv(sd); fd = sd->fd; - if( (g = sd->guild) == NULL ) + if ((g = sd->guild) == NULL) return; - WFIFOHEAD(fd,packet_len(0x1b6)); - WFIFOW(fd, 0)=0x1b6;//0x150; - WFIFOL(fd, 2)=g->guild_id; - WFIFOL(fd, 6)=g->guild_lv; - WFIFOL(fd,10)=g->connect_member; - WFIFOL(fd,14)=g->max_member; - WFIFOL(fd,18)=g->average_lv; - WFIFOL(fd,22)=(uint32)cap_value(g->exp,0,INT32_MAX); - WFIFOL(fd,26)=g->next_exp; - WFIFOL(fd,30)=0; // Tax Points - WFIFOL(fd,34)=0; // Honor: (left) Vulgar [-100,100] Famed (right) - WFIFOL(fd,38)=0; // Virtue: (down) Wicked [-100,100] Righteous (up) - WFIFOL(fd,42)=g->emblem_id; - memcpy(WFIFOP(fd,46),g->name, NAME_LENGTH); - memcpy(WFIFOP(fd,70),g->master, NAME_LENGTH); - - safestrncpy(WFIFOP(fd,94),msg_sd(sd,300+guild->checkcastles(g)),16); // "'N' castles" - WFIFOL(fd,110) = 0; // zeny + WFIFOHEAD(fd, packet_len(cmd)); + WFIFOW(fd, 0) = cmd; + WFIFOL(fd, 2) = g->guild_id; + WFIFOL(fd, 6) = g->guild_lv; + WFIFOL(fd, 10) = g->connect_member; + WFIFOL(fd, 14) = g->max_member; + WFIFOL(fd, 18) = g->average_lv; + WFIFOL(fd, 22) = (uint32)cap_value(g->exp, 0, INT32_MAX); + WFIFOL(fd, 26) = g->next_exp; + WFIFOL(fd, 30) = 0; // Tax Points + WFIFOL(fd, 34) = 0; // Honor: (left) Vulgar [-100,100] Famed (right) + WFIFOL(fd, 38) = 0; // Virtue: (down) Wicked [-100,100] Righteous (up) + WFIFOL(fd, 42) = g->emblem_id; + memcpy(WFIFOP(fd, 46), g->name, NAME_LENGTH); +#if PACKETVER < 20160622 + memcpy(WFIFOP(fd, 70), g->master, NAME_LENGTH); + safestrncpy(WFIFOP(fd, 94), msg_sd(sd, 300 + guild->checkcastles(g)), 16); // "'N' castles" + WFIFOL(fd, 110) = 0; // zeny +#else + safestrncpy(WFIFOP(fd, 70), msg_sd(sd, 300 + guild->checkcastles(g)), 16); // "'N' castles" + WFIFOL(fd, 86) = 0; // zeny + WFIFOL(fd, 90) = g->member[0].char_id; // leader +#endif - WFIFOSET(fd,packet_len(0x1b6)); + WFIFOSET(fd, packet_len(cmd)); } /// Guild alliance and opposition list (ZC_MYGUILD_BASIC_INFO). @@ -7504,35 +7595,47 @@ void clif_guild_memberlist(struct map_session_data *sd) int fd; int i,c; struct guild *g; +#if PACKETVER < 20161026 + const int cmd = 0x154; + const int size = 104; +#else + const int cmd = 0xaa5; + const int size = 34; +#endif + nullpo_retv(sd); - if( (fd = sd->fd) == 0 ) + if ((fd = sd->fd) == 0) return; - if( (g = sd->guild) == NULL ) + if ((g = sd->guild) == NULL) return; - WFIFOHEAD(fd, g->max_member * 104 + 4); - WFIFOW(fd, 0)=0x154; - for(i=0,c=0;i<g->max_member;i++){ - struct guild_member *m=&g->member[i]; - if(m->account_id==0) + WFIFOHEAD(fd, g->max_member * size + 4); + WFIFOW(fd, 0) = cmd; + for (i = 0, c = 0; i < g->max_member; i++) { + struct guild_member *m = &g->member[i]; + if (m->account_id == 0) continue; - WFIFOL(fd,c*104+ 4)=m->account_id; - WFIFOL(fd,c*104+ 8)=m->char_id; - WFIFOW(fd,c*104+12)=m->hair; - WFIFOW(fd,c*104+14)=m->hair_color; - WFIFOW(fd,c*104+16)=m->gender; - WFIFOW(fd,c*104+18)=m->class; - WFIFOW(fd,c*104+20)=m->lv; - WFIFOL(fd,c*104+22)=(int)cap_value(m->exp,0,INT32_MAX); - WFIFOL(fd,c*104+26)=m->online; - WFIFOL(fd,c*104+30)=m->position; - memset(WFIFOP(fd,c*104+34),0,50); //[Ind] - This is displayed in the 'note' column but being you can't edit it it's sent empty. - memcpy(WFIFOP(fd,c*104+84),m->name,NAME_LENGTH); + WFIFOL(fd, c * size + 4) = m->account_id; + WFIFOL(fd, c * size + 8) = m->char_id; + WFIFOW(fd, c * size + 12) = m->hair; + WFIFOW(fd, c * size + 14) = m->hair_color; + WFIFOW(fd, c * size + 16) = m->gender; + WFIFOW(fd, c * size + 18) = m->class; + WFIFOW(fd, c * size + 20) = m->lv; + WFIFOL(fd, c * size + 22) = (int)cap_value(m->exp, 0, INT32_MAX); + WFIFOL(fd, c * size + 26) = m->online; + WFIFOL(fd, c * size + 30) = m->position; +#if PACKETVER < 20161026 + memset(WFIFOP(fd, c * size + 34), 0, 50); //[Ind] - This is displayed in the 'note' column but being you can't edit it it's sent empty. + memcpy(WFIFOP(fd, c * size + 84), m->name, NAME_LENGTH); +#else + WFIFOL(fd, c * size + 34) = 0; // [4144] this is member last login time. But in hercules it not present. +#endif c++; } - WFIFOW(fd, 2)=c*104+4; - WFIFOSET(fd,WFIFOW(fd,2)); + WFIFOW(fd, 2) = c * size + 4; + WFIFOSET(fd, WFIFOW(fd, 2)); } /// Guild position name information (ZC_POSITION_ID_NAME_INFO). @@ -12953,13 +13056,22 @@ void clif_parse_GuildChangeMemberPosition(int fd, struct map_session_data *sd) _ void clif_parse_GuildChangeMemberPosition(int fd, struct map_session_data *sd) { int i; + int len = RFIFOW(fd, 2); if(!sd->state.gmaster_flag) return; + // Guild leadership change + if (len == 16 && RFIFOL(fd, 12) == 0) { + guild->gm_change(sd->status.guild_id, RFIFOL(fd, 8)); + return; + } + for(i=4;i<RFIFOW(fd,2);i+=12){ - guild->change_memberposition(sd->status.guild_id, - RFIFOL(fd,i),RFIFOL(fd,i+4),RFIFOL(fd,i+8)); + int position = RFIFOL(fd, i + 8); + if (position > 0) { + guild->change_memberposition(sd->status.guild_id, RFIFOL(fd, i), RFIFOL(fd, i + 4), position); + } } } @@ -19702,6 +19814,7 @@ void clif_defaults(void) { clif->party_created = clif_party_created; clif->party_member_info = clif_party_member_info; clif->party_info = clif_party_info; + clif->party_job_and_level = clif_party_job_and_level; clif->party_invite = clif_party_invite; clif->party_inviteack = clif_party_inviteack; clif->party_option = clif_party_option; diff --git a/src/map/clif.h b/src/map/clif.h index ccb227267..b34be81a3 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -917,6 +917,7 @@ struct clif_interface { void (*party_created) (struct map_session_data *sd,int result); void (*party_member_info) (struct party_data *p, struct map_session_data *sd); void (*party_info) (struct party_data* p, struct map_session_data *sd); + void (*party_job_and_level) (struct map_session_data *sd); void (*party_invite) (struct map_session_data *sd,struct map_session_data *tsd); void (*party_inviteack) (struct map_session_data* sd, const char* nick, int result); void (*party_option) (struct party_data *p,struct map_session_data *sd,int flag); diff --git a/src/map/guild.c b/src/map/guild.c index 6e5b1c539..838df3943 100644 --- a/src/map/guild.c +++ b/src/map/guild.c @@ -1814,23 +1814,28 @@ int guild_broken(int guild_id,int flag) } //Changes the Guild Master to the specified player. [Skotlex] -int guild_gm_change(int guild_id, struct map_session_data *sd) +int guild_gm_change(int guild_id, int char_id) { - struct guild *g; - nullpo_ret(sd); + struct guild *g = guild->search(guild_id); + char *name; + int i; - if (sd->status.guild_id != guild_id) - return 0; + nullpo_ret(g); - g=guild->search(guild_id); + ARR_FIND(0, MAX_GUILD, i, g->member[i].char_id == char_id); + + if (i == MAX_GUILD ) { + // Not part of the guild + return 0; + } - nullpo_ret(g); + name = g->member[i].name; - if (strcmp(g->master, sd->status.name) == 0) //Nothing to change. + if (strcmp(g->master, name) == 0) //Nothing to change. return 0; //Notify servers that master has changed. - intif->guild_change_gm(guild_id, sd->status.name, (int)strlen(sd->status.name)+1); + intif->guild_change_gm(guild_id, name, (int)strlen(name) + 1); return 1; } @@ -1864,6 +1869,7 @@ int guild_gm_changed(int guild_id, int account_id, int char_id) if (g->member[pos].sd && g->member[pos].sd->fd) { clif->message(g->member[pos].sd->fd, msg_sd(g->member[pos].sd,878)); //"You no longer are the Guild Master." g->member[pos].sd->state.gmaster_flag = 0; + clif->charnameack(0, &g->member[pos].sd->bl); } if (g->member[0].sd && g->member[0].sd->fd) { @@ -1871,6 +1877,7 @@ int guild_gm_changed(int guild_id, int account_id, int char_id) g->member[0].sd->state.gmaster_flag = 1; //Block his skills for 5 minutes to prevent abuse. guild->block_skill(g->member[0].sd, 300000); + clif->charnameack(0, &g->member[pos].sd->bl); } // announce the change to all guild members @@ -1880,6 +1887,7 @@ int guild_gm_changed(int guild_id, int account_id, int char_id) { clif->guild_basicinfo(g->member[i].sd); clif->guild_memberlist(g->member[i].sd); + clif->guild_belonginfo(g->member[i].sd, g); // Update clientside guildmaster flag } } diff --git a/src/map/guild.h b/src/map/guild.h index cdb28a37b..71e989870 100644 --- a/src/map/guild.h +++ b/src/map/guild.h @@ -141,7 +141,7 @@ struct guild_interface { int (*skillupack) (int guild_id,uint16 skill_id,int account_id); int (*dobreak) (struct map_session_data *sd, const char *name); int (*broken) (int guild_id,int flag); - int (*gm_change) (int guild_id, struct map_session_data *sd); + int (*gm_change) (int guild_id, int char_id); int (*gm_changed) (int guild_id, int account_id, int char_id); /* */ void (*castle_map_init) (void); diff --git a/src/map/packets_struct.h b/src/map/packets_struct.h index 0bd85db7f..796ea577c 100644 --- a/src/map/packets_struct.h +++ b/src/map/packets_struct.h @@ -76,8 +76,10 @@ enum packet_headers { additemType = 0x2d4, #elif PACKETVER < 20150226 additemType = 0x990, -#else +#elif PACKETVER < 20160921 additemType = 0xa0c, +#else + additemType = 0xa37, #endif #if PACKETVER < 4 idle_unitType = 0x78, @@ -448,6 +450,10 @@ struct packet_additem { #if PACKETVER >= 20150226 struct ItemOptions option_data[MAX_ITEM_OPTIONS]; #endif +#if PACKETVER >= 20160921 + uint8 favorite; + uint16 look; +#endif } __attribute__((packed)); struct packet_dropflooritem { diff --git a/src/map/pc.c b/src/map/pc.c index 2303a83ca..aedb029b6 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -750,6 +750,7 @@ int pc_setnewpc(struct map_session_data *sd, int account_id, int char_id, int lo return 0; } +// [4144] probably pc_equippoint should be replaced to pc_item_equippoint int pc_equippoint(struct map_session_data *sd,int n) { int ep = 0; @@ -782,6 +783,33 @@ int pc_equippoint(struct map_session_data *sd,int n) return ep; } +int pc_item_equippoint(struct map_session_data *sd, struct item_data* id) +{ + int ep = 0; + + nullpo_ret(sd); + nullpo_ret(id); + + if (!itemdb->isequip2(id)) + return 0; //Not equippable by players. + + ep = id->equip; + if (id->look == W_DAGGER || + id->look == W_1HSWORD || + id->look == W_1HAXE) { + if (pc->checkskill(sd, AS_LEFT) > 0 || + (sd->job & MAPID_UPPERMASK) == MAPID_ASSASSIN || + (sd->job & MAPID_UPPERMASK) == MAPID_KAGEROUOBORO) { + // Kagerou and Oboro can dual wield daggers. [Rytech] + if (ep == EQP_HAND_R) + return EQP_ARMS; + if (ep == EQP_SHADOW_WEAPON) + return EQP_SHADOW_ARMS; + } + } + return ep; +} + int pc_setinventorydata(struct map_session_data *sd) { int i; @@ -8765,6 +8793,7 @@ int pc_jobchange(struct map_session_data *sd, int class, int upper) status_calc_pc(sd,SCO_FORCE); pc->checkallowskill(sd); pc->equiplookall(sd); + pc->update_job_and_level(sd); //if you were previously famous, not anymore. if (fame_flag != 0) { @@ -11923,6 +11952,24 @@ void pc_check_supernovice_call(struct map_session_data *sd, const char *message) } } +void pc_update_job_and_level(struct map_session_data *sd) +{ + nullpo_retv(sd); + + if (sd->status.party_id) { + struct party_data *p; + int i; + + if ((p = party->search(sd->status.party_id)) != NULL) { + ARR_FIND(0, MAX_PARTY, i, p->party.member[i].char_id == sd->status.char_id); + if (i < MAX_PARTY) { + p->party.member[i].lv = sd->status.base_level; + clif->party_job_and_level(sd); + } + } + } +} + void do_final_pc(void) { db_destroy(pc->itemcd_db); pc->at_db->destroy(pc->at_db,pc->autotrade_final); @@ -12044,6 +12091,7 @@ void pc_defaults(void) { pc->isequip = pc_isequip; pc->equippoint = pc_equippoint; + pc->item_equippoint = pc_item_equippoint; pc->setinventorydata = pc_setinventorydata; pc->checkskill = pc_checkskill; @@ -12264,6 +12312,7 @@ void pc_defaults(void) { pc->checkcombo = pc_checkcombo; pc->calcweapontype = pc_calcweapontype; pc->removecombo = pc_removecombo; + pc->update_job_and_level = pc_update_job_and_level; pc->bank_withdraw = pc_bank_withdraw; pc->bank_deposit = pc_bank_deposit; diff --git a/src/map/pc.h b/src/map/pc.h index af52f8946..04fd98b24 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -859,6 +859,7 @@ END_ZEROED_BLOCK; /* End */ int (*isequip) (struct map_session_data *sd,int n); int (*equippoint) (struct map_session_data *sd,int n); + int (*item_equippoint) (struct map_session_data *sd, struct item_data* id); int (*setinventorydata) (struct map_session_data *sd); int (*checkskill) (struct map_session_data *sd,uint16 skill_id); @@ -1095,6 +1096,7 @@ END_ZEROED_BLOCK; /* End */ bool (*db_checkid) (int class); void (*validate_levels) (void); + void (*update_job_and_level) (struct map_session_data *sd); /** * Autotrade persistency [Ind/Hercules <3] diff --git a/src/map/script.c b/src/map/script.c index b22c88cfe..dbeae5fbc 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -10635,7 +10635,7 @@ BUILDIN(guildchangegm) if (sd == NULL) script_pushint(st,0); else - script_pushint(st,guild->gm_change(guild_id, sd)); + script_pushint(st, guild->gm_change(guild_id, sd->status.char_id)); return true; } @@ -13459,113 +13459,98 @@ BUILDIN(getequipcardcnt) /// Removes all cards from the item found in the specified equipment slot of the invoking character, /// and give them to the character. If any cards were removed in this manner, it will also show a success effect. -/// successremovecards <slot>; +/// successremovecards(<slot>); BUILDIN(successremovecards) { - int i=-1,c,cardflag=0; + int i = -1, c, cardflag = 0; struct map_session_data *sd = script->rid2sd(st); - int num = script_getnum(st,2); + int num = script_getnum(st, 2); if (sd == NULL) return true; if (num > 0 && num <= ARRAYLENGTH(script->equip)) - i=pc->checkequip(sd,script->equip[num-1]); + i = pc->checkequip(sd,script->equip[num - 1]); - if (i < 0 || !sd->inventory_data[i]) { + if (i < 0 || sd->inventory_data[i] == NULL) return true; - } - if(itemdb_isspecial(sd->status.inventory[i].card[0])) + if (itemdb_isspecial(sd->status.inventory[i].card[0])) return true; - for( c = sd->inventory_data[i]->slot - 1; c >= 0; --c ) { - if( sd->status.inventory[i].card[c] && itemdb_type(sd->status.inventory[i].card[c]) == IT_CARD ) {// extract this card from the item + for (c = sd->inventory_data[i]->slot - 1; c >= 0; --c) { + if (sd->status.inventory[i].card[c] > 0 && itemdb_type(sd->status.inventory[i].card[c]) == IT_CARD) { int flag; struct item item_tmp; - memset(&item_tmp,0,sizeof(item_tmp)); + + memset(&item_tmp, 0, sizeof(item_tmp)); + cardflag = 1; - item_tmp.nameid = sd->status.inventory[i].card[c]; + item_tmp.nameid = sd->status.inventory[i].card[c]; item_tmp.identify = 1; + sd->status.inventory[i].card[c] = 0; - if((flag=pc->additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))) { - // get back the cart in inventory - clif->additem(sd,0,0,flag); + if ((flag = pc->additem(sd, &item_tmp, 1, LOG_TYPE_SCRIPT))) { + clif->additem(sd, 0, 0, flag); map->addflooritem(&sd->bl, &item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0); } } } if (cardflag == 1) { - //if card was remove replace item with no card - int flag, j; - struct item item_tmp; - memset(&item_tmp,0,sizeof(item_tmp)); - - item_tmp.nameid = sd->status.inventory[i].nameid; - item_tmp.identify = 1; - item_tmp.refine = sd->status.inventory[i].refine; - item_tmp.attribute = sd->status.inventory[i].attribute; - item_tmp.expire_time = sd->status.inventory[i].expire_time; - item_tmp.bound = sd->status.inventory[i].bound; - - for (j = sd->inventory_data[i]->slot; j < MAX_SLOTS; j++) - item_tmp.card[j]=sd->status.inventory[i].card[j]; - - pc->delitem(sd, i, 1, 0, DELITEM_MATERIALCHANGE, LOG_TYPE_SCRIPT); - if ((flag=pc->additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))) { - //chk if can be spawn in inventory otherwise put on floor - clif->additem(sd,0,0,flag); - map->addflooritem(&sd->bl, &item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0); - } - + pc->unequipitem(sd, i, PCUNEQUIPITEM_FORCE); + clif->delitem(sd, i, 1, DELITEM_MATERIALCHANGE); + clif->additem(sd, i, 1, 0); + pc->equipitem(sd, i, sd->status.inventory[i].equip); clif->misceffect(&sd->bl,3); } return true; } /// Removes all cards from the item found in the specified equipment slot of the invoking character. -/// failedremovecards <slot>, <type>; +/// failedremovecards(<slot>, <type>); /// <type>=0 : will destroy both the item and the cards. /// <type>=1 : will keep the item, but destroy the cards. /// <type>=2 : will keep the cards, but destroy the item. -/// <type>=? : will just display the failure effect. +/// <type>=3 : will just display the failure effect. BUILDIN(failedremovecards) { - int i=-1,c,cardflag=0; + int i = -1, c, cardflag = 0; + int num = script_getnum(st, 2); + int typefail = script_getnum(st, 3); struct map_session_data *sd = script->rid2sd(st); - int num = script_getnum(st,2); - int typefail = script_getnum(st,3); if (sd == NULL) return true; if (num > 0 && num <= ARRAYLENGTH(script->equip)) - i=pc->checkequip(sd,script->equip[num-1]); + i = pc->checkequip(sd, script->equip[num - 1]); - if (i < 0 || !sd->inventory_data[i]) + if (i < 0 || sd->inventory_data[i] == NULL) return true; - if(itemdb_isspecial(sd->status.inventory[i].card[0])) + if (itemdb_isspecial(sd->status.inventory[i].card[0])) return true; - for( c = sd->inventory_data[i]->slot - 1; c >= 0; --c ) { - if( sd->status.inventory[i].card[c] && itemdb_type(sd->status.inventory[i].card[c]) == IT_CARD ) { + for (c = sd->inventory_data[i]->slot - 1; c >= 0; --c) { + if (sd->status.inventory[i].card[c] > 0 && itemdb_type(sd->status.inventory[i].card[c]) == IT_CARD) { cardflag = 1; - if(typefail == 2) {// add cards to inventory, clear + sd->status.inventory[i].card[c] = 0; + + if (typefail == 2) { // add cards to inventory, clear int flag; struct item item_tmp; - memset(&item_tmp,0,sizeof(item_tmp)); + memset(&item_tmp, 0, sizeof(item_tmp)); - item_tmp.nameid = sd->status.inventory[i].card[c]; + item_tmp.nameid = sd->status.inventory[i].card[c]; item_tmp.identify = 1; - if((flag=pc->additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))) { - clif->additem(sd,0,0,flag); + if ((flag = pc->additem(sd, &item_tmp, 1, LOG_TYPE_SCRIPT))) { + clif->additem(sd, 0, 0, flag); map->addflooritem(&sd->bl, &item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0); } } @@ -13573,35 +13558,16 @@ BUILDIN(failedremovecards) } if (cardflag == 1) { - if (typefail == 0 || typefail == 2) { - // destroy the item + if (typefail == 0 || typefail == 2) { // destroy the item pc->delitem(sd, i, 1, 0, DELITEM_FAILREFINE, LOG_TYPE_SCRIPT); } else if (typefail == 1) { - // destroy the card - int flag, j; - struct item item_tmp; - - memset(&item_tmp,0,sizeof(item_tmp)); - - item_tmp.nameid = sd->status.inventory[i].nameid; - item_tmp.identify = 1; - item_tmp.refine = sd->status.inventory[i].refine; - item_tmp.attribute = sd->status.inventory[i].attribute; - item_tmp.expire_time = sd->status.inventory[i].expire_time; - item_tmp.bound = sd->status.inventory[i].bound; - - for (j = sd->inventory_data[i]->slot; j < MAX_SLOTS; j++) - item_tmp.card[j]=sd->status.inventory[i].card[j]; - - pc->delitem(sd, i, 1, 0, DELITEM_FAILREFINE, LOG_TYPE_SCRIPT); - - if((flag=pc->additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))) { - clif->additem(sd,0,0,flag); - map->addflooritem(&sd->bl, &item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0); - } + pc->unequipitem(sd, i, PCUNEQUIPITEM_FORCE); + clif->delitem(sd, i, 1, DELITEM_MATERIALCHANGE); + clif->additem(sd, i, 1, 0); + pc->equipitem(sd, i, sd->status.inventory[i].equip); } - clif->misceffect(&sd->bl,2); } + clif->misceffect(&sd->bl, 2); return true; } @@ -15043,22 +15009,62 @@ BUILDIN(dispbottom) * All The Players Full Recovery * (HP/SP full restore and resurrect if need) *------------------------------------------*/ +int buildin_recovery_sub(struct map_session_data *sd) +{ + nullpo_retr(0, sd); + + if (pc_isdead(sd)) { + status->revive(&sd->bl, 100, 100); + } else { + status_percent_heal(&sd->bl, 100, 100); + } + + return 0; +} + +int buildin_recovery_pc_sub(struct map_session_data *sd, va_list ap) +{ + return script->buildin_recovery_sub(sd); +} + +int buildin_recovery_bl_sub(struct block_list *bl, va_list ap) +{ + return script->buildin_recovery_sub(BL_CAST(BL_PC, bl)); +} + BUILDIN(recovery) { - struct map_session_data *sd; - struct s_mapiterator* iter; + if (script_hasdata(st, 2)) { + if (script_isstringtype(st, 2)) { + int16 m = map->mapname2mapid(script_getstr(st, 2)); - iter = mapit_getallusers(); - for (sd = BL_UCAST(BL_PC, mapit->first(iter)); mapit->exists(iter); sd = BL_UCAST(BL_PC, mapit->next(iter))) { - if(pc_isdead(sd)) - status->revive(&sd->bl, 100, 100); - else - status_percent_heal(&sd->bl, 100, 100); - clif->message(sd->fd,msg_sd(sd,880)); // "You have been recovered!" + if (m == -1) { + ShowWarning("script:recovery: invalid map!\n"); + return false; + } + + if (script_hasdata(st, 6)) { + int16 x1 = script_getnum(st, 3); + int16 y1 = script_getnum(st, 4); + int16 x2 = script_getnum(st, 5); + int16 y2 = script_getnum(st, 6); + map->foreachinarea(script->buildin_recovery_bl_sub, m, x1, y1, x2, y2, BL_PC); + } else { + map->foreachinmap(script->buildin_recovery_bl_sub, m, BL_PC); + } + } else { + struct map_session_data *sd = script->id2sd(st, script_getnum(st, 2)); + + if (sd != NULL) { + script->buildin_recovery_sub(sd); + } + } + } else { + map->foreachpc(script->buildin_recovery_pc_sub); } - mapit->free(iter); return true; } + /*========================================== * Get your pet info: getpetinfo(n) * n -> 0:pet_id 1:pet_class 2:pet_name @@ -17032,6 +17038,7 @@ BUILDIN(swap) { struct map_session_data *sd = NULL; struct script_data *data1, *data2; + struct reg_db *ref1, *ref2; const char *varname1, *varname2; int64 uid1, uid2; @@ -17072,6 +17079,8 @@ BUILDIN(swap) uid1 = reference_getuid(data1); uid2 = reference_getuid(data2); + ref1 = reference_getref(data1); + ref2 = reference_getref(data2); if (is_string_variable(varname1)) { const char *value1, *value2; @@ -17080,8 +17089,8 @@ BUILDIN(swap) value2 = script_getstr(st,3); if (strcmpi(value1, value2)) { - script->set_reg(st, sd, uid1, varname1, value2, script_getref(st,3)); - script->set_reg(st, sd, uid2, varname2, value1, script_getref(st,2)); + script->set_reg(st, sd, uid1, varname1, value2, ref1); + script->set_reg(st, sd, uid2, varname2, value1, ref2); } } else { @@ -17091,8 +17100,8 @@ BUILDIN(swap) value2 = script_getnum(st,3); if (value1 != value2) { - script->set_reg(st, sd, uid1, varname1, (const void *)h64BPTRSIZE(value2), script_getref(st,3)); - script->set_reg(st, sd, uid2, varname2, (const void *)h64BPTRSIZE(value1), script_getref(st,2)); + script->set_reg(st, sd, uid1, varname1, (const void *)h64BPTRSIZE(value2), ref1); + script->set_reg(st, sd, uid2, varname2, (const void *)h64BPTRSIZE(value1), ref2); } } return true; @@ -21690,6 +21699,8 @@ BUILDIN(unbindatcmd) ARR_FIND(0, atcommand->binding_count, i, strcmp(atcommand->binding[i]->command, atcmd) == 0); if( i < atcommand->binding_count ) { int cursor = 0; + aFree(atcommand->binding[i]->at_groups); + aFree(atcommand->binding[i]->char_groups); aFree(atcommand->binding[i]); atcommand->binding[i] = NULL; /* compact the list now that we freed a slot somewhere */ @@ -23639,7 +23650,7 @@ void script_parse_builtin(void) { BUILDIN_DEF(pcre_match,"ss"), BUILDIN_DEF(dispbottom,"s?"), //added from jA [Lupus] BUILDIN_DEF(getusersname,""), - BUILDIN_DEF(recovery,""), + BUILDIN_DEF(recovery,"?????"), BUILDIN_DEF(getpetinfo,"i"), BUILDIN_DEF(gethominfo,"i"), BUILDIN_DEF(getmercinfo,"i?"), @@ -24375,6 +24386,9 @@ void script_defaults(void) script->db_free_code_sub = db_script_free_code_sub; script->add_autobonus = script_add_autobonus; script->menu_countoptions = menu_countoptions; + script->buildin_recovery_sub = buildin_recovery_sub; + script->buildin_recovery_pc_sub = buildin_recovery_pc_sub; + script->buildin_recovery_bl_sub = buildin_recovery_bl_sub; script->buildin_areawarp_sub = buildin_areawarp_sub; script->buildin_areapercentheal_sub = buildin_areapercentheal_sub; script->buildin_delitem_delete = buildin_delitem_delete; diff --git a/src/map/script.h b/src/map/script.h index fddcf4908..189122230 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -854,6 +854,9 @@ struct script_interface { int (*db_free_code_sub) (union DBKey key, struct DBData *data, va_list ap); void (*add_autobonus) (const char *autobonus); int (*menu_countoptions) (const char *str, int max_count, int *total); + int (*buildin_recovery_sub) (struct map_session_data *sd); + int (*buildin_recovery_pc_sub) (struct map_session_data *sd, va_list ap); + int (*buildin_recovery_bl_sub) (struct block_list *bl, va_list ap); int (*buildin_areawarp_sub) (struct block_list *bl, va_list ap); int (*buildin_areapercentheal_sub) (struct block_list *bl, va_list ap); void (*buildin_delitem_delete) (struct map_session_data *sd, int idx, int *amount, bool delete_items); diff --git a/src/map/skill.c b/src/map/skill.c index b70ddc055..e187b7e8b 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -2555,7 +2555,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,skill_lv,BDT_MULTIHIT); break; case WL_CHAINLIGHTNING_ATK: - dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,WL_CHAINLIGHTNING,-2,BDT_SKILL); + dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,WL_CHAINLIGHTNING_ATK,-2,BDT_SKILL); break; case LG_OVERBRAND_BRANDISH: case LG_OVERBRAND: @@ -12156,7 +12156,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 struct skill_unit_group *sg; struct block_list *ss; struct map_session_data *tsd; - struct status_data *tstatus, *bst; + struct status_data *tstatus; struct status_change *tsc, *ssc; struct skill_unit_group_tickset *ts; enum sc_type type; @@ -12181,8 +12181,6 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 tstatus = status->get_status_data(bl); nullpo_ret(tstatus); - bst = status->get_base_status(bl); - nullpo_ret(bst); type = status->skill2sc(sg->skill_id); skill_id = sg->skill_id; @@ -12858,6 +12856,8 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 if (tsc && (tsc->data[SC_HALLUCINATIONWALK] || tsc->data[SC_VACUUM_EXTREME])) { return 0; } else { + struct status_data *bst = status->get_base_status(bl); + nullpo_ret(bst); sg->limit -= 1000 * bst->str/20; sc_start(ss, bl, SC_VACUUM_EXTREME, 100, sg->skill_lv, sg->limit); |