summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/char_sql/char.c3
-rw-r--r--src/common/socket.c7
-rw-r--r--src/common/timer.c2
-rw-r--r--src/common/utils.c2
-rw-r--r--src/map/atcommand.c55
-rw-r--r--src/map/battle.c4
-rw-r--r--src/map/battleground.c4
-rw-r--r--src/map/buyingstore.c2
-rw-r--r--src/map/chat.c38
-rw-r--r--src/map/chat.h5
-rw-r--r--src/map/clif.c185
-rw-r--r--src/map/clif.h2
-rw-r--r--src/map/guild.c4
-rw-r--r--src/map/mail.c2
-rw-r--r--src/map/map.c3
-rw-r--r--src/map/mob.c4
-rw-r--r--src/map/npc.c12
-rw-r--r--src/map/party.c4
-rw-r--r--src/map/pc.c60
-rw-r--r--src/map/pc.h8
-rw-r--r--src/map/pet.c7
-rw-r--r--src/map/script.c85
-rw-r--r--src/map/searchstore.c2
-rw-r--r--src/map/skill.c1
-rw-r--r--src/map/status.c3
-rw-r--r--src/map/trade.c4
-rw-r--r--src/map/unit.c5
-rw-r--r--src/map/vending.c23
28 files changed, 313 insertions, 223 deletions
diff --git a/src/char_sql/char.c b/src/char_sql/char.c
index e135fee78..36de40bf5 100644
--- a/src/char_sql/char.c
+++ b/src/char_sql/char.c
@@ -473,7 +473,8 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p)
(p->party_id != cp->party_id) || (p->guild_id != cp->guild_id) ||
(p->pet_id != cp->pet_id) || (p->weapon != cp->weapon) || (p->hom_id != cp->hom_id) ||
(p->shield != cp->shield) || (p->head_top != cp->head_top) ||
- (p->head_mid != cp->head_mid) || (p->head_bottom != cp->head_bottom) || (p->delete_date != cp->delete_date)
+ (p->head_mid != cp->head_mid) || (p->head_bottom != cp->head_bottom) || (p->delete_date != cp->delete_date) ||
+ (p->rename != cp->rename)
)
{ //Save status
if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `base_level`='%d', `job_level`='%d',"
diff --git a/src/common/socket.c b/src/common/socket.c
index 0a576e517..262351dcf 100644
--- a/src/common/socket.c
+++ b/src/common/socket.c
@@ -749,7 +749,7 @@ int do_sockets(int next)
if(session[i]->wdata_size)
session[i]->func_send(i);
- if(session[i]->eof) //func_send can't free a session, this is safe.
+ if(session[i]->flag.eof) //func_send can't free a session, this is safe.
{ //Finally, even if there is no data to parse, connections signalled eof should be closed, so we call parse_func [Skotlex]
session[i]->func_parse(i); //This should close the session immediately.
}
@@ -1351,9 +1351,6 @@ void send_shortlist_do_sends()
{
int i = 0;
- // Assume all or most of the fd's don't remain in the shortlist
- memset(send_shortlist_set, 0, sizeof(send_shortlist_set));
-
while( i < send_shortlist_count )
{
int fd = send_shortlist_array[i];
@@ -1375,7 +1372,6 @@ void send_shortlist_do_sends()
// be sent from it we'll keep it in the shortlist.
if( session[fd] && !session[fd]->flag.eof && session[fd]->wdata_size )
{
- send_shortlist_set[fd/32] |= 1<<(fd%32);
++i;
continue;
}
@@ -1383,6 +1379,7 @@ void send_shortlist_do_sends()
// Remove fd from shortlist, move the last fd to the current position
send_shortlist_array[i] = send_shortlist_array[--send_shortlist_count];
+ send_shortlist_set[fd/32]&=~(1<<(fd%32));
}
}
#endif
diff --git a/src/common/timer.c b/src/common/timer.c
index 190e41eaf..86e148ee3 100644
--- a/src/common/timer.c
+++ b/src/common/timer.c
@@ -146,7 +146,7 @@ static unsigned int tick(void)
//
return (unsigned int)((_rdtsc() - RDTSC_BEGINTICK) / RDTSC_CLOCK);
//
-#elif (defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0 && defined(_POSIX_MONOTONIC_CLOCK) /* posix compliant */) || (defined(__FreeBSD_cc_version) && __FreeBSD_cc_version >= 500005 /* FreeBSD >= 5.1.0 */)
+#elif defined(HAVE_MONOTONIC_CLOCK)
struct timespec tval;
clock_gettime(CLOCK_MONOTONIC, &tval);
return tval.tv_sec * 1000 + tval.tv_nsec / 1000000;
diff --git a/src/common/utils.c b/src/common/utils.c
index f1813ea41..1602afa52 100644
--- a/src/common/utils.c
+++ b/src/common/utils.c
@@ -269,7 +269,7 @@ unsigned int get_percentage(const unsigned int A, const unsigned int B)
if( B == 0 )
{
ShowError("get_percentage(): divison by zero! (A=%u,B=%u)\n", A, B);
- return -1;
+ return ~0U;
}
result = 100 * ((double)A / (double)B);
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index 0d1c8f9d9..3eb0c37ac 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -1150,7 +1150,7 @@ ACMD_FUNC(storage)
{
nullpo_retr(-1, sd);
- if (sd->npc_id || sd->vender_id || sd->state.buyingstore || sd->state.trading || sd->state.storage_flag)
+ if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.trading || sd->state.storage_flag)
return -1;
if (storage_storageopen(sd) == 1)
@@ -1177,7 +1177,7 @@ ACMD_FUNC(guildstorage)
return -1;
}
- if (sd->npc_id || sd->vender_id || sd->state.buyingstore || sd->state.trading)
+ if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.trading)
return -1;
if (sd->state.storage_flag == 1) {
@@ -2462,7 +2462,7 @@ ACMD_FUNC(monster)
if (number <= 0)
number = 1;
- if (strlen(name) < 1)
+ if( !name[0] )
strcpy(name, "--ja--");
// If value of atcommand_spawn_quantity_limit directive is greater than or equal to 1 and quantity of monsters is greater than value of the directive
@@ -2543,7 +2543,7 @@ ACMD_FUNC(monstersmall)
if (number <= 0)
number = 1;
- if (strlen(name) < 1)
+ if( !name[0] )
strcpy(name, "--ja--");
// If value of atcommand_spawn_quantity_limit directive is greater than or equal to 1 and quantity of monsters is greater than value of the directive
@@ -2619,7 +2619,7 @@ ACMD_FUNC(monsterbig)
if (number <= 0)
number = 1;
- if (strlen(name) < 1)
+ if( !name[0] )
strcpy(name, "--ja--");
// If value of atcommand_spawn_quantity_limit directive is greater than or equal to 1 and quantity of monsters is greater than value of the directive
@@ -6030,7 +6030,7 @@ ACMD_FUNC(autotrade)
return -1;
}
- if( !sd->vender_id && !sd->state.buyingstore ) { //check if player is vending or buying
+ if( !sd->state.vending && !sd->state.buyingstore ) { //check if player is vending or buying
clif_displaymessage(fd, msg_txt(549)); // "You should have a shop open to use @autotrade."
return -1;
}
@@ -6068,7 +6068,7 @@ ACMD_FUNC(changegm)
return -1;
}
- if (strlen(message)==0)
+ if( !message[0] )
{
clif_displaymessage(fd, "Command usage: @changegm <guildmember name>");
return -1;
@@ -6091,7 +6091,7 @@ ACMD_FUNC(changeleader)
{
nullpo_retr(-1, sd);
- if (strlen(message)==0)
+ if( !message[0] )
{
clif_displaymessage(fd, "Command usage: @changeleader <party member name>");
return -1;
@@ -7829,31 +7829,32 @@ ACMD_FUNC(monsterignore)
*------------------------------------------*/
ACMD_FUNC(fakename)
{
- char name[NAME_LENGTH];
nullpo_retr(-1, sd);
-
- if((!message || !*message) && strlen(sd->fakename) > 1) {
- sd->fakename[0]='\0';
- clif_charnameack(0, &sd->bl);
- clif_displaymessage(sd->fd,"Returned to real name.");
- return 0;
- }
- if (!message || !*message || sscanf(message, "%23[^\n]", name) < 1) {
- clif_displaymessage(sd->fd,"You must enter a name.");
+ if( !message || !*message )
+ {
+ if( sd->fakename[0] )
+ {
+ sd->fakename[0] = '\0';
+ clif_charnameack(0, &sd->bl);
+ clif_displaymessage(sd->fd, "Returned to real name.");
+ return 0;
+ }
+
+ clif_displaymessage(sd->fd, "You must enter a name.");
return -1;
}
- if(strlen(name) < 2) {
- clif_displaymessage(sd->fd,"Fake name must be at least two characters.");
+ if( strlen(message) < 2 )
+ {
+ clif_displaymessage(sd->fd, "Fake name must be at least two characters.");
return -1;
}
- memcpy(sd->fakename,name,NAME_LENGTH);
- sd->fakename[NAME_LENGTH-1] = '\0';
+ safestrncpy(sd->fakename, message, sizeof(sd->fakename));
clif_charnameack(0, &sd->bl);
- clif_displaymessage(sd->fd,"Fake name enabled.");
-
+ clif_displaymessage(sd->fd, "Fake name enabled.");
+
return 0;
}
@@ -7987,7 +7988,7 @@ ACMD_FUNC(duel)
return 0;
}
- if(strlen(message) > 0) {
+ if( message[0] ) {
if(sscanf(message, "%d", &maxpl) >= 1) {
if(maxpl < 2 || maxpl > 65535) {
clif_displaymessage(fd, msg_txt(357)); // "Duel: Invalid value."
@@ -8163,7 +8164,7 @@ ACMD_FUNC(clone)
*-----------------------------------*/
ACMD_FUNC(main)
{
- if(strlen(message) > 0) {
+ if( message[0] ) {
if(strcmpi(message, "on") == 0) {
if(!sd->state.mainchat) {
@@ -9249,7 +9250,7 @@ ACMD_FUNC(commands)
if( gm_lvl < atcommand_info[i].level2 && stristr(command,"charcommands") )
continue;
- slen = (unsigned int)strlen(atcommand_info[i].command);
+ slen = strlen(atcommand_info[i].command);
// flush the text buffer if this command won't fit into it
if( slen + cur - line_buff >= CHATBOX_SIZE )
diff --git a/src/map/battle.c b/src/map/battle.c
index f60be479a..40e59039b 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -1442,8 +1442,8 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo
case MC_MAMMONITE:
skillratio += 50*skill_lv;
break;
- case HT_POWER: //FIXME: How exactly is the STR based damage supposed to be done? [Skotlex]
- skillratio += 5*sstatus->str;
+ case HT_POWER:
+ skillratio += -50+8*sstatus->str;
break;
case AC_DOUBLE:
case MA_DOUBLE:
diff --git a/src/map/battleground.c b/src/map/battleground.c
index 1c2a90d90..58e3b469c 100644
--- a/src/map/battleground.c
+++ b/src/map/battleground.c
@@ -130,7 +130,7 @@ int bg_team_leave(struct map_session_data *sd, int flag)
sprintf(output, "Server : %s has quit the game...", sd->status.name);
else
sprintf(output, "Server : %s is leaving the battlefield...", sd->status.name);
- clif_bg_message(bg, "Server", output, strlen(output) + 1);
+ clif_bg_message(bg, 0, "Server", output, strlen(output) + 1);
if( bg->logout_event[0] && flag )
npc_event(sd, bg->logout_event, 0);
@@ -212,7 +212,7 @@ int bg_send_message(struct map_session_data *sd, const char *mes, int len)
nullpo_ret(sd);
if( sd->state.bg_id == 0 || (bg = bg_team_search(sd->state.bg_id)) == NULL )
return 0;
- clif_bg_message(bg, sd->status.name, mes, len);
+ clif_bg_message(bg, sd->bl.id, sd->status.name, mes, len);
return 0;
}
diff --git a/src/map/buyingstore.c b/src/map/buyingstore.c
index 8f158cd29..5b9734819 100644
--- a/src/map/buyingstore.c
+++ b/src/map/buyingstore.c
@@ -46,7 +46,7 @@ static unsigned int buyingstore_getuid(void)
bool buyingstore_setup(struct map_session_data* sd, unsigned char slots)
{
- if( !battle_config.feature_buying_store || sd->vender_id || sd->state.buyingstore || sd->state.trading || slots == 0 )
+ if( !battle_config.feature_buying_store || sd->state.vending || sd->state.buyingstore || sd->state.trading || slots == 0 )
{
return false;
}
diff --git a/src/map/chat.c b/src/map/chat.c
index 4ba784b2e..933674db8 100644
--- a/src/map/chat.c
+++ b/src/map/chat.c
@@ -23,7 +23,7 @@ int chat_triggerevent(struct chat_data *cd); // forward declaration
/// Initializes a chatroom object (common functionality for both pc and npc chatrooms).
/// Returns a chatroom object on success, or NULL on failure.
-static struct chat_data* chat_createchat(struct block_list* bl, const char* title, const char* pass, int limit, bool pub, int trigger, const char* ev)
+static struct chat_data* chat_createchat(struct block_list* bl, const char* title, const char* pass, int limit, bool pub, int trigger, const char* ev, int zeny, int minLvl, int maxLvl)
{
struct chat_data* cd;
nullpo_retr(NULL, bl);
@@ -36,6 +36,9 @@ static struct chat_data* chat_createchat(struct block_list* bl, const char* titl
cd->users = 0;
cd->limit = min(limit, ARRAYLENGTH(cd->usersd));
cd->trigger = trigger;
+ cd->zeny = zeny;
+ cd->minLvl = minLvl;
+ cd->maxLvl = maxLvl;
memset(cd->usersd, 0, sizeof(cd->usersd));
cd->owner = bl;
safestrncpy(cd->npc_event, ev, sizeof(cd->npc_event));
@@ -69,7 +72,7 @@ int chat_createpcchat(struct map_session_data* sd, const char* title, const char
if( sd->chatID )
return 0; //Prevent people abusing the chat system by creating multiple chats, as pointed out by End of Exam. [Skotlex]
- if( sd->vender_id || sd->state.buyingstore )
+ if( sd->state.vending || sd->state.buyingstore )
{// not chat, when you already have a store open
return 0;
}
@@ -88,7 +91,7 @@ int chat_createpcchat(struct map_session_data* sd, const char* title, const char
pc_stop_walking(sd,1);
- cd = chat_createchat(&sd->bl, title, pass, limit, pub, 0, "");
+ cd = chat_createchat(&sd->bl, title, pass, limit, pub, 0, "", 0, 1, MAX_LEVEL);
if( cd )
{
cd->users = 1;
@@ -113,7 +116,7 @@ int chat_joinchat(struct map_session_data* sd, int chatid, const char* pass)
nullpo_ret(sd);
cd = (struct chat_data*)map_id2bl(chatid);
- if( cd == NULL || cd->bl.type != BL_CHAT || cd->bl.m != sd->bl.m || sd->vender_id || sd->state.buyingstore || sd->chatID || cd->users >= cd->limit )
+ if( cd == NULL || cd->bl.type != BL_CHAT || cd->bl.m != sd->bl.m || sd->state.vending || sd->state.buyingstore || sd->chatID || cd->users >= cd->limit )
{
clif_joinchatfail(sd,0);
return 0;
@@ -125,6 +128,22 @@ int chat_joinchat(struct map_session_data* sd, int chatid, const char* pass)
return 0;
}
+ if( sd->status.base_level < cd->minLvl || sd->status.base_level > cd->maxLvl )
+ {
+ if(sd->status.base_level < cd->minLvl)
+ clif_joinchatfail(sd,5);
+ else
+ clif_joinchatfail(sd,6);
+
+ return 0;
+ }
+
+ if( sd->status.zeny < cd->zeny )
+ {
+ clif_joinchatfail(sd,4);
+ return 0;
+ }
+
pc_stop_walking(sd,1);
cd->usersd[cd->users] = sd;
cd->users++;
@@ -299,7 +318,7 @@ int chat_kickchat(struct map_session_data* sd, const char* kickusername)
}
/// Creates a chat room for the npc.
-int chat_createnpcchat(struct npc_data* nd, const char* title, int limit, bool pub, int trigger, const char* ev)
+int chat_createnpcchat(struct npc_data* nd, const char* title, int limit, bool pub, int trigger, const char* ev, int zeny, int minLvl, int maxLvl)
{
struct chat_data* cd;
nullpo_ret(nd);
@@ -310,7 +329,14 @@ int chat_createnpcchat(struct npc_data* nd, const char* title, int limit, bool p
return 0;
}
- cd = chat_createchat(&nd->bl, title, "", limit, pub, trigger, ev);
+ if( zeny > MAX_ZENY || maxLvl > MAX_LEVEL )
+ {
+ ShowError("chat_createnpcchat: npc '%s' has a required lvl or amount of zeny over the max limit!\n", nd->exname);
+ return 0;
+ }
+
+ cd = chat_createchat(&nd->bl, title, "", limit, pub, trigger, ev, zeny, minLvl, maxLvl);
+
if( cd )
{
nd->chat_id = cd->bl.id;
diff --git a/src/map/chat.h b/src/map/chat.h
index 569e6cbe8..be3efb513 100644
--- a/src/map/chat.h
+++ b/src/map/chat.h
@@ -17,6 +17,9 @@ struct chat_data {
uint8 users; // current user count
uint8 limit; // join limit
uint8 trigger; // number of users needed to trigger event
+ uint32 zeny; // required zeny to join
+ uint32 minLvl; // minimum base level to join
+ uint32 maxLvl; // maximum base level allowed to join
struct map_session_data* usersd[20];
struct block_list* owner;
char npc_event[50];
@@ -30,7 +33,7 @@ int chat_changechatowner(struct map_session_data* sd, const char* nextownername)
int chat_changechatstatus(struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub);
int chat_kickchat(struct map_session_data* sd, const char* kickusername);
-int chat_createnpcchat(struct npc_data* nd, const char* title, int limit, bool pub, int trigger, const char* ev);
+int chat_createnpcchat(struct npc_data* nd, const char* title, int limit, bool pub, int trigger, const char* ev, int zeny, int minLvl, int maxLvl);
int chat_deletenpcchat(struct npc_data* nd);
int chat_enableevent(struct chat_data* cd);
int chat_disableevent(struct chat_data* cd);
diff --git a/src/map/clif.c b/src/map/clif.c
index 960a63c0e..e4105c170 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -3297,8 +3297,8 @@ int clif_addchat(struct chat_data* cd,struct map_session_data *sd)
}
/*==========================================
- * Announce the new owner
- * R 00e1 <owner flag>.l <nick>.24B
+ * Announce the new owner (ZC_ROLE_CHANGE)
+ * R 00e1 <role>.L <nick>.24B
*------------------------------------------*/
void clif_changechatowner(struct chat_data* cd, struct map_session_data* sd)
{
@@ -3307,18 +3307,12 @@ void clif_changechatowner(struct chat_data* cd, struct map_session_data* sd)
nullpo_retv(sd);
nullpo_retv(cd);
- //FIXME: this announces a swap between positions 0 and 1 (probably not what we want) [ultramage]
- //FIXME: aegis sends obviously incorrect packets; need to figure out what to send to display it correctly :X
- //TODO: is it just owner swap, or can it do general-purpose reordering?
- // It's not position, but operator flag, everyone set to 1 gets chat
- // operator menu (yes, that means a chat may host multiple operators) [Ai4rei]
-
WBUFW(buf, 0) = 0xe1;
- WBUFL(buf, 2) = 1;
+ WBUFL(buf, 2) = 1; // normal
memcpy(WBUFP(buf,6),cd->usersd[0]->status.name,NAME_LENGTH);
WBUFW(buf,30) = 0xe1;
- WBUFL(buf,32) = 0;
+ WBUFL(buf,32) = 0; // owner (menu)
memcpy(WBUFP(buf,36),sd->status.name,NAME_LENGTH);
clif_send(buf,packet_len(0xe1)*2,&sd->bl,CHAT);
@@ -3645,7 +3639,7 @@ static void clif_getareachar_pc(struct map_session_data* sd,struct map_session_d
clif_dispchat(cd,sd->fd);
}
- if(dstsd->vender_id)
+ if( dstsd->state.vending )
clif_showvendingboard(&dstsd->bl,dstsd->message,sd->fd);
if( dstsd->state.buyingstore )
@@ -4077,7 +4071,7 @@ int clif_outsight(struct block_list *bl,va_list ap)
if(cd->usersd[0]==sd)
clif_dispchat(cd,tsd->fd);
}
- if(sd->vender_id)
+ if( sd->state.vending )
clif_closevendingboard(bl,tsd->fd);
if( sd->state.buyingstore )
clif_buyingstore_disappear_entry_single(tsd, sd);
@@ -7624,7 +7618,9 @@ int clif_refresh(struct map_session_data *sd)
return 0;
}
-// updates the object's (bl) name on client
+/// Updates the object's (bl) name on client (ZC_ACK_REQNAME/ZC_ACK_REQNAMEALL)
+/// 0095 <unit id>.L <char name>.24B
+/// 0195 <unit id>.L <char name>.24B <party name>.24B <guild name>.24B <position name>.24B
int clif_charnameack (int fd, struct block_list *bl)
{
unsigned char buf[103];
@@ -7647,24 +7643,31 @@ int clif_charnameack (int fd, struct block_list *bl)
if (ssd->fd == fd && ssd->disguise)
WBUFL(buf,2) = -bl->id;
- if (strlen(ssd->fakename)>1) {
+ if( ssd->fakename[0] )
+ {
+ WBUFW(buf, 0) = cmd = 0x195;
memcpy(WBUFP(buf,6), ssd->fakename, NAME_LENGTH);
+ WBUFB(buf,30) = WBUFB(buf,54) = WBUFB(buf,78) = 0;
break;
}
memcpy(WBUFP(buf,6), ssd->status.name, NAME_LENGTH);
-
- if (!battle_config.display_party_name) {
- if (ssd->status.party_id > 0 && ssd->status.guild_id > 0 && (g = guild_search(ssd->status.guild_id)) != NULL)
- p = party_search(ssd->status.party_id);
- }else{
- if (ssd->status.party_id > 0)
- p = party_search(ssd->status.party_id);
- }
- if( ssd->status.guild_id > 0 && (g = guild_search(ssd->status.guild_id)) != NULL )
+ if( ssd->status.party_id )
+ {
+ p = party_search(ssd->status.party_id);
+ }
+ if( ssd->status.guild_id )
{
- ARR_FIND(0, g->max_member, i, g->member[i].account_id == ssd->status.account_id && g->member[i].char_id == ssd->status.char_id);
- if( i < g->max_member ) ps = g->member[i].position;
+ if( ( g = guild_search(ssd->status.guild_id) ) != NULL )
+ {
+ ARR_FIND(0, g->max_member, i, g->member[i].account_id == ssd->status.account_id && g->member[i].char_id == ssd->status.char_id);
+ if( i < g->max_member ) ps = g->member[i].position;
+ }
+ }
+
+ if( !battle_config.display_party_name && g == NULL )
+ {// do not display party unless the player is also in a guild
+ p = NULL;
}
if (p == NULL && g == NULL)
@@ -7766,7 +7769,7 @@ int clif_charnameupdate (struct map_session_data *ssd)
nullpo_ret(ssd);
- if (strlen(ssd->fakename)>1)
+ if( ssd->fakename[0] )
return 0; //No need to update as the party/guild was not displayed anyway.
WBUFW(buf,0) = cmd;
@@ -9606,11 +9609,14 @@ void clif_parse_ChatRoomStatusChange(int fd, struct map_session_data* sd)
}
/*==========================================
- * S 00e0 ?.l <nick>.24B
+ * CZ_REQ_ROLE_CHANGE
+ * S 00e0 <role>.L <nick>.24B
+ * role:
+ * 0 = owner (ROOMROLE_OWNER)
+ * 1 = normal (ROOMROLE_GENERAL)
*------------------------------------------*/
void clif_parse_ChangeChatOwner(int fd, struct map_session_data* sd)
{
- //TODO: the first argument seems to be the destination position (always 0) [ultramage]
chat_changechatowner(sd,(char*)RFIFOP(fd,6));
}
@@ -10265,6 +10271,7 @@ void clif_parse_ItemIdentify(int fd,struct map_session_data *sd)
return;
if( idx == -1 )
{// cancel pressed
+ sd->menuskill_val = sd->menuskill_id = 0;
return;
}
skill_identify(sd,idx-2);
@@ -10418,7 +10425,7 @@ void clif_parse_MoveFromKafra(int fd,struct map_session_data *sd)
*------------------------------------------*/
void clif_parse_MoveToKafraFromCart(int fd, struct map_session_data *sd)
{
- if(sd->vender_id)
+ if( sd->state.vending )
return;
if (!pc_iscarton(sd))
return;
@@ -10435,7 +10442,7 @@ void clif_parse_MoveToKafraFromCart(int fd, struct map_session_data *sd)
*------------------------------------------*/
void clif_parse_MoveFromKafraToCart(int fd, struct map_session_data *sd)
{
- if (sd->vender_id)
+ if( sd->state.vending )
return;
if (!pc_iscarton(sd))
return;
@@ -12846,24 +12853,29 @@ void clif_parse_Mail_send(int fd, struct map_session_data *sd)
* AUCTION SYSTEM
* By Zephyrus
*==========================================*/
+
+
+/// Opens/closes the auction window (ZC_AUCTION_WINDOWS)
+/// 025f <type>.L
+/// type:
+/// 0 = open
+/// 1 = close
void clif_Auction_openwindow(struct map_session_data *sd)
{
int fd = sd->fd;
- if( sd->state.storage_flag || sd->vender_id || sd->state.buyingstore || sd->state.trading )
+ if( sd->state.storage_flag || sd->state.vending || sd->state.buyingstore || sd->state.trading )
return;
- WFIFOHEAD(fd,12);
+ WFIFOHEAD(fd,packet_len(0x25f));
WFIFOW(fd,0) = 0x25f;
WFIFOL(fd,2) = 0;
- WFIFOB(fd,6) = 0xb6;
- WFIFOB(fd,7) = 0x00;
- WFIFOB(fd,8) = 0xa6;
- WFIFOB(fd,9) = 0xde;
- WFIFOW(fd,10) = 0;
- WFIFOSET(fd,12);
+ WFIFOSET(fd,packet_len(0x25f));
}
+
+/// Returns auction item search results (ZC_AUCTION_ITEM_REQ_SEARCH)
+/// 0252 <packet len>.W <pages>.L <count>.L { <auction id>.L <seller name>.24B <name id>.W <type>.L <amount>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W <now price>.L <max price>.L <buyer name>.24B <delete time>.L }*
void clif_Auction_results(struct map_session_data *sd, short count, short pages, uint8 *buf)
{
int i, fd = sd->fd, len = sizeof(struct auction_data);
@@ -12871,7 +12883,7 @@ void clif_Auction_results(struct map_session_data *sd, short count, short pages,
struct item_data *item;
int k;
- WFIFOHEAD(fd,20);
+ WFIFOHEAD(fd,12 + (count * 83));
WFIFOW(fd,0) = 0x252;
WFIFOW(fd,2) = 12 + (count * 83);
WFIFOL(fd,4) = pages;
@@ -12890,9 +12902,8 @@ void clif_Auction_results(struct map_session_data *sd, short count, short pages,
else
WFIFOW(fd,28+k) = auction.item.nameid;
- WFIFOW(fd,30+k) = auction.type;
- WFIFOW(fd,32+k) = 0; // ??
- WFIFOW(fd,34+k) = auction.item.amount; // Allways 1
+ WFIFOL(fd,30+k) = auction.type;
+ WFIFOW(fd,34+k) = auction.item.amount; // Always 1
WFIFOB(fd,36+k) = auction.item.identify;
WFIFOB(fd,37+k) = auction.item.attribute;
WFIFOB(fd,38+k) = auction.item.refine;
@@ -12905,7 +12916,7 @@ void clif_Auction_results(struct map_session_data *sd, short count, short pages,
safestrncpy((char*)WFIFOP(fd,55+k), auction.buyer_name, NAME_LENGTH);
WFIFOL(fd,79+k) = (uint32)auction.timestamp;
}
- WFIFOSET(fd, 12 + (count * 83));
+ WFIFOSET(fd,WFIFOW(fd,2));
}
static void clif_Auction_setitem(int fd, int index, bool fail)
@@ -12928,7 +12939,7 @@ void clif_parse_Auction_cancelreg(int fd, struct map_session_data *sd)
void clif_parse_Auction_setitem(int fd, struct map_session_data *sd)
{
int idx = RFIFOW(fd,2) - 2;
- int amount = RFIFOL(fd,4); // Allways 1
+ int amount = RFIFOL(fd,4); // Always 1
struct item_data *item;
if( sd->auction.amount > 0 )
@@ -12963,34 +12974,40 @@ void clif_parse_Auction_setitem(int fd, struct map_session_data *sd)
clif_Auction_setitem(fd, idx + 2, false);
}
-// 0 = You have failed to bid into the auction
-// 1 = You have successfully bid in the auction
-// 2 = The auction has been canceled
-// 3 = An auction with at least one bidder cannot be canceled
-// 4 = You cannot register more than 5 items in an auction at a time
-// 5 = You do not have enough Zeny to pay the Auction Fee
-// 6 = You have won the auction
-// 7 = You have failed to win the auction
-// 8 = You do not have enough Zeny
-// 9 = You cannot place more than 5 bids at a time
-
+/// Result from an auction action (ZC_AUCTION_RESULT)
+/// 0250 <result>.B
+/// result:
+/// 0 = You have failed to bid into the auction
+/// 1 = You have successfully bid in the auction
+/// 2 = The auction has been canceled
+/// 3 = An auction with at least one bidder cannot be canceled
+/// 4 = You cannot register more than 5 items in an auction at a time
+/// 5 = You do not have enough Zeny to pay the Auction Fee
+/// 6 = You have won the auction
+/// 7 = You have failed to win the auction
+/// 8 = You do not have enough Zeny
+/// 9 = You cannot place more than 5 bids at a time
void clif_Auction_message(int fd, unsigned char flag)
{
- WFIFOHEAD(fd,3);
+ WFIFOHEAD(fd,packet_len(0x250));
WFIFOW(fd,0) = 0x250;
WFIFOB(fd,2) = flag;
- WFIFOSET(fd,3);
+ WFIFOSET(fd,packet_len(0x250));
}
-// 0 = You have ended the auction
-// 1 = You cannot end the auction
-// 2 = Bid number is incorrect
+
+/// Result of the auction close request (ZC_AUCTION_ACK_MY_SELL_STOP)
+/// 025e <result>.W
+/// result:
+/// 0 = You have ended the auction
+/// 1 = You cannot end the auction
+/// 2 = Bid number is incorrect
void clif_Auction_close(int fd, unsigned char flag)
{
- WFIFOHEAD(fd,6);
- WFIFOW(fd,0) = 0x25d;
- WFIFOL(fd,2) = flag;
- WFIFOSET(fd,6);
+ WFIFOHEAD(fd,packet_len(0x25e));
+ WFIFOW(fd,0) = 0x25d; // BUG: The client identifies this packet as 0x25d (CZ_AUCTION_REQ_MY_SELL_STOP)
+ WFIFOW(fd,2) = flag;
+ WFIFOSET(fd,packet_len(0x25e));
}
void clif_parse_Auction_register(int fd, struct map_session_data *sd)
@@ -13749,7 +13766,10 @@ int clif_bg_xy_remove(struct map_session_data *sd)
return 0;
}
-int clif_bg_message(struct battleground_data *bg, const char *name, const char *mes, int len)
+
+/// Notifies clients of a battleground message (ZC_BATTLEFIELD_CHAT)
+/// 02dc <packet len>.W <account id>.L <name>.24B <message>.?B
+int clif_bg_message(struct battleground_data *bg, int src_id, const char *name, const char *mes, int len)
{
struct map_session_data *sd;
unsigned char *buf;
@@ -13760,7 +13780,7 @@ int clif_bg_message(struct battleground_data *bg, const char *name, const char *
WBUFW(buf,0) = 0x2dc;
WBUFW(buf,2) = len + NAME_LENGTH + 8;
- WBUFL(buf,4) = sd->state.bg_id;
+ WBUFL(buf,4) = src_id;
memcpy(WBUFP(buf,8), name, NAME_LENGTH);
memcpy(WBUFP(buf,32), mes, len);
clif_send(buf,WBUFW(buf,2), &sd->bl, BG);
@@ -13974,6 +13994,7 @@ void clif_party_show_picker(struct map_session_data * sd, struct item * item_dat
{
#if PACKETVER >= 20071002
unsigned char buf[22];
+ struct item_data* id = itemdb_search(item_data->nameid);
WBUFW(buf,0)=0x2b8;
WBUFL(buf,2) = sd->status.account_id;
@@ -13981,12 +14002,9 @@ void clif_party_show_picker(struct map_session_data * sd, struct item * item_dat
WBUFB(buf,8) = item_data->identify;
WBUFB(buf,9) = item_data->attribute;
WBUFB(buf,10) = item_data->refine;
- WBUFW(buf,11) = item_data->card[0];
- WBUFW(buf,13) = item_data->card[1];
- WBUFW(buf,15) = item_data->card[2];
- WBUFW(buf,17) = item_data->card[3];
- //WBUFW(buf,19) = 0; // equip location? 32+2 for left/right hand, 0x8000 for 'throw' (verify this)
- //WBUFB(buf,21) = 0; // item type
+ clif_addcards(WBUFP(buf,11), item_data);
+ WBUFW(buf,19) = id->equip; // equip location
+ WBUFB(buf,21) = itemtype(id->type); // item type
clif_send(buf, packet_len(0x2b8), &sd->bl, PARTY_SAMEMAP_WOS);
#endif
}
@@ -14033,6 +14051,26 @@ void clif_showdigit(struct map_session_data* sd, unsigned char type, int value)
}
+/// Notification of the state of client command /effect (CZ_LESSEFFECT)
+/// 021d <state>.L
+/// state:
+/// 0 = Full effects
+/// 1 = Reduced effects
+///
+/// @note The state is used on Aegis for sending skill unit packet
+/// 0x11f (ZC_SKILL_ENTRY) instead of 0x1c9 (ZC_SKILL_ENTRY2)
+/// whenever possible. Due to the way the decision check is
+/// constructed, this state tracking was rendered useless,
+/// as the only skill unit, that is sent with 0x1c9 is
+/// Graffiti.
+void clif_parse_LessEffect(int fd, struct map_session_data* sd)
+{
+ int isLess = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]);
+
+ sd->state.lesseffect = ( isLess != 0 );
+}
+
+
/// Buying Store System
///
@@ -14813,7 +14851,7 @@ static int packetdb_readdb(void)
12, 26, 9, 11, -1, -1, 10, 2,282, 11, 4, 36, -1, -1, 4, 2,
//#0x0240
-1, -1, -1, -1, -1, 3, 4, 8, -1, 3, 70, 4, 8, 12, 4, 10,
- 3, 32, -1, 3, 3, 5, 5, 8, 2, 3, -1, 6, 4, -1, 4, 0,
+ 3, 32, -1, 3, 3, 5, 5, 8, 2, 3, -1, 6, 4, 6, 4, 6,
6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
//#0x0280
@@ -15129,6 +15167,7 @@ static int packetdb_readdb(void)
{clif_parse_PartyBookingDeleteReq,"bookingdelreq"},
#endif
{clif_parse_PVPInfo,"pvpinfo"},
+ {clif_parse_LessEffect,"lesseffect"},
// Buying Store
{clif_parse_ReqOpenBuyingStore,"reqopenbuyingstore"},
{clif_parse_ReqCloseBuyingStore,"reqclosebuyingstore"},
diff --git a/src/map/clif.h b/src/map/clif.h
index 85293405d..2d90eb522 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -451,7 +451,7 @@ int clif_guild_xy_remove(struct map_session_data *sd);
int clif_bg_hp(struct map_session_data *sd);
int clif_bg_xy(struct map_session_data *sd);
int clif_bg_xy_remove(struct map_session_data *sd);
-int clif_bg_message(struct battleground_data *bg, const char *name, const char *mes, int len);
+int clif_bg_message(struct battleground_data *bg, int src_id, const char *name, const char *mes, int len);
int clif_bg_updatescore(int m);
int clif_bg_updatescore_single(struct map_session_data *sd);
int clif_sendbgemblem_area(struct map_session_data *sd);
diff --git a/src/map/guild.c b/src/map/guild.c
index 7b20808d6..e56b346ec 100644
--- a/src/map/guild.c
+++ b/src/map/guild.c
@@ -357,7 +357,9 @@ int guild_create(struct map_session_data *sd, const char *name)
nullpo_ret(sd);
safestrncpy(tname, name, NAME_LENGTH);
- if( strlen(trim(tname)) == 0 )
+ trim(tname);
+
+ if( !tname[0] )
return 0; // empty name
if( sd->status.guild_id )
diff --git a/src/map/mail.c b/src/map/mail.c
index c866bfb60..59afa0421 100644
--- a/src/map/mail.c
+++ b/src/map/mail.c
@@ -162,7 +162,7 @@ int mail_openmail(struct map_session_data *sd)
{
nullpo_ret(sd);
- if( sd->state.storage_flag || sd->vender_id || sd->state.buyingstore || sd->state.trading )
+ if( sd->state.storage_flag || sd->state.vending || sd->state.buyingstore || sd->state.trading )
return 0;
clif_Mail_window(sd->fd, 0);
diff --git a/src/map/map.c b/src/map/map.c
index 2cd146ee4..9f9c93608 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -89,7 +89,6 @@ char *LOG_CONF_NAME;
char *MAP_CONF_NAME;
char *BATTLE_CONF_FILENAME;
char *ATCOMMAND_CONF_FILENAME;
-char *CHARCOMMAND_CONF_FILENAME;
char *SCRIPT_CONF_NAME;
char *MSG_CONF_NAME;
char *GRF_PATH_FILENAME;
@@ -3515,7 +3514,6 @@ void map_helpscreen(int flag)
puts(" --map-config <file> Load map-server configuration from <file>");
puts(" --battle-config <file> Load battle configuration from <file>");
puts(" --atcommand-config <file> Load atcommand configuration from <file>");
- puts(" --charcommand-config <file> Load charcommand configuration from <file>");
puts(" --script-config <file> Load script configuration from <file>");
puts(" --msg-config <file> Load message configuration from <file>");
puts(" --grf-path-file <file> Load grf path file configuration from <file>");
@@ -3564,7 +3562,6 @@ int do_init(int argc, char *argv[])
MAP_CONF_NAME = "conf/map_athena.conf";
BATTLE_CONF_FILENAME = "conf/battle_athena.conf";
ATCOMMAND_CONF_FILENAME = "conf/atcommand_athena.conf";
- CHARCOMMAND_CONF_FILENAME = "conf/charcommand_athena.conf";
SCRIPT_CONF_NAME = "conf/script_athena.conf";
MSG_CONF_NAME = "conf/msg_athena.conf";
GRF_PATH_FILENAME = "conf/grf-files.txt";
diff --git a/src/map/mob.c b/src/map/mob.c
index 6135850b6..1626f49a0 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -2586,7 +2586,7 @@ int mob_class_change (struct mob_data *md, int class_)
mob_stop_walking(md, 0);
unit_skillcastcancel(&md->bl, 0);
status_set_viewdata(&md->bl, class_);
- clif_mob_class_change(md,class_);
+ clif_mob_class_change(md,md->vd->class_);
status_calc_mob(md, 1);
md->ud.state.speed_changed = 1; //Speed change update.
@@ -4167,7 +4167,7 @@ static bool mob_parse_row_mobskilldb(char** str, int columns, int current)
ms->val[1] = 0; //Do not "set" it.
}
- if(str[17] != NULL && strlen(str[17])>2)
+ if(*str[17])
ms->emotion=atoi(str[17]);
else
ms->emotion=-1;
diff --git a/src/map/npc.c b/src/map/npc.c
index bc2018459..95331ae5b 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -160,9 +160,13 @@ int npc_enable_sub(struct block_list *bl, va_list ap)
int npc_enable(const char* name, int flag)
{
- struct npc_data* nd = (struct npc_data*)strdb_get(npcname_db, name);
+ struct npc_data* nd = npc_name2id(name);
+
if (nd==NULL)
+ {
+ ShowError("npc_enable: Attempted to %s a non-existing NPC '%s' (flag=%d).\n", (flag&3) ? "show" : "hide", name, flag);
return 0;
+ }
if (flag&1)
nd->sc.option&=~OPTION_INVISIBLE;
@@ -813,7 +817,7 @@ int npc_touchnext_areanpc(struct map_session_data* sd, bool leavemap)
nd->touching_id = sd->touching_id = 0;
snprintf(name, ARRAYLENGTH(name), "%s::%s", nd->exname, script_config.ontouch_name);
- map_forcountinarea(npc_touch_areanpc_sub,nd->bl.m,nd->bl.m - xs,nd->bl.y - ys,nd->bl.x + xs,nd->bl.y + ys,1,BL_PC,sd->bl.id,nd->bl.id,name);
+ map_forcountinarea(npc_touch_areanpc_sub,nd->bl.m,nd->bl.x - xs,nd->bl.y - ys,nd->bl.x + xs,nd->bl.y + ys,1,BL_PC,sd->bl.id,nd->bl.id,name);
}
return 0;
}
@@ -902,7 +906,7 @@ int npc_touch_areanpc2(struct mob_data *md)
switch( map[m].npc[i]->subtype )
{
case WARP:
- if( !battle_config.mob_warp&1 )
+ if( !( battle_config.mob_warp&1 ) )
continue;
xs = map[m].npc[i]->u.warp.xs;
ys = map[m].npc[i]->u.warp.ys;
@@ -1034,7 +1038,7 @@ struct npc_data* npc_checknear(struct map_session_data* sd, struct block_list* b
*------------------------------------------*/
int npc_globalmessage(const char* name, const char* mes)
{
- struct npc_data* nd = (struct npc_data *) strdb_get(npcname_db, name);
+ struct npc_data* nd = npc_name2id(name);
char temp[100];
if (!nd)
diff --git a/src/map/party.c b/src/map/party.c
index 21867c95a..47dba49e9 100644
--- a/src/map/party.c
+++ b/src/map/party.c
@@ -128,7 +128,9 @@ int party_create(struct map_session_data *sd,char *name,int item,int item2)
char tname[NAME_LENGTH];
safestrncpy(tname, name, NAME_LENGTH);
- if( strlen(trim(tname)) == 0 )
+ trim(tname);
+
+ if( !tname[0] )
{// empty name
return 0;
}
diff --git a/src/map/pc.c b/src/map/pc.c
index 82e395153..7ee8bec90 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -3251,7 +3251,10 @@ int pc_payzeny(struct map_session_data *sd,int zeny)
nullpo_ret(sd);
if( zeny < 0 )
- return pc_getzeny(sd, -zeny);
+ {
+ ShowError("pc_payzeny: Paying negative Zeny (zeny=%d, account_id=%d, char_id=%d).\n", zeny, sd->status.account_id, sd->status.char_id);
+ return 1;
+ }
if( sd->status.zeny < zeny )
return 1; //Not enough.
@@ -3307,7 +3310,10 @@ int pc_getzeny(struct map_session_data *sd,int zeny)
nullpo_ret(sd);
if( zeny < 0 )
- return pc_payzeny(sd, -zeny);
+ {
+ ShowError("pc_getzeny: Obtaining negative Zeny (zeny=%d, account_id=%d, char_id=%d).\n", zeny, sd->status.account_id, sd->status.char_id);
+ return 1;
+ }
if( zeny > MAX_ZENY - sd->status.zeny )
zeny = MAX_ZENY - sd->status.zeny;
@@ -3447,7 +3453,7 @@ int pc_dropitem(struct map_session_data *sd,int n,int amount)
if(sd->status.inventory[n].nameid <= 0 ||
sd->status.inventory[n].amount <= 0 ||
sd->status.inventory[n].amount < amount ||
- sd->state.trading || sd->vender_id != 0 ||
+ sd->state.trading || sd->state.vending ||
!sd->inventory_data[n] //pc_delitem would fail on this case.
)
return 0;
@@ -3887,7 +3893,7 @@ int pc_putitemtocart(struct map_session_data *sd,int idx,int amount)
item_data = &sd->status.inventory[idx];
- if( item_data->nameid == 0 || amount < 1 || item_data->amount < amount || sd->vender_id )
+ if( item_data->nameid == 0 || amount < 1 || item_data->amount < amount || sd->state.vending )
return 1;
if( pc_cart_additem(sd,item_data,amount) == 0 )
@@ -3927,7 +3933,7 @@ int pc_getitemfromcart(struct map_session_data *sd,int idx,int amount)
item_data=&sd->status.cart[idx];
- if(item_data->nameid==0 || amount < 1 || item_data->amount<amount || sd->vender_id )
+ if(item_data->nameid==0 || amount < 1 || item_data->amount<amount || sd->state.vending )
return 1;
if((flag = pc_additem(sd,item_data,amount)) == 0)
return pc_cart_delitem(sd,idx,amount,0);
@@ -6220,7 +6226,7 @@ int pc_readparam(struct map_session_data* sd,int type)
*------------------------------------------*/
int pc_setparam(struct map_session_data *sd,int type,int val)
{
- int i = 0;
+ int i = 0, statlimit;
nullpo_ret(sd);
@@ -6283,7 +6289,7 @@ int pc_setparam(struct map_session_data *sd,int type,int val)
}
break;
case SP_SEX:
- sd->status.sex = val;
+ sd->status.sex = val ? SEX_MALE : SEX_FEMALE;
break;
case SP_WEIGHT:
sd->weight = val;
@@ -6292,34 +6298,52 @@ int pc_setparam(struct map_session_data *sd,int type,int val)
sd->max_weight = val;
break;
case SP_HP:
- sd->battle_status.hp = val;
+ sd->battle_status.hp = cap_value(val, 1, (int)sd->battle_status.max_hp);
break;
case SP_MAXHP:
- sd->battle_status.max_hp = val;
+ sd->battle_status.max_hp = cap_value(val, 1, battle_config.max_hp);
+
+ if( sd->battle_status.max_hp < sd->battle_status.hp )
+ {
+ sd->battle_status.hp = sd->battle_status.max_hp;
+ clif_updatestatus(sd, SP_HP);
+ }
break;
case SP_SP:
- sd->battle_status.sp = val;
+ sd->battle_status.sp = cap_value(val, 0, (int)sd->battle_status.max_sp);
break;
case SP_MAXSP:
- sd->battle_status.max_sp = val;
+ sd->battle_status.max_sp = cap_value(val, 1, battle_config.max_sp);
+
+ if( sd->battle_status.max_sp < sd->battle_status.sp )
+ {
+ sd->battle_status.sp = sd->battle_status.max_sp;
+ clif_updatestatus(sd, SP_SP);
+ }
break;
case SP_STR:
- sd->status.str = val;
+ statlimit = pc_maxparameter(sd);
+ sd->status.str = cap_value(val, 1, statlimit);
break;
case SP_AGI:
- sd->status.agi = val;
+ statlimit = pc_maxparameter(sd);
+ sd->status.agi = cap_value(val, 1, statlimit);
break;
case SP_VIT:
- sd->status.vit = val;
+ statlimit = pc_maxparameter(sd);
+ sd->status.vit = cap_value(val, 1, statlimit);
break;
case SP_INT:
- sd->status.int_ = val;
+ statlimit = pc_maxparameter(sd);
+ sd->status.int_ = cap_value(val, 1, statlimit);
break;
case SP_DEX:
- sd->status.dex = val;
+ statlimit = pc_maxparameter(sd);
+ sd->status.dex = cap_value(val, 1, statlimit);
break;
case SP_LUK:
- sd->status.luk = val;
+ statlimit = pc_maxparameter(sd);
+ sd->status.luk = cap_value(val, 1, statlimit);
break;
case SP_KARMA:
sd->status.karma = val;
@@ -7538,7 +7562,7 @@ int pc_checkitem(struct map_session_data *sd)
nullpo_ret(sd);
- if( sd->vender_id ) //Avoid reorganizing items when we are vending, as that leads to exploits (pointed out by End of Exam)
+ if( sd->state.vending ) //Avoid reorganizing items when we are vending, as that leads to exploits (pointed out by End of Exam)
return 0;
if( battle_config.item_check )
diff --git a/src/map/pc.h b/src/map/pc.h
index b9ccf3e88..28ed28da8 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -130,6 +130,8 @@ struct map_session_data {
unsigned ignoreAll : 1;
unsigned debug_remove_map : 1; // temporary state to track double remove_map's [FlavioJS]
unsigned buyingstore : 1;
+ unsigned lesseffect : 1;
+ unsigned vending : 1;
unsigned short autoloot;
unsigned short autolootid; // [Zephyrus]
unsigned noks : 3; // [Zeph Kill Steal Protection]
@@ -522,9 +524,9 @@ extern int duel_count;
#define pc_setsit(sd) ( (sd)->state.dead_sit = (sd)->vd.dead_sit = 2 )
#define pc_isdead(sd) ( (sd)->state.dead_sit == 1 )
#define pc_issit(sd) ( (sd)->vd.dead_sit == 2 )
-#define pc_isidle(sd) ( (sd)->chatID || (sd)->vender_id || (sd)->state.buyingstore || DIFF_TICK(last_tick, (sd)->idletime) >= battle_config.idle_no_share )
-#define pc_istrading(sd) ( (sd)->npc_id || (sd)->vender_id || (sd)->state.buyingstore || (sd)->state.trading )
-#define pc_cant_act(sd) ( (sd)->npc_id || (sd)->vender_id || (sd)->state.buyingstore || (sd)->chatID || (sd)->sc.opt1 || (sd)->state.trading || (sd)->state.storage_flag )
+#define pc_isidle(sd) ( (sd)->chatID || (sd)->state.vending || (sd)->state.buyingstore || DIFF_TICK(last_tick, (sd)->idletime) >= battle_config.idle_no_share )
+#define pc_istrading(sd) ( (sd)->npc_id || (sd)->state.vending || (sd)->state.buyingstore || (sd)->state.trading )
+#define pc_cant_act(sd) ( (sd)->npc_id || (sd)->state.vending || (sd)->state.buyingstore || (sd)->chatID || (sd)->sc.opt1 || (sd)->state.trading || (sd)->state.storage_flag )
#define pc_setdir(sd,b,h) ( (sd)->ud.dir = (b) ,(sd)->head_dir = (h) )
#define pc_setchatid(sd,n) ( (sd)->chatID = n )
#define pc_ishiding(sd) ( (sd)->sc.option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) )
diff --git a/src/map/pet.c b/src/map/pet.c
index 6b16fe888..1f350ec4b 100644
--- a/src/map/pet.c
+++ b/src/map/pet.c
@@ -1220,7 +1220,7 @@ int read_petdb()
for( i = 0; i < ARRAYLENGTH(filename); i++ )
{
char line[1024];
- int lines;
+ int lines, entries;
sprintf(line, "%s/%s", db_path, filename[i]);
fp=fopen(line,"r");
@@ -1231,7 +1231,7 @@ int read_petdb()
continue;
}
- lines = 0;
+ lines = entries = 0;
while( fgets(line, sizeof(line), fp) && j < MAX_PET_DB )
{
char *str[22], *p;
@@ -1326,12 +1326,13 @@ int read_petdb()
pet_db[j].equip_script = parse_script(str[21], filename[i], lines, 0);
j++;
+ entries++;
}
if( j >= MAX_PET_DB )
ShowWarning("read_petdb: Reached max number of pets [%d]. Remaining pets were not read.\n ", MAX_PET_DB);
fclose(fp);
- ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' pets in '"CL_WHITE"%s"CL_RESET"'.\n",j,filename[i]);
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' pets in '"CL_WHITE"%s"CL_RESET"'.\n", entries, filename[i]);
}
return 0;
}
diff --git a/src/map/script.c b/src/map/script.c
index dec4a3f89..4e874b5f0 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -9268,46 +9268,22 @@ BUILDIN_FUNC(globalmes)
/// Creates a waiting room (chat room) for this npc.
///
-/// waitingroom "<title>",<limit>,<trigger>,"<event>";
-/// waitingroom "<title>",<limit>,"<event>",<trigger>;
-/// waitingroom "<title>",<limit>,"<event>";
-/// waitingroom "<title>",<limit>;
+/// waitingroom "<title>",<limit>{,"<event>"{,<trigger>{,<zeny>{,<minlvl>{,<maxlvl>}}}}};
BUILDIN_FUNC(waitingroom)
{
- struct npc_data* nd;
- const char* title;
- const char* ev = "";
- int limit;
- int trigger = 0;
+ struct npc_data* nd;
int pub = 1;
-
- title = script_getstr(st, 2);
- limit = script_getnum(st, 3);
-
- if( script_hasdata(st,5) )
- {
- struct script_data* last = script_getdata(st, 5);
- get_val(st, last);
- if( data_isstring(last) )
- {// ,<trigger>,"<event>"
- trigger = script_getnum(st, 4);
- ev = script_getstr(st, 5);
- }
- else
- {// ,"<event>",<trigger>
- ev = script_getstr(st, 4);
- trigger = script_getnum(st,5);
- }
- }
- else if( script_hasdata(st,4) )
- {// ,"<event>"
- ev = script_getstr(st, 4);
- trigger = limit;
- }
+ const char* title = script_getstr(st, 2);
+ int limit = script_getnum(st, 3);
+ const char* ev = script_hasdata(st,4) ? script_getstr(st,4) : "";
+ int trigger = script_hasdata(st,5) ? script_getnum(st,5) : limit;
+ int zeny = script_hasdata(st,6) ? script_getnum(st,6) : 0;
+ int minLvl = script_hasdata(st,7) ? script_getnum(st,7) : 1;
+ int maxLvl = script_hasdata(st,8) ? script_getnum(st,8) : MAX_LEVEL;
nd = (struct npc_data *)map_id2bl(st->oid);
if( nd != NULL )
- chat_createnpcchat(nd, title, limit, pub, trigger, ev);
+ chat_createnpcchat(nd, title, limit, pub, trigger, ev, zeny, minLvl, maxLvl);
return 0;
}
@@ -9471,11 +9447,19 @@ BUILDIN_FUNC(warpwaitingpc)
for( i = 0; i < n && cd->users > 0; i++ )
{
sd = cd->usersd[0];
- if( sd == NULL )
- {
- ShowDebug("script:warpwaitingpc: no user in chat room position 0 (cd->users=%d,%d/%d)\n", cd->users, i, n);
- mapreg_setreg(reference_uid(add_str("$@warpwaitingpc"), i), 0);
- continue;// Broken npc chat room?
+
+ if( strcmp(map_name,"SavePoint") == 0 && map[sd->bl.m].flag.noteleport )
+ {// can't teleport on this map
+ break;
+ }
+
+ if( cd->zeny )
+ {// fee set
+ if( (uint32)sd->status.zeny < cd->zeny )
+ {// no zeny to cover set fee
+ break;
+ }
+ pc_payzeny(sd, cd->zeny);
}
mapreg_setreg(reference_uid(add_str("$@warpwaitingpc"), i), sd->bl.id);
@@ -9483,12 +9467,7 @@ BUILDIN_FUNC(warpwaitingpc)
if( strcmp(map_name,"Random") == 0 )
pc_randomwarp(sd,CLR_TELEPORT);
else if( strcmp(map_name,"SavePoint") == 0 )
- {
- if( map[sd->bl.m].flag.noteleport )
- return 0;// can't teleport on this map
-
pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT);
- }
else
pc_setpos(sd, mapindex_name2id(map_name), x, y, CLR_OUTSIGHT);
}
@@ -11459,7 +11438,15 @@ BUILDIN_FUNC(specialeffect)
clif_specialeffect(&nd->bl, type, target);
}
else
- clif_specialeffect(bl, type, target);
+ {
+ if (target == SELF) {
+ TBL_PC *sd=script_rid2sd(st);
+ if (sd)
+ clif_specialeffect_single(bl,type,sd->fd);
+ } else {
+ clif_specialeffect(bl, type, target);
+ }
+ }
return 0;
}
@@ -11792,6 +11779,8 @@ BUILDIN_FUNC(movenpc)
if ((nd = npc_name2id(npc)) == NULL)
return -1;
+ if (script_hasdata(st,5))
+ nd->ud.dir = script_getnum(st,5);
npc_movenpc(nd, x, y);
return 0;
}
@@ -13111,7 +13100,7 @@ BUILDIN_FUNC(checkvending) // check vending [Nab4]
sd = script_rid2sd(st);
if(sd)
- script_pushint(st,(sd->vender_id != 0));
+ script_pushint(st,sd->state.vending);
else
script_pushint(st,0);
@@ -15029,7 +15018,7 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(skillpointcount,""),
BUILDIN_DEF(changebase,"i?"),
BUILDIN_DEF(changesex,""),
- BUILDIN_DEF(waitingroom,"si??"),
+ BUILDIN_DEF(waitingroom,"si?????"),
BUILDIN_DEF(delwaitingroom,"?"),
BUILDIN_DEF2(waitingroomkickall,"kickwaitingroomall","?"),
BUILDIN_DEF(enablewaitingroomevent,"?"),
@@ -15102,7 +15091,7 @@ struct script_function buildin_func[] = {
BUILDIN_DEF(mapwarp,"ssii??"), // Added by RoVeRT
BUILDIN_DEF(atcommand,"s"), // [MouseJstr]
BUILDIN_DEF(charcommand,"s"), // [MouseJstr]
- BUILDIN_DEF(movenpc,"sii"), // [MouseJstr]
+ BUILDIN_DEF(movenpc,"sii?"), // [MouseJstr]
BUILDIN_DEF(message,"ss"), // [MouseJstr]
BUILDIN_DEF(npctalk,"s"), // [Valaris]
BUILDIN_DEF(mobcount,"ss"),
diff --git a/src/map/searchstore.c b/src/map/searchstore.c
index d7378ab36..76f0d4e2e 100644
--- a/src/map/searchstore.c
+++ b/src/map/searchstore.c
@@ -71,7 +71,7 @@ static bool searchstore_hasstore(struct map_session_data* sd, unsigned char type
{
switch( type )
{
- case SEARCHTYPE_VENDING: return (bool)( sd->vender_id != 0 );
+ case SEARCHTYPE_VENDING: return sd->state.vending;
case SEARCHTYPE_BUYING_STORE: return sd->state.buyingstore;
}
return false;
diff --git a/src/map/skill.c b/src/map/skill.c
index 160beeaef..d95d04134 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -398,6 +398,7 @@ int skillnotok (int skillid, struct map_session_data *sd)
break;
case MC_VENDING:
case MC_IDENTIFY:
+ case ALL_BUYING_STORE:
return 0; // always allowed
case WZ_ICEWALL:
// noicewall flag [Valaris]
diff --git a/src/map/status.c b/src/map/status.c
index 33da5fb14..e4f333753 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -7439,6 +7439,9 @@ int status_change_clear_buffs (struct block_list* bl, int type)
case SC_FOOD_DEX_CASH:
case SC_FOOD_INT_CASH:
case SC_FOOD_LUK_CASH:
+ case SC_EXPBOOST:
+ case SC_JEXPBOOST:
+ case SC_ITEMBOOST:
continue;
//Debuffs that can be removed.
diff --git a/src/map/trade.c b/src/map/trade.c
index bedbb9451..fb9fecbac 100644
--- a/src/map/trade.c
+++ b/src/map/trade.c
@@ -138,8 +138,8 @@ void trade_tradeack(struct map_session_data *sd, int type)
}
//Check if you can start trade.
- if (sd->npc_id || sd->vender_id || sd->state.buyingstore || sd->state.storage_flag ||
- tsd->npc_id || tsd->vender_id || tsd->state.buyingstore || tsd->state.storage_flag)
+ if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.storage_flag ||
+ tsd->npc_id || tsd->state.vending || tsd->state.buyingstore || tsd->state.storage_flag)
{ //Fail
clif_tradestart(sd, 2);
clif_tradestart(tsd, 2);
diff --git a/src/map/unit.c b/src/map/unit.c
index 2467baf86..da1ce1c14 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -802,7 +802,7 @@ int unit_can_move(struct block_list *bl)
if (sd && (
pc_issit(sd) ||
- sd->vender_id ||
+ sd->state.vending ||
sd->state.buyingstore ||
sd->state.blockedmove
))
@@ -1871,8 +1871,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file,
chat_leavechat(sd,0);
if(sd->trade_partner)
trade_tradecancel(sd);
- if(sd->vender_id)
- vending_closevending(sd);
+ vending_closevending(sd);
buyingstore_close(sd);
searchstore_close(sd);
if(sd->state.storage_flag == 1)
diff --git a/src/map/vending.c b/src/map/vending.c
index 08e15d733..c5ead6513 100644
--- a/src/map/vending.c
+++ b/src/map/vending.c
@@ -19,16 +19,11 @@
#include <stdio.h>
#include <string.h>
-static int vending_nextid = 1;
+static int vending_nextid = 0;
/// Returns an unique vending shop id.
static int vending_getuid(void)
{
- if(!vending_nextid)
- {// wrapped around, 0 is reserved for "not vending" state on eathena
- vending_nextid = 1;
- }
-
return vending_nextid++;
}
@@ -39,8 +34,11 @@ void vending_closevending(struct map_session_data* sd)
{
nullpo_retv(sd);
- sd->vender_id = 0;
- clif_closevendingboard(&sd->bl,0);
+ if( sd->state.vending )
+ {
+ sd->state.vending = false;
+ clif_closevendingboard(&sd->bl, 0);
+ }
}
/*==========================================
@@ -53,7 +51,7 @@ void vending_vendinglistreq(struct map_session_data* sd, int id)
if( (vsd = map_id2sd(id)) == NULL )
return;
- if( vsd->vender_id == 0 )
+ if( !vsd->state.vending )
return; // not vending
if ( !pc_can_give_items(pc_isGM(sd)) || !pc_can_give_items(pc_isGM(vsd)) ) //check if both GMs are allowed to trade
@@ -78,7 +76,7 @@ void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const ui
struct map_session_data* vsd = map_id2sd(aid);
nullpo_retv(sd);
- if( vsd == NULL || vsd->vender_id == 0 || vsd->bl.id == sd->bl.id )
+ if( vsd == NULL || !vsd->state.vending || vsd->bl.id == sd->bl.id )
return; // invalid shop
if( vsd->vender_id != uid )
@@ -309,6 +307,7 @@ void vending_openvending(struct map_session_data* sd, const char* message, bool
return;
}
+ sd->state.vending = true;
sd->vender_id = vending_getuid();
sd->vend_num = i;
safestrncpy(sd->message, message, MESSAGE_SIZE);
@@ -324,7 +323,7 @@ bool vending_search(struct map_session_data* sd, unsigned short nameid)
{
int i;
- if( !sd->vender_id )
+ if( !sd->state.vending )
{// not vending
return false;
}
@@ -347,7 +346,7 @@ bool vending_searchall(struct map_session_data* sd, const struct s_search_store_
unsigned int idx, cidx;
struct item* it;
- if( !sd->vender_id )
+ if( !sd->state.vending )
{// not vending
return true;
}