summaryrefslogtreecommitdiff
path: root/src/map
diff options
context:
space:
mode:
Diffstat (limited to 'src/map')
-rw-r--r--src/map/atcommand.c2
-rw-r--r--src/map/clif.c281
-rw-r--r--src/map/clif.h1
-rw-r--r--src/map/date.c7
-rw-r--r--src/map/date.h1
-rw-r--r--src/map/guild.c26
-rw-r--r--src/map/guild.h2
-rw-r--r--src/map/npc.c11
-rw-r--r--src/map/packets_struct.h8
-rw-r--r--src/map/pc.c52
-rw-r--r--src/map/pc.h2
-rw-r--r--src/map/quest.c21
-rw-r--r--src/map/quest.h2
-rw-r--r--src/map/script.c387
-rw-r--r--src/map/script.h3
15 files changed, 592 insertions, 214 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/date.c b/src/map/date.c
index a20578e51..20ab9fe95 100644
--- a/src/map/date.c
+++ b/src/map/date.c
@@ -77,6 +77,13 @@ int date_get_sec(void)
return lt->tm_sec;
}
+int date_get_dayofweek(void)
+{
+ time_t t = time(NULL);
+ struct tm *lt = localtime(&t);
+ return lt->tm_wday;
+}
+
/*==========================================
* Star gladiator related checks
*------------------------------------------*/
diff --git a/src/map/date.h b/src/map/date.h
index 3a109d1ad..ac0a3a7fa 100644
--- a/src/map/date.h
+++ b/src/map/date.h
@@ -31,6 +31,7 @@ int date_get_day(void);
int date_get_hour(void);
int date_get_min(void);
int date_get_sec(void);
+int date_get_dayofweek(void);
bool is_day_of_sun(void);
bool is_day_of_moon(void);
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/npc.c b/src/map/npc.c
index 2876ea595..a358fd2fb 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -2119,6 +2119,17 @@ int npc_selllist_sub(struct map_session_data *sd, struct itemlist *item_list, st
script->cleararray_pc(sd, card_slot, (void*)0);
}
+ for (j = 0; j < MAX_ITEM_OPTIONS; j++) { // Clear Each item option entry
+ key_opt_idx[j] = 0;
+ key_opt_value[j] = 0;
+
+ snprintf(opt_index_str, sizeof(opt_index_str), "@slot_opt_idx%d", j + 1);
+ script->cleararray_pc(sd, opt_index_str, (void*)0);
+
+ snprintf(opt_value_str, sizeof(opt_value_str), "@slot_opt_val%d", j + 1);
+ script->cleararray_pc(sd, opt_value_str, (void*)0);
+ }
+
// save list of to be sold items
for (i = 0; i < VECTOR_LENGTH(*item_list); i++) {
struct itemlist_entry *entry = &VECTOR_INDEX(*item_list, i);
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..a925b523c 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;
@@ -5090,9 +5118,8 @@ int pc_useitem(struct map_session_data *sd,int n) {
clif->msgtable_num(sd, MSG_SECONDS_UNTIL_USE, delay_tick + 1); // [%d] seconds left until you can use
#else
char delay_msg[100];
- clif->msgtable_num(sd, MSG_SECONDS_UNTIL_USE, delay_tick + 1); // [%d] seconds left until you can use
sprintf(delay_msg, msg_sd(sd, 26), delay_tick + 1);
- clif->messagecolor_self(sd->fd, COLOR_YELLOW, delay_msg);
+ clif->messagecolor_self(sd->fd, COLOR_YELLOW, delay_msg); // [%d] seconds left until you can use
#endif
return 0; // Delay has not expired yet
}
@@ -8765,6 +8792,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 +11951,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 +12090,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 +12311,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/quest.c b/src/map/quest.c
index ed8e5bd33..4e3362adb 100644
--- a/src/map/quest.c
+++ b/src/map/quest.c
@@ -103,22 +103,23 @@ int quest_pc_login(struct map_session_data *sd)
*
* New quest will be added as Q_ACTIVE.
*
- * @param sd Player's data
- * @param quest_id ID of the quest to add.
+ * @param sd Player's data
+ * @param quest_id ID of the quest to add.
+ * @param time_limit Custom time, in UNIX epoch, for this quest
* @return 0 in case of success, nonzero otherwise
*/
-int quest_add(struct map_session_data *sd, int quest_id)
+int quest_add(struct map_session_data *sd, int quest_id, unsigned int time_limit)
{
int n;
struct quest_db *qi = quest->db(quest_id);
nullpo_retr(-1, sd);
- if( qi == &quest->dummy ) {
+ if (qi == &quest->dummy) {
ShowError("quest_add: quest %d not found in DB.\n", quest_id);
return -1;
}
- if( quest->check(sd, quest_id, HAVEQUEST) >= 0 ) {
+ if (quest->check(sd, quest_id, HAVEQUEST) >= 0) {
ShowError("quest_add: Character %d already has quest %d.\n", sd->status.char_id, quest_id);
return -1;
}
@@ -130,7 +131,7 @@ int quest_add(struct map_session_data *sd, int quest_id)
sd->avail_quests++;
RECREATE(sd->quest_log, struct quest, sd->num_quests);
- if( sd->avail_quests != sd->num_quests ) {
+ if (sd->avail_quests != sd->num_quests) {
// The character has some completed quests, make room before them so that they will stay at the end of the array
memmove(&sd->quest_log[n+1], &sd->quest_log[n], sizeof(struct quest)*(sd->num_quests-sd->avail_quests));
}
@@ -138,7 +139,9 @@ int quest_add(struct map_session_data *sd, int quest_id)
memset(&sd->quest_log[n], 0, sizeof(struct quest));
sd->quest_log[n].quest_id = qi->id;
- if( qi->time )
+ if (time_limit != 0)
+ sd->quest_log[n].time = time_limit;
+ else if (qi->time != 0)
sd->quest_log[n].time = (unsigned int)(time(NULL) + qi->time);
sd->quest_log[n].state = Q_ACTIVE;
@@ -147,8 +150,8 @@ int quest_add(struct map_session_data *sd, int quest_id)
clif->quest_add(sd, &sd->quest_log[n]);
clif->quest_update_objective(sd, &sd->quest_log[n]);
- if( map->save_settings&64 )
- chrif->save(sd,0);
+ if ((map->save_settings & 64) != 0)
+ chrif->save(sd, 0);
return 0;
}
diff --git a/src/map/quest.h b/src/map/quest.h
index 8837a1fb6..dda7c2c0a 100644
--- a/src/map/quest.h
+++ b/src/map/quest.h
@@ -69,7 +69,7 @@ struct quest_interface {
/* */
struct quest_db *(*db) (int quest_id);
int (*pc_login) (struct map_session_data *sd);
- int (*add) (struct map_session_data *sd, int quest_id);
+ int (*add) (struct map_session_data *sd, int quest_id, unsigned int time_limit);
int (*change) (struct map_session_data *sd, int qid1, int qid2);
int (*delete) (struct map_session_data *sd, int quest_id);
int (*update_objective_sub) (struct block_list *bl, va_list ap);
diff --git a/src/map/script.c b/src/map/script.c
index 4150d3adb..c23a335c3 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -30,6 +30,7 @@
#include "map/chat.h"
#include "map/chrif.h"
#include "map/clif.h"
+#include "map/date.h"
#include "map/elemental.h"
#include "map/guild.h"
#include "map/homunculus.h"
@@ -7038,6 +7039,7 @@ BUILDIN(__setr)
int64 num;
const char* name;
char prefix;
+ struct reg_db *ref;
data = script_getdata(st,2);
//datavalue = script_getdata(st,3);
@@ -7050,11 +7052,11 @@ BUILDIN(__setr)
num = reference_getuid(data);
name = reference_getname(data);
+ ref = reference_getref(data);
prefix = *name;
if (not_server_variable(prefix)) {
- sd = script->rid2sd(st);
- if (sd == NULL) {
+ if (ref == NULL && (sd = script->rid2sd(st)) == NULL) {
ShowError("script:set: no player attached for player variable '%s'\n", name);
return true;
}
@@ -7102,9 +7104,9 @@ BUILDIN(__setr)
}
if (is_string_variable(name))
- script->set_reg(st, sd, num, name, script_getstr(st, 3), script_getref(st, 2));
+ script->set_reg(st, sd, num, name, script_getstr(st, 3), ref);
else
- script->set_reg(st, sd, num, name, (const void *)h64BPTRSIZE(script_getnum(st, 3)), script_getref(st, 2));
+ script->set_reg(st, sd, num, name, (const void *)h64BPTRSIZE(script_getnum(st, 3)), ref);
return true;
}
@@ -10635,7 +10637,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 +13461,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 +13560,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;
}
@@ -14098,7 +14066,7 @@ BUILDIN(getequippedoptioninfo)
/**
* Gets the option information of an equipment.
- * *getequipoptioninfo(<equip_index>,<slot>,<type>);
+ * *getequipoption(<equip_index>,<slot>,<type>);
*
* @param equip_index as the Index of the Equipment.
* @param slot as the slot# of the Item Option (1 to MAX_ITEM_OPTIONS)
@@ -14115,24 +14083,24 @@ BUILDIN(getequipoption)
if (sd == NULL) {
script_pushint(st, -1);
- ShowError("buildin_getequipoptioninfo: Player not attached!\n");
+ ShowError("buildin_getequipoption: Player not attached!\n");
return false;
}
if (slot <= 0 || slot > MAX_ITEM_OPTIONS) {
script_pushint(st, -1);
- ShowError("buildin_getequipoptioninfo: Invalid option slot %d (Min: 1, Max: %d) provided.\n", slot, MAX_ITEM_OPTIONS);
+ ShowError("buildin_getequipoption: Invalid option slot %d (Min: 1, Max: %d) provided.\n", slot, MAX_ITEM_OPTIONS);
return false;
}
if (equip_index > 0 && equip_index <= ARRAYLENGTH(script->equip)) {
if ((i = pc->checkequip(sd, script->equip[equip_index - 1])) == -1) {
- ShowError("buildin_getequipoptioninfo: No equipment is equipped in the given index %d.\n", equip_index);
+ ShowError("buildin_getequipoption: No equipment is equipped in the given index %d.\n", equip_index);
script_pushint(st, -1);
return false;
}
} else {
- ShowError("buildin_getequipoptioninfo: Invalid equipment index %d provided.\n", equip_index);
+ ShowError("buildin_getequipoption: Invalid equipment index %d provided.\n", equip_index);
script_pushint(st, 0);
return false;
}
@@ -14146,7 +14114,7 @@ BUILDIN(getequipoption)
val = sd->status.inventory[i].option[slot-1].value;
break;
default:
- ShowError("buildin_geteqiupoptioninfo: Invalid option data type %d provided.\n", opt_type);
+ ShowError("buildin_getequipoption: Invalid option data type %d provided.\n", opt_type);
script_pushint(st, -1);
break;
}
@@ -15043,22 +15011,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
@@ -16211,6 +16219,60 @@ BUILDIN(isstr)
return true;
}
+enum datatype {
+ DATATYPE_NIL = 1 << 7, // we don't start at 1, to leave room for primitives
+ DATATYPE_STR = 1 << 8,
+ DATATYPE_INT = 1 << 9,
+ DATATYPE_CONST = 1 << 10,
+ DATATYPE_PARAM = 1 << 11,
+ DATATYPE_VAR = 1 << 12,
+ DATATYPE_LABEL = 1 << 13,
+};
+
+BUILDIN(getdatatype) {
+ int type;
+
+ if (script_hasdata(st, 2)) {
+ struct script_data *data = script_getdata(st, 2);
+
+ if (data_isstring(data)) {
+ type = DATATYPE_STR;
+ if (data->type == C_CONSTSTR) {
+ type |= DATATYPE_CONST;
+ }
+ } else if (data_isint(data)) {
+ type = DATATYPE_INT;
+ } else if (data_islabel(data)) {
+ type = DATATYPE_LABEL;
+ } else if (data_isreference(data)) {
+ if (reference_toconstant(data)) {
+ type = DATATYPE_CONST | DATATYPE_INT;
+ } else if (reference_toparam(data)) {
+ type = DATATYPE_PARAM | DATATYPE_INT;
+ } else if (reference_tovariable(data)) {
+ type = DATATYPE_VAR;
+ if (is_string_variable(reference_getname(data))) {
+ type |= DATATYPE_STR;
+ } else {
+ type |= DATATYPE_INT;
+ }
+ } else {
+ ShowError("script:getdatatype: Unknown reference type!\n");
+ script->reportdata(data);
+ st->state = END;
+ return false;
+ }
+ } else {
+ type = data->type; // fallback to primitive type if unknown
+ }
+ } else {
+ type = DATATYPE_NIL; // nothing was passed
+ }
+
+ script_pushint(st, type);
+ return true;
+}
+
//=======================================================
// chr <int>
//-------------------------------------------------------
@@ -17032,6 +17094,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 +17135,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 +17145,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 +17156,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;
@@ -20273,19 +20338,21 @@ BUILDIN(setquest)
{
unsigned short i;
int quest_id;
+ unsigned int time_limit;
struct map_session_data *sd = script->rid2sd(st);
if (sd == NULL)
return true;
quest_id = script_getnum(st, 2);
+ time_limit = script_hasdata(st, 3) ? script_getnum(st, 3) : 0;
- quest->add(sd, quest_id);
+ quest->add(sd, quest_id, time_limit);
// If questinfo is set, remove quest bubble once quest is set.
- for(i = 0; i < map->list[sd->bl.m].qi_count; i++) {
+ for (i = 0; i < map->list[sd->bl.m].qi_count; i++) {
struct questinfo *qi = &map->list[sd->bl.m].qi_data[i];
- if( qi->quest_id == quest_id ) {
+ if (qi->quest_id == quest_id) {
#if PACKETVER >= 20120410
clif->quest_show_event(sd, &qi->nd->bl, 9999, 0);
#else
@@ -23148,6 +23215,100 @@ BUILDIN(mergeitem)
return true;
}
+// getcalendartime(<day of month>, <day of week>{, <hour>{, <minute>}});
+// Returns the UNIX Timestamp of next ocurrency of given time
+BUILDIN(getcalendartime)
+{
+ struct tm info = { 0 };
+ int day_of_month = script_hasdata(st, 4) ? script_getnum(st, 4) : -1;
+ int day_of_week = script_hasdata(st, 5) ? script_getnum(st, 5) : -1;
+ int year = date_get_year();
+ int month = date_get_month();
+ int day = date_get_day();
+ int cur_hour = date_get_hour();
+ int cur_min = date_get_min();
+ int hour = script_getnum(st, 2);
+ int minute = script_getnum(st, 3);
+
+ info.tm_sec = 0;
+ info.tm_min = minute;
+ info.tm_hour = hour;
+ info.tm_mday = day;
+ info.tm_mon = month - 1;
+ info.tm_year = year - 1900;
+
+ if (day_of_month > -1 && day_of_week > -1) {
+ ShowError("script:getcalendartime: You must only specify a day_of_week or a day_of_month, not both\n");
+ script_pushint(st, -1);
+ return false;
+ }
+ if (day_of_month > -1 && (day_of_month < 1 || day_of_month > 31)) {
+ ShowError("script:getcalendartime: Day of Month in invalid range. Must be between 1 and 31.\n");
+ script_pushint(st, -1);
+ return false;
+ }
+ if (day_of_week > -1 && (day_of_week < 0 || day_of_week > 6)) {
+ ShowError("script:getcalendartime: Day of Week in invalid range. Must be between 0 and 6.\n");
+ script_pushint(st, -1);
+ return false;
+ }
+ if (hour > -1 && (hour > 23)) {
+ ShowError("script:getcalendartime: Hour in invalid range. Must be between 0 and 23.\n");
+ script_pushint(st, -1);
+ return false;
+ }
+ if (minute > -1 && (minute > 59)) {
+ ShowError("script:getcalendartime: Minute in invalid range. Must be between 0 and 59.\n");
+ script_pushint(st, -1);
+ return false;
+ }
+ if (hour == -1 || minute == -1) {
+ ShowError("script:getcalendartime: Minutes and Hours are required\n");
+ script_pushint(st, -1);
+ return false;
+ }
+
+ if (day_of_month > -1) {
+ if (day_of_month < day) { // Next Month
+ info.tm_mon++;
+ } else if (day_of_month == day) { // Today
+ if (hour < cur_hour || (hour == cur_hour && minute < cur_min)) { // But past time, next month
+ info.tm_mon++;
+ }
+ }
+
+ // Loops until month has finding a month that has day_of_month
+ do {
+ time_t t;
+ struct tm *lt;
+ info.tm_mday = day_of_month;
+ t = mktime(&info);
+ lt = localtime(&t);
+ info = *lt;
+ } while (info.tm_mday != day_of_month);
+ } else if (day_of_week > -1) {
+ int cur_wday = date_get_dayofweek();
+
+ if (day_of_week > cur_wday) { // This week
+ info.tm_mday += (day_of_week - cur_wday);
+ } else if (day_of_week == cur_wday) { // Today
+ if (hour < cur_hour || (hour == cur_hour && minute <= cur_min)) {
+ info.tm_mday += 7; // Next week
+ }
+ } else if (day_of_week < cur_wday) { // Next week
+ info.tm_mday += (7 - cur_wday + day_of_week);
+ }
+ } else if (day_of_week == -1 && day_of_month == -1) { // Next occurence of hour/min
+ if (hour < cur_hour || (hour == cur_hour && minute < cur_min)) {
+ info.tm_mday++;
+ }
+ }
+
+ script_pushint(st, mktime(&info));
+
+ return true;
+}
+
/** place holder for the translation macro **/
BUILDIN(_)
{
@@ -23643,7 +23804,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?"),
@@ -23654,6 +23815,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(charisalpha,"si"), //isalpha [Valaris]
BUILDIN_DEF(charat,"si"),
BUILDIN_DEF(isstr,"v"),
+ BUILDIN_DEF(getdatatype, "?"),
BUILDIN_DEF(chr,"i"),
BUILDIN_DEF(ord,"s"),
BUILDIN_DEF(setchar,"ssi"),
@@ -23856,7 +24018,7 @@ void script_parse_builtin(void) {
//Quest Log System [Inkfish]
BUILDIN_DEF(questinfo, "ii??"),
- BUILDIN_DEF(setquest, "i"),
+ BUILDIN_DEF(setquest, "i?"),
BUILDIN_DEF(erasequest, "i?"),
BUILDIN_DEF(completequest, "i?"),
BUILDIN_DEF(questprogress, "i?"),
@@ -23908,6 +24070,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(removechannelhandler, "ss"),
BUILDIN_DEF(showscript, "s?"),
BUILDIN_DEF(mergeitem,""),
+ BUILDIN_DEF(getcalendartime, "ii??"),
BUILDIN_DEF(_,"s"),
BUILDIN_DEF2(_, "_$", "s"),
};
@@ -24127,6 +24290,15 @@ void script_hardcoded_constants(void)
script->set_constant("PERM_DISABLE_EXP", PC_PERM_DISABLE_EXP, false, false);
script->set_constant("PERM_DISABLE_SKILL_USAGE", PC_PERM_DISABLE_SKILL_USAGE, false, false);
+ script->constdb_comment("Data types");
+ script->set_constant("DATATYPE_NIL", DATATYPE_NIL, false, false);
+ script->set_constant("DATATYPE_STR", DATATYPE_STR, false, false);
+ script->set_constant("DATATYPE_INT", DATATYPE_INT, false, false);
+ script->set_constant("DATATYPE_CONST", DATATYPE_CONST, false, false);
+ script->set_constant("DATATYPE_PARAM", DATATYPE_PARAM, false, false);
+ script->set_constant("DATATYPE_VAR", DATATYPE_VAR, false, false);
+ script->set_constant("DATATYPE_LABEL", DATATYPE_LABEL, false, false);
+
script->constdb_comment("Renewal");
#ifdef RENEWAL
script->set_constant("RENEWAL", 1, false, false);
@@ -24379,6 +24551,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);