diff options
Diffstat (limited to 'src/map')
-rw-r--r-- | src/map/atcommand.c | 55 | ||||
-rw-r--r-- | src/map/battle.c | 4 | ||||
-rw-r--r-- | src/map/battleground.c | 4 | ||||
-rw-r--r-- | src/map/buyingstore.c | 2 | ||||
-rw-r--r-- | src/map/chat.c | 38 | ||||
-rw-r--r-- | src/map/chat.h | 5 | ||||
-rw-r--r-- | src/map/clif.c | 185 | ||||
-rw-r--r-- | src/map/clif.h | 2 | ||||
-rw-r--r-- | src/map/guild.c | 4 | ||||
-rw-r--r-- | src/map/mail.c | 2 | ||||
-rw-r--r-- | src/map/map.c | 3 | ||||
-rw-r--r-- | src/map/mob.c | 4 | ||||
-rw-r--r-- | src/map/npc.c | 12 | ||||
-rw-r--r-- | src/map/party.c | 4 | ||||
-rw-r--r-- | src/map/pc.c | 60 | ||||
-rw-r--r-- | src/map/pc.h | 8 | ||||
-rw-r--r-- | src/map/pet.c | 7 | ||||
-rw-r--r-- | src/map/script.c | 85 | ||||
-rw-r--r-- | src/map/searchstore.c | 2 | ||||
-rw-r--r-- | src/map/skill.c | 1 | ||||
-rw-r--r-- | src/map/status.c | 3 | ||||
-rw-r--r-- | src/map/trade.c | 4 | ||||
-rw-r--r-- | src/map/unit.c | 5 | ||||
-rw-r--r-- | src/map/vending.c | 23 |
24 files changed, 307 insertions, 215 deletions
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; } |