summaryrefslogtreecommitdiff
path: root/src/map/clif.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/clif.c')
-rw-r--r--src/map/clif.c811
1 files changed, 480 insertions, 331 deletions
diff --git a/src/map/clif.c b/src/map/clif.c
index 029080958..d00cac0ee 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -4,60 +4,60 @@
#define HERCULES_CORE
-#include "../config/core.h" // ANTI_MAYAP_CHEAT, RENEWAL, SECURE_NPCTIMEOUT
+#include "config/core.h" // ANTI_MAYAP_CHEAT, RENEWAL, SECURE_NPCTIMEOUT
#include "clif.h"
+#include "map/atcommand.h"
+#include "map/battle.h"
+#include "map/battleground.h"
+#include "map/channel.h"
+#include "map/chat.h"
+#include "map/chrif.h"
+#include "map/elemental.h"
+#include "map/guild.h"
+#include "map/homunculus.h"
+#include "map/instance.h"
+#include "map/intif.h"
+#include "map/irc-bot.h"
+#include "map/itemdb.h"
+#include "map/log.h"
+#include "map/mail.h"
+#include "map/map.h"
+#include "map/mercenary.h"
+#include "map/mob.h"
+#include "map/npc.h"
+#include "map/party.h"
+#include "map/pc.h"
+#include "map/pet.h"
+#include "map/quest.h"
+#include "map/script.h"
+#include "map/skill.h"
+#include "map/status.h"
+#include "map/storage.h"
+#include "map/trade.h"
+#include "map/unit.h"
+#include "map/vending.h"
+#include "common/HPM.h"
+#include "common/cbasetypes.h"
+#include "common/conf.h"
+#include "common/ers.h"
+#include "common/grfio.h"
+#include "common/malloc.h"
+#include "common/mmo.h" // NEW_CARTS
+#include "common/nullpo.h"
+#include "common/random.h"
+#include "common/showmsg.h"
+#include "common/socket.h"
+#include "common/strlib.h"
+#include "common/timer.h"
+#include "common/utils.h"
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <time.h>
-#include "atcommand.h"
-#include "battle.h"
-#include "battleground.h"
-#include "channel.h"
-#include "chat.h"
-#include "chrif.h"
-#include "elemental.h"
-#include "guild.h"
-#include "homunculus.h"
-#include "instance.h"
-#include "intif.h"
-#include "irc-bot.h"
-#include "itemdb.h"
-#include "log.h"
-#include "mail.h"
-#include "map.h"
-#include "mercenary.h"
-#include "mob.h"
-#include "npc.h"
-#include "party.h"
-#include "pc.h"
-#include "pet.h"
-#include "quest.h"
-#include "script.h"
-#include "skill.h"
-#include "status.h"
-#include "storage.h"
-#include "trade.h"
-#include "unit.h"
-#include "vending.h"
-#include "../common/HPM.h"
-#include "../common/cbasetypes.h"
-#include "../common/conf.h"
-#include "../common/ers.h"
-#include "../common/grfio.h"
-#include "../common/malloc.h"
-#include "../common/mmo.h" // NEW_CARTS
-#include "../common/nullpo.h"
-#include "../common/random.h"
-#include "../common/showmsg.h"
-#include "../common/socket.h"
-#include "../common/strlib.h"
-#include "../common/timer.h"
-#include "../common/utils.h"
-
struct clif_interface clif_s;
/* re-usable */
@@ -688,6 +688,7 @@ void clif_authrefuse(int fd, uint8 error_code)
/// 109 = BAN_INVALID_PWD_CNT
/// 110 = BAN_NOT_ALLOWED_JOBCLASS
/// ? = disconnected -> MsgStringTable[3]
+// TODO: type enum
void clif_authfail_fd(int fd, int type)
{
if (!fd || !session[fd] || session[fd]->func_parse != clif->parse) //clif_authfail should only be invoked on players!
@@ -1369,7 +1370,7 @@ bool clif_spawn(struct block_list *bl)
if( sd->bg_id && map->list[sd->bl.m].flag.battleground )
clif->sendbgemblem_area(sd);
for( i = 0; i < sd->sc_display_count; i++ ) {
- clif->sc_load(&sd->bl, sd->bl.id,AREA,status->IconChangeTable[sd->sc_display[i]->type],sd->sc_display[i]->val1,sd->sc_display[i]->val2,sd->sc_display[i]->val3);
+ clif->sc_load(&sd->bl, sd->bl.id,AREA,status->dbs->IconChangeTable[sd->sc_display[i]->type],sd->sc_display[i]->val1,sd->sc_display[i]->val2,sd->sc_display[i]->val3);
}
if (sd->charm_type != CHARM_TYPE_NONE && sd->charm_count > 0)
clif->spiritcharm(sd);
@@ -1520,19 +1521,24 @@ void clif_homskillinfoblock(struct map_session_data *sd) {
WFIFOHEAD(fd, 4+37*MAX_HOMUNSKILL);
WFIFOW(fd,0)=0x235;
- for ( i = 0; i < MAX_HOMUNSKILL; i++){
+ for ( i = 0; i < MAX_HOMUNSKILL; i++ ) {
int id = hd->homunculus.hskill[i].id;
- if (id != 0) {
+ if ( id != 0 ) {
j = id - HM_SKILLBASE;
- WFIFOW(fd,len ) = id;
- WFIFOW(fd,len+2) = skill->get_inf(id);
- WFIFOW(fd,len+4) = 0;
- WFIFOW(fd,len+6) = hd->homunculus.hskill[j].lv;
- WFIFOW(fd,len+8) = skill->get_sp(id,hd->homunculus.hskill[j].lv);
- WFIFOW(fd,len+10)= skill->get_range2(&sd->hd->bl, id,hd->homunculus.hskill[j].lv);
- safestrncpy((char*)WFIFOP(fd,len+12), skill->get_name(id), NAME_LENGTH);
- WFIFOB(fd,len+36) = (hd->homunculus.hskill[j].lv < homun->skill_tree_get_max(id, hd->homunculus.class_))?1:0;
- len+=37;
+ WFIFOW(fd, len) = id;
+ WFIFOW(fd, len + 2) = skill->get_inf(id);
+ WFIFOW(fd, len + 4) = 0;
+ WFIFOW(fd, len + 6) = hd->homunculus.hskill[j].lv;
+ if ( hd->homunculus.hskill[j].lv ) {
+ WFIFOW(fd, len + 8) = skill->get_sp(id, hd->homunculus.hskill[j].lv);
+ WFIFOW(fd, len + 10) = skill->get_range2(&sd->hd->bl, id, hd->homunculus.hskill[j].lv);
+ } else {
+ WFIFOW(fd, len + 8) = 0;
+ WFIFOW(fd, len + 10) = 0;
+ }
+ safestrncpy((char*)WFIFOP(fd, len + 12), skill->get_name(id), NAME_LENGTH);
+ WFIFOB(fd, len + 36) = (hd->homunculus.hskill[j].lv < homun->skill_tree_get_max(id, hd->homunculus.class_)) ? 1 : 0;
+ len += 37;
}
}
WFIFOW(fd,2)=len;
@@ -2292,15 +2298,7 @@ void clif_dropitem(struct map_session_data *sd,int n,int amount)
/// Notifies the client, that an inventory item was deleted (ZC_DELETE_ITEM_FROM_BODY).
/// 07fa <delete type>.W <index>.W <amount>.W
-/// delete type:
-/// 0 = Normal
-/// 1 = Item used for a skill
-/// 2 = Refine failed
-/// 3 = Material changed
-/// 4 = Moved to storage
-/// 5 = Moved to cart
-/// 6 = Item sold
-/// 7 = Consumed by Four Spirit Analysis (SO_EL_ANALYSIS) skill
+/// delete type: @see enum delitem_reason
void clif_delitem(struct map_session_data *sd,int n,int amount, short reason)
{
#if PACKETVER < 20091117
@@ -2976,6 +2974,9 @@ void clif_changelook(struct block_list *bl,int type,int val)
case LOOK_BASE:
if( !sd ) break;
+ if ( val == INVISIBLE_CLASS ) /* nothing to change look */
+ return;
+
if( sd->sc.option&OPTION_COSTUME )
vd->weapon = vd->shield = 0;
@@ -3226,14 +3227,14 @@ void clif_arrow_create_list(struct map_session_data *sd)
for (i = 0, c = 0; i < MAX_SKILL_ARROW_DB; i++) {
int j;
- if (skill->arrow_db[i].nameid > 0
- && (j = pc->search_inventory(sd, skill->arrow_db[i].nameid)) != INDEX_NOT_FOUND
+ if (skill->dbs->arrow_db[i].nameid > 0
+ && (j = pc->search_inventory(sd, skill->dbs->arrow_db[i].nameid)) != INDEX_NOT_FOUND
&& !sd->status.inventory[j].equip && sd->status.inventory[j].identify
) {
- if ((j = itemdb_viewid(skill->arrow_db[i].nameid)) > 0)
+ if ((j = itemdb_viewid(skill->dbs->arrow_db[i].nameid)) > 0)
WFIFOW(fd,c*2+4) = j;
else
- WFIFOW(fd,c*2+4) = skill->arrow_db[i].nameid;
+ WFIFOW(fd,c*2+4) = skill->dbs->arrow_db[i].nameid;
c++;
}
}
@@ -3459,6 +3460,7 @@ void clif_useitemack(struct map_session_data *sd,int index,int amount,bool ok)
/// 0 = Room has been successfully created (opens chat room)
/// 1 = Room limit exceeded
/// 2 = Same room already exists
+// TODO: Flag enum
void clif_createchat(struct map_session_data* sd, int flag)
{
int fd;
@@ -4003,7 +4005,7 @@ void clif_getareachar_pc(struct map_session_data* sd,struct map_session_data* ds
clif->charm_single(sd->fd, dstsd);
for( i = 0; i < dstsd->sc_display_count; i++ ) {
- clif->sc_load(&sd->bl,dstsd->bl.id,SELF,status->IconChangeTable[dstsd->sc_display[i]->type],dstsd->sc_display[i]->val1,dstsd->sc_display[i]->val2,dstsd->sc_display[i]->val3);
+ clif->sc_load(&sd->bl,dstsd->bl.id,SELF,status->dbs->IconChangeTable[dstsd->sc_display[i]->type],dstsd->sc_display[i]->val1,dstsd->sc_display[i]->val2,dstsd->sc_display[i]->val3);
}
if( (sd->status.party_id && dstsd->status.party_id == sd->status.party_id) || //Party-mate, or hpdisp setting.
(sd->bg_id && sd->bg_id == dstsd->bg_id) || //BattleGround
@@ -4012,11 +4014,11 @@ void clif_getareachar_pc(struct map_session_data* sd,struct map_session_data* ds
clif->hpmeter_single(sd->fd, dstsd->bl.id, dstsd->battle_status.hp, dstsd->battle_status.max_hp);
// display link (sd - dstsd) to sd
- ARR_FIND( 0, 5, i, sd->devotion[i] == dstsd->bl.id );
- if( i < 5 ) clif->devotion(&sd->bl, sd);
+ ARR_FIND( 0, MAX_PC_DEVOTION, i, sd->devotion[i] == dstsd->bl.id );
+ if( i < MAX_PC_DEVOTION ) clif->devotion(&sd->bl, sd);
// display links (dstsd - devotees) to sd
- ARR_FIND( 0, 5, i, dstsd->devotion[i] > 0 );
- if( i < 5 ) clif->devotion(&dstsd->bl, sd);
+ ARR_FIND( 0, MAX_PC_DEVOTION, i, dstsd->devotion[i] > 0 );
+ if( i < MAX_PC_DEVOTION ) clif->devotion(&dstsd->bl, sd);
// display link (dstsd - crusader) to sd
if( dstsd->sc.data[SC_DEVOTION] && (d_bl = map->id2bl(dstsd->sc.data[SC_DEVOTION]->val1)) != NULL )
clif->devotion(d_bl, sd);
@@ -4131,20 +4133,8 @@ int clif_calc_walkdelay(struct block_list *bl,int delay, int type, int damage, i
/// Sends a 'damage' packet (src performs action on dst)
/// 008a <src ID>.L <dst ID>.L <server tick>.L <src speed>.L <dst speed>.L <damage>.W <div>.W <type>.B <damage2>.W (ZC_NOTIFY_ACT)
/// 02e1 <src ID>.L <dst ID>.L <server tick>.L <src speed>.L <dst speed>.L <damage>.L <div>.W <type>.B <damage2>.L (ZC_NOTIFY_ACT2)
-/// type:
-/// 0 = damage [ damage: total damage, div: amount of hits, damage2: assassin dual-wield damage ]
-/// 1 = pick up item
-/// 2 = sit down
-/// 3 = stand up
-/// 4 = damage (endure)
-/// 5 = (splash?)
-/// 6 = (skill?)
-/// 7 = (repeat damage?)
-/// 8 = multi-hit damage
-/// 9 = multi-hit damage (endure)
-/// 10 = critical hit
-/// 11 = lucky dodge
-/// 12 = (touch skill?)
+/// type: @see enum battle_dmg_type
+/// for BDT_NORMAL: [ damage: total damage, div: amount of hits, damage2: assassin dual-wield damage ]
int clif_damage(struct block_list* src, struct block_list* dst, int sdelay, int ddelay, int64 in_damage, short div, unsigned char type, int64 in_damage2) {
struct packet_damage p;
struct status_change *sc;
@@ -4222,7 +4212,7 @@ int clif_damage(struct block_list* src, struct block_list* dst, int sdelay, int
*------------------------------------------*/
void clif_takeitem(struct block_list* src, struct block_list* dst)
{
- //clif->damage(src,dst,0,0,0,0,1,0);
+ //clif->damage(src,dst,0,0,0,0,BDT_PICKUP,0);
unsigned char buf[32];
nullpo_retv(src);
@@ -4576,15 +4566,23 @@ void clif_skillinfoblock(struct map_session_data *sd)
WFIFOW(fd,0) = 0x10f;
for ( i = 0, len = 4; i < MAX_SKILL; i++) {
if( (id = sd->status.skill[i].id) != 0 ) {
+ int level;
// workaround for bugreport:5348
if (len + 37 > 8192)
break;
- WFIFOW(fd,len) = id;
- WFIFOL(fd,len+2) = skill->get_inf(id);
- WFIFOW(fd,len+6) = sd->status.skill[i].lv;
- WFIFOW(fd,len+8) = skill->get_sp(id,sd->status.skill[i].lv);
- WFIFOW(fd,len+10)= skill->get_range2(&sd->bl, id,sd->status.skill[i].lv);
+ WFIFOW(fd, len) = id;
+ WFIFOL(fd, len + 2) = skill->get_inf(id);
+ level = sd->status.skill[i].lv;
+ WFIFOW(fd, len + 6) = level;
+ if (level) {
+ WFIFOW(fd, len + 8) = skill->get_sp(id, level);
+ WFIFOW(fd, len + 10)= skill->get_range2(&sd->bl, id, level);
+ }
+ else {
+ WFIFOW(fd, len + 8) = 0;
+ WFIFOW(fd, len + 10)= 0;
+ }
safestrncpy((char*)WFIFOP(fd,len+12), skill->get_name(id), NAME_LENGTH);
if(sd->status.skill[i].flag == SKILL_FLAG_PERMANENT)
WFIFOB(fd,len+36) = (sd->status.skill[i].lv < skill->tree_get_max(id, sd->status.class_))? 1:0;
@@ -4612,26 +4610,33 @@ void clif_skillinfoblock(struct map_session_data *sd)
/// 0111 <skill id>.W <type>.L <level>.W <sp cost>.W <attack range>.W <skill name>.24B <upgradable>.B
void clif_addskill(struct map_session_data *sd, int id)
{
- int fd, idx = skill->get_index(id);
+ int fd, skill_lv, idx = skill->get_index(id);
nullpo_retv(sd);
fd = sd->fd;
if (!fd) return;
- if( sd->status.skill[idx].id <= 0 )
+ if (sd->status.skill[idx].id <= 0)
return;
+ skill_lv = sd->status.skill[idx].lv;
+
WFIFOHEAD(fd, packet_len(0x111));
WFIFOW(fd,0) = 0x111;
WFIFOW(fd,2) = id;
WFIFOL(fd,4) = skill->get_inf(id);
- WFIFOW(fd,8) = sd->status.skill[idx].lv;
- WFIFOW(fd,10) = skill->get_sp(id,sd->status.skill[idx].lv);
- WFIFOW(fd,12)= skill->get_range2(&sd->bl, id,sd->status.skill[idx].lv);
+ WFIFOW(fd,8) = skill_lv;
+ if (skill_lv > 0) {
+ WFIFOW(fd,10) = skill->get_sp(id, skill_lv);
+ WFIFOW(fd,12) = skill->get_range2(&sd->bl, id, skill_lv);
+ } else {
+ WFIFOW(fd,10) = 0;
+ WFIFOW(fd,12) = 0;
+ }
safestrncpy((char*)WFIFOP(fd,14), skill->get_name(id), NAME_LENGTH);
- if( sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT )
- WFIFOB(fd,38) = (sd->status.skill[idx].lv < skill->tree_get_max(id, sd->status.class_))? 1:0;
+ if (sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT)
+ WFIFOB(fd,38) = (skill_lv < skill->tree_get_max(id, sd->status.class_))? 1:0;
else
WFIFOB(fd,38) = 0;
WFIFOSET(fd,packet_len(0x111));
@@ -4691,16 +4696,22 @@ void clif_skillinfo(struct map_session_data *sd,int skill_id, int inf)
{
const int fd = sd->fd;
int idx = skill->get_index(skill_id);
+ int skill_lv = sd->status.skill[idx].lv;
WFIFOHEAD(fd,packet_len(0x7e1));
WFIFOW(fd,0) = 0x7e1;
WFIFOW(fd,2) = skill_id;
WFIFOL(fd,4) = inf?inf:skill->get_inf(skill_id);
- WFIFOW(fd,8) = sd->status.skill[idx].lv;
- WFIFOW(fd,10) = skill->get_sp(skill_id,sd->status.skill[idx].lv);
- WFIFOW(fd,12) = skill->get_range2(&sd->bl,skill_id,sd->status.skill[idx].lv);
- if( sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT )
- WFIFOB(fd,14) = (sd->status.skill[idx].lv < skill->tree_get_max(skill_id, sd->status.class_))? 1:0;
+ WFIFOW(fd,8) = skill_lv;
+ if (skill_lv > 0) {
+ WFIFOW(fd,10) = skill->get_sp(skill_id, skill_lv);
+ WFIFOW(fd,12) = skill->get_range2(&sd->bl, skill_id, skill_lv);
+ } else {
+ WFIFOW(fd,10) = 0;
+ WFIFOW(fd,12) = 0;
+ }
+ if (sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT)
+ WFIFOB(fd,14) = (skill_lv < skill->tree_get_max(skill_id, sd->status.class_))? 1:0;
else
WFIFOB(fd,14) = 0;
WFIFOSET(fd,packet_len(0x7e1));
@@ -5179,13 +5190,13 @@ void clif_skill_produce_mix_list(struct map_session_data *sd, int skill_id , int
WFIFOW(fd, 0)=0x18d;
for(i=0,c=0;i<MAX_SKILL_PRODUCE_DB;i++){
- if( skill->can_produce_mix(sd,skill->produce_db[i].nameid, trigger, 1) &&
- ( ( skill_id > 0 && skill->produce_db[i].req_skill == skill_id ) || skill_id < 0 )
+ if( skill->can_produce_mix(sd,skill->dbs->produce_db[i].nameid, trigger, 1) &&
+ ( ( skill_id > 0 && skill->dbs->produce_db[i].req_skill == skill_id ) || skill_id < 0 )
){
- if((view = itemdb_viewid(skill->produce_db[i].nameid)) > 0)
+ if((view = itemdb_viewid(skill->dbs->produce_db[i].nameid)) > 0)
WFIFOW(fd,c*8+ 4)= view;
else
- WFIFOW(fd,c*8+ 4)= skill->produce_db[i].nameid;
+ WFIFOW(fd,c*8+ 4)= skill->dbs->produce_db[i].nameid;
WFIFOW(fd,c*8+ 6)= 0;
WFIFOW(fd,c*8+ 8)= 0;
WFIFOW(fd,c*8+10)= 0;
@@ -5226,13 +5237,13 @@ void clif_cooking_list(struct map_session_data *sd, int trigger, uint16 skill_id
c = 0;
for( i = 0; i < MAX_SKILL_PRODUCE_DB; i++ ) {
- if( !skill->can_produce_mix(sd,skill->produce_db[i].nameid,trigger, qty) )
+ if( !skill->can_produce_mix(sd,skill->dbs->produce_db[i].nameid,trigger, qty) )
continue;
- if( (view = itemdb_viewid(skill->produce_db[i].nameid)) > 0 )
+ if( (view = itemdb_viewid(skill->dbs->produce_db[i].nameid)) > 0 )
WFIFOW(fd, 6 + 2 * c) = view;
else
- WFIFOW(fd, 6 + 2 * c) = skill->produce_db[i].nameid;
+ WFIFOW(fd, 6 + 2 * c) = skill->dbs->produce_db[i].nameid;
c++;
}
@@ -5256,7 +5267,7 @@ void clif_cooking_list(struct map_session_data *sd, int trigger, uint16 skill_id
if( skill_id != AM_PHARMACY ) { // AM_PHARMACY is used to Cooking.
// It fails.
#if PACKETVER >= 20090922
- clif->msg_skill(sd,skill_id,0x625);
+ clif->msgtable_skill(sd, skill_id, MSG_COOKING_LIST_FAIL);
#else
WFIFOW(fd,2) = 6 + 2 * c;
WFIFOSET(fd,WFIFOW(fd,2));
@@ -5338,7 +5349,7 @@ void clif_displaymessage(const int fd, const char* mes) {
#if PACKETVER == 20141022
/** for some reason game client crashes depending on message pattern (only for this packet) **/
/** so we redirect to ZC_NPC_CHAT **/
- clif->colormes(fd,COLOR_DEFAULT,mes);
+ clif->messagecolor_self(fd, COLOR_DEFAULT, mes);
#else
size_t len;
@@ -5558,6 +5569,7 @@ void clif_map_type(struct map_session_data* sd, enum map_type type) {
/// Updates PvP ranking (ZC_NOTIFY_RANKING).
/// 019a <id>.L <ranking>.L <total>.L
+// FIXME: missing documentation for the 'type' parameter
void clif_pvpset(struct map_session_data *sd,int pvprank,int pvpnum,int type)
{
if(type == 2) {
@@ -5703,54 +5715,30 @@ void clif_solved_charname(int fd, int charid, const char* name)
/// 017b <packet len>.W { <name id>.W }*
void clif_use_card(struct map_session_data *sd,int idx)
{
- int i,c,ep;
- int fd=sd->fd;
+ int i, c;
+ int fd;
nullpo_retv(sd);
- if (idx < 0 || idx >= MAX_INVENTORY) //Crash-fix from bad packets.
+ fd = sd->fd;
+ if (sd->state.trading != 0)
+ return;
+ if (!pc->can_insert_card(sd, idx))
return;
- if (!sd->inventory_data[idx] || sd->inventory_data[idx]->type != IT_CARD)
- return; //Avoid parsing invalid item indexes (no card/no item)
-
- ep=sd->inventory_data[idx]->equip;
- WFIFOHEAD(fd,MAX_INVENTORY * 2 + 4);
- WFIFOW(fd,0)=0x17b;
-
- for(i=c=0;i<MAX_INVENTORY;i++){
- int j;
-
- if(sd->inventory_data[i] == NULL)
- continue;
- if(sd->inventory_data[i]->type!=IT_WEAPON && sd->inventory_data[i]->type!=IT_ARMOR)
- continue;
- if(itemdb_isspecial(sd->status.inventory[i].card[0])) //Can't slot it
- continue;
-
- if (sd->status.inventory[i].identify == 0) //Not identified
- continue;
-
- if ((sd->inventory_data[i]->equip&ep) == 0) //Not equippable on this part.
- continue;
-
- if(sd->inventory_data[i]->type==IT_WEAPON && ep==EQP_SHIELD) //Shield card won't go on left weapon.
- continue;
-
- ARR_FIND( 0, sd->inventory_data[i]->slot, j, sd->status.inventory[i].card[j] == 0 );
- if (j == sd->inventory_data[i]->slot) // No room
- continue;
+ WFIFOHEAD(fd, MAX_INVENTORY * 2 + 4);
+ WFIFOW(fd, 0) = 0x17b;
- if( sd->status.inventory[i].equip > 0 ) // Do not check items that are already equipped
+ for (i = c = 0; i < MAX_INVENTORY; i++) {
+ if (!pc->can_insert_card_into(sd, idx, i))
continue;
-
- WFIFOW(fd,4+c*2)=i+2;
+ WFIFOW(fd, 4 + c * 2) = i + 2;
c++;
}
- if( !c ) return; // no item is available for card insertion
+ if (!c) return; // no item is available for card insertion
- WFIFOW(fd,2)=4+c*2;
- WFIFOSET(fd,WFIFOW(fd,2));
+ WFIFOW(fd, 2) = 4 + c * 2;
+ WFIFOSET(fd, WFIFOW(fd, 2));
}
@@ -6183,6 +6171,14 @@ void clif_openvending(struct map_session_data* sd, int id, struct s_vending* ven
clif->addcards(WFIFOP(fd,22+i*22), &sd->status.cart[index]);
}
WFIFOSET(fd,WFIFOW(fd,2));
+
+#if PACKETVER >= 20141022
+ /** should go elsewhere perhaps? it has to be bundled with this however. **/
+ WFIFOHEAD(fd, 3);
+ WFIFOW(fd, 0) = 0xa28;
+ WFIFOB(fd, 2) = 0;/** 1 is failure. our current responses to failure are working so not yet implemented **/
+ WFIFOSET(fd, 3);
+#endif
}
@@ -6877,7 +6873,7 @@ void clif_devotion(struct block_list *src, struct map_session_data *tsd)
if( sd == NULL )
return;
- for( i = 0; i < 5; i++ )
+ for( i = 0; i < MAX_PC_DEVOTION; i++ )
WBUFL(buf,6+4*i) = sd->devotion[i];
WBUFW(buf,26) = skill->get_range2(src, CR_DEVOTION, pc->checkskill(sd, CR_DEVOTION));
}
@@ -7034,9 +7030,7 @@ void clif_guild_created(struct map_session_data *sd,int flag)
/// Notifies the client that it is belonging to a guild (ZC_UPDATE_GDID).
/// 016c <guild id>.L <emblem id>.L <mode>.L <ismaster>.B <inter sid>.L <guild name>.24B
-/// mode:
-/// &0x01 = allow invite
-/// &0x10 = allow expel
+/// mode: @see enum guild_permission
void clif_guild_belonginfo(struct map_session_data *sd, struct guild *g)
{
int ps,fd;
@@ -7286,9 +7280,7 @@ void clif_guild_positionnamelist(struct map_session_data *sd) {
/// Guild position information (ZC_POSITION_INFO).
/// 0160 <packet len>.W { <position id>.L <mode>.L <ranking>.L <pay rate>.L }*
-/// mode:
-/// &0x01 = allow invite
-/// &0x10 = allow expel
+/// mode: @see enum guild_permission
/// ranking:
/// TODO
void clif_guild_positioninfolist(struct map_session_data *sd) {
@@ -7316,9 +7308,7 @@ void clif_guild_positioninfolist(struct map_session_data *sd) {
/// Notifies clients in a guild about updated position information (ZC_ACK_CHANGE_GUILD_POSITIONINFO).
/// 0174 <packet len>.W { <position id>.L <mode>.L <ranking>.L <pay rate>.L <position name>.24B }*
-/// mode:
-/// &0x01 = allow invite
-/// &0x10 = allow expel
+/// mode: @see enum guild_permission
/// ranking:
/// TODO
void clif_guild_positionchanged(struct guild *g,int idx)
@@ -7432,8 +7422,13 @@ void clif_guild_skillinfo(struct map_session_data* sd)
WFIFOW(fd,p+0) = id;
WFIFOL(fd,p+2) = skill->get_inf(id);
WFIFOW(fd,p+6) = g->skill[i].lv;
- WFIFOW(fd,p+8) = skill->get_sp(id, g->skill[i].lv);
- WFIFOW(fd,p+10) = skill->get_range(id, g->skill[i].lv);
+ if ( g->skill[i].lv ) {
+ WFIFOW(fd, p + 8) = skill->get_sp(id, g->skill[i].lv);
+ WFIFOW(fd, p + 10) = skill->get_range(id, g->skill[i].lv);
+ } else {
+ WFIFOW(fd, p + 8) = 0;
+ WFIFOW(fd, p + 10) = 0;
+ }
safestrncpy((char*)WFIFOP(fd,p+12), skill->get_name(id), NAME_LENGTH);
WFIFOB(fd,p+36)= (g->skill[i].lv < guild->skill_get_max(id) && sd == g->member[0].sd) ? 1 : 0;
c++;
@@ -8107,28 +8102,41 @@ void clif_specialeffect_value(struct block_list* bl, int effect_id, int num, sen
clif->send(buf, packet_len(0x284), bl, SELF);
}
}
-// Modification of clif_messagecolor to send colored messages to players to chat log only (doesn't display overhead)
-/// 02c1 <packet len>.W <id>.L <color>.L <message>.?B
-int clif_colormes(int fd, enum clif_colors color, const char* msg) {
+/**
+ * Modification of clif_messagecolor to send colored messages to players to chat log only (doesn't display overhead).
+ *
+ * 02c1 <packet len>.W <id>.L <color>.L <message>.?B
+ *
+ * @param fd Target fd to send the message to
+ * @param color Message color (RGB format: 0xRRGGBB)
+ * @param msg Message text
+ */
+void clif_messagecolor_self(int fd, uint32 color, const char *msg)
+{
size_t msg_len = strlen(msg) + 1;
WFIFOHEAD(fd,msg_len + 12);
WFIFOW(fd,0) = 0x2C1;
WFIFOW(fd,2) = msg_len + 12;
WFIFOL(fd,4) = 0;
- WFIFOL(fd,8) = color_table[color];
+ WFIFOL(fd,8) = RGB2BGR(color);
safestrncpy((char*)WFIFOP(fd,12), msg, msg_len);
WFIFOSET(fd, msg_len + 12);
-
- return 0;
}
-/// Monster/NPC color chat [SnakeDrak] (ZC_NPC_CHAT).
-/// 02c1 <packet len>.W <id>.L <color>.L <message>.?B
-void clif_messagecolor(struct block_list* bl, unsigned int color, const char* msg) {
+/**
+ * Monster/NPC color chat [SnakeDrak] (ZC_NPC_CHAT).
+ *
+ * 02c1 <packet len>.W <id>.L <color>.L <message>.?B
+ *
+ * @param bl Source block list.
+ * @param color Message color (RGB format: 0xRRGGBB)
+ * @param msg Message text
+ */
+void clif_messagecolor(struct block_list* bl, uint32 color, const char *msg)
+{
size_t msg_len = strlen(msg) + 1;
uint8 buf[256];
- color = (color & 0x0000FF) << 16 | (color & 0x00FF00) | (color & 0xFF0000) >> 16; // RGB to BGR
nullpo_retv(bl);
@@ -8140,48 +8148,29 @@ void clif_messagecolor(struct block_list* bl, unsigned int color, const char* ms
WBUFW(buf,0) = 0x2C1;
WBUFW(buf,2) = msg_len + 12;
WBUFL(buf,4) = bl->id;
- WBUFL(buf,8) = color;
+ WBUFL(buf,8) = RGB2BGR(color);
memcpy(WBUFP(buf,12), msg, msg_len);
clif->send(buf, WBUFW(buf,2), bl, AREA_CHAT_WOC);
}
-/// Public chat message [Valaris] (ZC_NOTIFY_CHAT).
-/// 008d <packet len>.W <id>.L <message>.?B
-void clif_message(struct block_list* bl, const char* msg) {
- unsigned short msg_len = strlen(msg) + 1;
- uint8 buf[256];
- nullpo_retv(bl);
-
- if( msg_len > sizeof(buf)-8 ) {
- ShowWarning("clif_message: Truncating too long message '%s' (len=%u).\n", msg, msg_len);
- msg_len = sizeof(buf)-8;
- }
-
- WBUFW(buf,0) = 0x8d;
- WBUFW(buf,2) = msg_len + 8;
- WBUFL(buf,4) = bl->id;
- safestrncpy((char*)WBUFP(buf,8), msg, msg_len);
-
- clif->send(buf, WBUFW(buf,2), bl, AREA_CHAT_WOC);
-}
-
/**
* Notifies the client that the storage window is still open
*
* Should only be used in cases where the client closed the
* storage window without server's consent
**/
-void clif_refresh_storagewindow( struct map_session_data *sd ) {
+void clif_refresh_storagewindow(struct map_session_data *sd)
+{
// Notify the client that the storage is open
- if( sd->state.storage_flag == 1 ) {
+ if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) {
storage->sortitem(sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items));
clif->storagelist(sd, sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items));
clif->updatestorageamount(sd, sd->status.storage.storage_amount, MAX_STORAGE);
}
// Notify the client that the gstorage is open otherwise it will
// remain locked forever and nobody will be able to access it
- if( sd->state.storage_flag == 2 ) {
+ if (sd->state.storage_flag == STORAGE_FLAG_GUILD) {
struct guild_storage *gstor;
if( (gstor = idb_get(gstorage->db,sd->status.guild_id)) == NULL) {
// Shouldn't happen... The information should already be at the map-server
@@ -8231,7 +8220,7 @@ void clif_refresh(struct map_session_data *sd)
map->foreachinrange(clif->getareachar,&sd->bl,AREA_SIZE,BL_ALL,sd);
clif->weather_check(sd);
if( sd->chatID )
- chat->leave(sd,0);
+ chat->leave(sd, false);
if( sd->state.vending )
clif->openvending(sd, sd->bl.id, sd->vending);
if( pc_issit(sd) )
@@ -8712,9 +8701,15 @@ void clif_viewequip_ack(struct map_session_data* sd, struct map_session_data* ts
}
-/// Display msgstringtable.txt string (ZC_MSG).
-/// 0291 <message>.W
-void clif_msg(struct map_session_data* sd, unsigned short id)
+/**
+ * Displays a string from msgstringtable.txt (ZC_MSG).
+ *
+ * 0291 <msg id>.W
+ *
+ * @param sd The target character.
+ * @param msg_id msgstringtable message index, 0-based (@see enum clif_messages)
+ */
+void clif_msgtable(struct map_session_data* sd, unsigned short msg_id)
{
int fd;
nullpo_retv(sd);
@@ -8722,31 +8717,47 @@ void clif_msg(struct map_session_data* sd, unsigned short id)
WFIFOHEAD(fd, packet_len(0x291));
WFIFOW(fd, 0) = 0x291;
- WFIFOW(fd, 2) = id; // zero-based msgstringtable.txt index
+ WFIFOW(fd, 2) = msg_id; // zero-based msgstringtable.txt index
WFIFOSET(fd, packet_len(0x291));
}
-
-/// Display msgstringtable.txt string and fill in a valid for %d format (ZC_MSG_VALUE).
-/// 0x7e2 <message>.W <value>.L
-void clif_msg_value(struct map_session_data* sd, unsigned short id, int value)
+/**
+ * Displays a format string from msgstringtable.txt with a %d value (ZC_MSG_VALUE).
+ *
+ * 0x7e2 <msg id>.W <value>.L
+ *
+ * @param sd The target character.
+ * @param msg_id msgstringtable message index, 0-based (@see enum clif_messages)
+ * @param value The value to fill %d.
+ */
+void clif_msgtable_num(struct map_session_data *sd, unsigned short msg_id, int value)
{
- int fd = sd->fd;
+#if PACKETVER >= 20090805
+ int fd;
+ nullpo_retv(sd);
+ fd = sd->fd;
WFIFOHEAD(fd, packet_len(0x7e2));
- WFIFOW(fd,0) = 0x7e2;
- WFIFOW(fd,2) = id;
- WFIFOL(fd,4) = value;
+ WFIFOW(fd, 0) = 0x7e2;
+ WFIFOW(fd, 2) = msg_id;
+ WFIFOL(fd, 4) = value;
WFIFOSET(fd, packet_len(0x7e2));
+#endif
}
-
-/// Displays msgstringtable.txt string, prefixed with a skill name. (ZC_MSG_SKILL).
-/// 07e6 <skill id>.W <msg id>.L
-///
-/// NOTE: Message has following format and is printed in color 0xCDCDFF (purple):
-/// "[SkillName] Message"
-void clif_msg_skill(struct map_session_data* sd, uint16 skill_id, int msg_id)
+/**
+ * Displays a string from msgstringtable.txt, prefixed with a skill name (ZC_MSG_SKILL).
+ *
+ * 07e6 <skill id>.W <msg id>.L
+ *
+ * NOTE: Message has following format and is printed in color 0xCDCDFF (purple):
+ * "[SkillName] Message"
+ *
+ * @param sd The target character.
+ * @param skill_id ID of the skill to display.
+ * @param msg_id msgstringtable message index, 0-based (@see enum clif_messages)
+ */
+void clif_msgtable_skill(struct map_session_data* sd, uint16 skill_id, int msg_id)
{
int fd = sd->fd;
@@ -8857,12 +8868,13 @@ void clif_channel_msg(struct channel_data *chan, struct map_session_data *sd, ch
DBIterator *iter = db_iterator(chan->users);
struct map_session_data *user;
unsigned short msg_len = strlen(msg) + 1;
+ uint32 color = channel->config->colors[chan->color];
WFIFOHEAD(sd->fd,msg_len + 12);
WFIFOW(sd->fd,0) = 0x2C1;
WFIFOW(sd->fd,2) = msg_len + 12;
WFIFOL(sd->fd,4) = 0;
- WFIFOL(sd->fd,8) = channel->config->colors[chan->color];
+ WFIFOL(sd->fd,8) = RGB2BGR(color);
safestrncpy((char*)WFIFOP(sd->fd,12), msg, msg_len);
for (user = dbi_first(iter); dbi_exists(iter); user = dbi_next(iter)) {
@@ -8884,11 +8896,12 @@ void clif_channel_msg2(struct channel_data *chan, char *msg)
struct map_session_data *user;
unsigned char buf[210];
unsigned short msg_len = strlen(msg) + 1;
+ uint32 color = channel->config->colors[chan->color];
WBUFW(buf,0) = 0x2C1;
WBUFW(buf,2) = msg_len + 12;
WBUFL(buf,4) = 0;
- WBUFL(buf,8) = channel->config->colors[chan->color];
+ WBUFL(buf,8) = RGB2BGR(color);
safestrncpy((char*)WBUFP(buf,12), msg, msg_len);
for (user = dbi_first(iter); dbi_exists(iter); user = dbi_next(iter)) {
@@ -8984,9 +8997,6 @@ void clif_parse_WantToConnection(int fd, struct map_session_data* sd) {
/// Notification from the client, that it has finished map loading and is about to display player's character (CZ_NOTIFY_ACTORINIT).
/// 007d
void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) {
-#if PACKETVER >= 20090218
- int i;
-#endif
bool first_time = false;
if(sd->bl.prev != NULL)
@@ -9171,10 +9181,13 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) {
//Auron reported that This skill only triggers when you logon on the map o.O [Skotlex]
if ((lv = pc->checkskill(sd,SG_KNOWLEDGE)) > 0) {
- if(sd->bl.m == sd->feel_map[0].m
- || sd->bl.m == sd->feel_map[1].m
- || sd->bl.m == sd->feel_map[2].m)
- sc_start(NULL,&sd->bl, SC_KNOWLEDGE, 100, lv, skill->get_time(SG_KNOWLEDGE, lv));
+ int i;
+ for (i = 0; i < MAX_PC_FEELHATE; i++) {
+ if (sd->bl.m == sd->feel_map[i].m) {
+ sc_start(NULL,&sd->bl, SC_KNOWLEDGE, 100, lv, skill->get_time(SG_KNOWLEDGE, lv));
+ break;
+ }
+ }
}
if(sd->pd && sd->pd->pet.intimate > 900)
@@ -9202,14 +9215,16 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) {
clif->updatestatus(sd,SP_DEX);
clif->updatestatus(sd,SP_LUK);
- // abort currently running script
- sd->state.using_fake_npc = 0;
- sd->state.menu_or_input = 0;
- sd->npc_menu = 0;
-
- if(sd->npc_id)
- npc->event_dequeue(sd);
-
+ if (sd->state.warp_clean) {
+ // abort currently running script
+ sd->state.using_fake_npc = 0;
+ sd->state.menu_or_input = 0;
+ sd->npc_menu = 0;
+ if(sd->npc_id)
+ npc->event_dequeue(sd);
+ } else {
+ sd->state.warp_clean = 1;
+ }
if( sd->guild && ( battle_config.guild_notice_changemap == 2 || ( battle_config.guild_notice_changemap == 1 && sd->state.changemap ) ) )
clif->guild_notice(sd,sd->guild);
}
@@ -9254,6 +9269,9 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) {
if (channel->config->local && channel->config->local_autojoin) {
channel->map_join(sd);
}
+ if (channel->config->irc && channel->config->irc_autojoin) {
+ channel->irc_join(sd);
+ }
}
mail->clear(sd);
@@ -9317,14 +9335,17 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) {
// NPC Quest / Event Icon Check [Kisuka]
#if PACKETVER >= 20090218
- for(i = 0; i < map->list[sd->bl.m].qi_count; i++) {
- struct questinfo *qi = &map->list[sd->bl.m].qi_data[i];
- if( quest->check(sd, qi->quest_id, HAVEQUEST) == -1 ) {// Check if quest is not started
- if( qi->hasJob ) { // Check if quest is job-specific, check is user is said job class.
- if( sd->class_ == qi->job )
+ {
+ int i;
+ for(i = 0; i < map->list[sd->bl.m].qi_count; i++) {
+ struct questinfo *qi = &map->list[sd->bl.m].qi_data[i];
+ if( quest->check(sd, qi->quest_id, HAVEQUEST) == -1 ) {// Check if quest is not started
+ if( qi->hasJob ) { // Check if quest is job-specific, check is user is said job class.
+ if( sd->class_ == qi->job )
+ clif->quest_show_event(sd, &qi->nd->bl, qi->icon, qi->color);
+ } else {
clif->quest_show_event(sd, &qi->nd->bl, qi->icon, qi->color);
- } else {
- clif->quest_show_event(sd, &qi->nd->bl, qi->icon, qi->color);
+ }
}
}
}
@@ -9633,6 +9654,7 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd)
} else if ( sd->fontcolor && !sd->chatID ) {
char mout[200];
unsigned char mylen = 1;
+ uint32 color = 0;
if( sd->disguise == -1 ) {
sd->fontcolor_tid = timer->add(timer->gettick()+5000, clif->undisguise_timer, sd->bl.id, 0);
@@ -9650,11 +9672,12 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd)
mylen += snprintf(mout, 200, "%s : %s",sd->fakename[0]?sd->fakename:sd->status.name,message);
+ color = channel->config->colors[sd->fontcolor - 1];
WFIFOHEAD(fd,mylen + 12);
WFIFOW(fd,0) = 0x2C1;
WFIFOW(fd,2) = mylen + 12;
WFIFOL(fd,4) = sd->bl.id;
- WFIFOL(fd,8) = channel->config->colors[sd->fontcolor - 1];
+ WFIFOL(fd,8) = RGB2BGR(color);
safestrncpy((char*)WFIFOP(fd,12), mout, mylen);
clif->send(WFIFOP(fd,0), WFIFOW(fd,2), &sd->bl, AREA_WOS);
WFIFOL(fd,4) = -sd->bl.id;
@@ -9841,7 +9864,7 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
return;
if(action_type != 0x00 && action_type != 0x07)
- pc_stop_walking(sd, 1);
+ pc_stop_walking(sd, STOPWALKING_FLAG_FIXPOS);
pc_stop_attack(sd);
if(target_id<0 && -target_id == sd->bl.id) // for disguises [Valaris]
@@ -10245,7 +10268,7 @@ void clif_parse_EquipItem(int fd,struct map_session_data *sd) {
if( sd->npc_id ) {
if ( !sd->npc_item_flag )
return;
- } else if ( sd->state.storage_flag || sd->sc.opt1 )
+ } else if (sd->state.storage_flag != STORAGE_FLAG_CLOSED || sd->sc.opt1)
; //You can equip/unequip stuff while storage is open/under status changes
else if ( pc_cant_act2(sd) || sd->state.prerefining )
return;
@@ -10287,7 +10310,7 @@ void clif_parse_UnequipItem(int fd,struct map_session_data *sd)
if( sd->npc_id ) {
if ( !sd->npc_item_flag )
return;
- } else if ( sd->state.storage_flag || sd->sc.opt1 )
+ } else if (sd->state.storage_flag != STORAGE_FLAG_CLOSED || sd->sc.opt1)
; //You can equip/unequip stuff while storage is open/under status changes
else if ( pc_cant_act2(sd) || sd->state.prerefining )
return;
@@ -10297,7 +10320,7 @@ void clif_parse_UnequipItem(int fd,struct map_session_data *sd)
if( battle_config.idletime_criteria & BCIDLE_USEITEM )
sd->idletime = sockt->last_tick;
- pc->unequipitem(sd,index,1);
+ pc->unequipitem(sd,index, PCUNEQUIPITEM_RECALC);
}
@@ -10315,7 +10338,7 @@ void clif_parse_NpcClicked(int fd,struct map_session_data *sd)
}
if( sd->npc_id || sd->state.workinprogress&2 ){
#ifdef RENEWAL
- clif->msg(sd, 0x783); // TODO look for the client date that has this message.
+ clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS); // TODO look for the client date that has this message.
#endif
return;
}
@@ -10330,7 +10353,7 @@ void clif_parse_NpcClicked(int fd,struct map_session_data *sd)
case BL_NPC:
if( sd->ud.skill_id < RK_ENCHANTBLADE && sd->ud.skilltimer != INVALID_TIMER ) {// TODO: should only work with none 3rd job skills
#ifdef RENEWAL
- clif->msg(sd, 0x783);
+ clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS);
#endif
break;
}
@@ -10525,7 +10548,7 @@ void clif_parse_KickFromChat(int fd,struct map_session_data *sd)
/// 00e3
void clif_parse_ChatLeave(int fd, struct map_session_data* sd)
{
- chat->leave(sd,0);
+ chat->leave(sd, false);
}
@@ -10682,7 +10705,7 @@ void clif_parse_ChangeCart(int fd,struct map_session_data *sd)
#ifdef RENEWAL
if( sd->npc_id || sd->state.workinprogress&1 ){
- clif->msg(sd, 0x783);
+ clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS);
return;
}
#endif
@@ -10872,7 +10895,7 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd)
if( sd->npc_id || sd->state.workinprogress&1 ){
#ifdef RENEWAL
- clif->msg(sd, 0x783); // TODO look for the client date that has this message.
+ clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS); // TODO look for the client date that has this message.
#endif
return;
}
@@ -10880,7 +10903,7 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd)
if( pc_cant_act(sd)
&& skill_id != RK_REFRESH
&& !(skill_id == SR_GENTLETOUCH_CURE && (sd->sc.opt1 == OPT1_STONE || sd->sc.opt1 == OPT1_FREEZE || sd->sc.opt1 == OPT1_STUN))
- && ( sd->state.storage_flag && !(tmp&INF_SELF_SKILL) ) // SELF skills can be used with the storage open, issue: 8027
+ && (sd->state.storage_flag != STORAGE_FLAG_CLOSED && !(tmp&INF_SELF_SKILL)) // SELF skills can be used with the storage open, issue: 8027
)
return;
@@ -10968,7 +10991,7 @@ void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uint16 ski
#ifdef RENEWAL
if( sd->state.workinprogress&1 ){
- clif->msg(sd, 0x783); // TODO look for the client date that has this message.
+ clif->msgtable(sd, MSG_NPC_WORK_IN_PROGRESS); // TODO look for the client date that has this message.
return;
}
#endif
@@ -11085,7 +11108,7 @@ void clif_parse_UseSkillMap(int fd, struct map_session_data* sd)
return;
// It is possible to use teleport with the storage window open issue:8027
- if( pc_cant_act(sd) && (!sd->state.storage_flag && skill_id != AL_TELEPORT) ) {
+ if (pc_cant_act(sd) && (sd->state.storage_flag == STORAGE_FLAG_CLOSED && skill_id != AL_TELEPORT)) {
clif_menuskill_clear(sd);
return;
}
@@ -11349,8 +11372,6 @@ void clif_parse_AutoSpell(int fd,struct map_session_data *sd)
/// 017a <card index>.W
void clif_parse_UseCard(int fd,struct map_session_data *sd)
{
- if (sd->state.trading != 0)
- return;
clif->use_card(sd,RFIFOW(fd,2)-2);
}
@@ -11359,8 +11380,6 @@ void clif_parse_UseCard(int fd,struct map_session_data *sd)
/// 017c <card index>.W <equip index>.W
void clif_parse_InsertCard(int fd,struct map_session_data *sd)
{
- if (sd->state.trading != 0)
- return;
pc->insert_card(sd,RFIFOW(fd,2)-2,RFIFOW(fd,4)-2);
}
@@ -11428,9 +11447,9 @@ void clif_parse_MoveToKafra(int fd, struct map_session_data *sd)
if (item_index < 0 || item_index >= MAX_INVENTORY || item_amount < 1)
return;
- if (sd->state.storage_flag == 1)
+ if (sd->state.storage_flag == STORAGE_FLAG_NORMAL)
storage->add(sd, item_index, item_amount);
- else if (sd->state.storage_flag == 2)
+ else if (sd->state.storage_flag == STORAGE_FLAG_GUILD)
gstorage->add(sd, item_index, item_amount);
}
@@ -11446,9 +11465,9 @@ void clif_parse_MoveFromKafra(int fd,struct map_session_data *sd)
item_index = RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[0])-1;
item_amount = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[1]);
- if (sd->state.storage_flag == 1)
+ if (sd->state.storage_flag == STORAGE_FLAG_NORMAL)
storage->get(sd, item_index, item_amount);
- else if(sd->state.storage_flag == 2)
+ else if(sd->state.storage_flag == STORAGE_FLAG_GUILD)
gstorage->get(sd, item_index, item_amount);
}
@@ -11462,9 +11481,9 @@ void clif_parse_MoveToKafraFromCart(int fd, struct map_session_data *sd)
if (!pc_iscarton(sd))
return;
- if (sd->state.storage_flag == 1)
+ if (sd->state.storage_flag == STORAGE_FLAG_NORMAL)
storage->addfromcart(sd, RFIFOW(fd,2) - 2, RFIFOL(fd,4));
- else if (sd->state.storage_flag == 2)
+ else if (sd->state.storage_flag == STORAGE_FLAG_GUILD)
gstorage->addfromcart(sd, RFIFOW(fd,2) - 2, RFIFOL(fd,4));
}
@@ -11478,9 +11497,9 @@ void clif_parse_MoveFromKafraToCart(int fd, struct map_session_data *sd)
if (!pc_iscarton(sd))
return;
- if (sd->state.storage_flag == 1)
+ if (sd->state.storage_flag == STORAGE_FLAG_NORMAL)
storage->gettocart(sd, RFIFOW(fd,2)-1, RFIFOL(fd,4));
- else if (sd->state.storage_flag == 2)
+ else if (sd->state.storage_flag == STORAGE_FLAG_GUILD)
gstorage->gettocart(sd, RFIFOW(fd,2)-1, RFIFOL(fd,4));
}
@@ -11489,9 +11508,9 @@ void clif_parse_MoveFromKafraToCart(int fd, struct map_session_data *sd)
/// 00f7
void clif_parse_CloseKafra(int fd, struct map_session_data *sd)
{
- if( sd->state.storage_flag == 1 )
+ if( sd->state.storage_flag == STORAGE_FLAG_NORMAL )
storage->close(sd);
- else if( sd->state.storage_flag == 2 )
+ else if( sd->state.storage_flag == STORAGE_FLAG_GUILD )
gstorage->close(sd);
}
@@ -12701,7 +12720,7 @@ bool clif_sub_guild_invite(int fd, struct map_session_data *sd, struct map_sessi
return false;
}
- if ( t_sd && t_sd->state.noask ) {// @noask [LuzZza]
+ if (t_sd->state.noask) {// @noask [LuzZza]
clif->noask_sub(sd, t_sd, 2);
return false;
}
@@ -14142,7 +14161,7 @@ void clif_parse_AutoRevive(int fd, struct map_session_data *sd) {
if (item_position == INDEX_NOT_FOUND)
status_change_end(&sd->bl,SC_LIGHT_OF_REGENE,INVALID_TIMER);
else
- pc->delitem(sd, item_position, 1, 0, 1, LOG_TYPE_CONSUME);
+ pc->delitem(sd, item_position, 1, 0, DELITEM_SKILLUSE, LOG_TYPE_CONSUME);
clif->skill_nodamage(&sd->bl,&sd->bl,ALL_RESURRECTION,4,1);
}
@@ -14672,7 +14691,7 @@ void clif_Auction_openwindow(struct map_session_data *sd)
{
int fd = sd->fd;
- if( sd->state.storage_flag || sd->state.vending || sd->state.buyingstore || sd->state.trading )
+ if (sd->state.storage_flag != STORAGE_FLAG_CLOSED || sd->state.vending || sd->state.buyingstore || sd->state.trading)
return;
if( !battle_config.feature_auction )
@@ -14918,7 +14937,7 @@ void clif_parse_Auction_register(int fd, struct map_session_data *sd)
{
int zeny = auction.hours*battle_config.auction_feeperhour;
- pc->delitem(sd, sd->auction.index, sd->auction.amount, 1, 6, LOG_TYPE_AUCTION);
+ pc->delitem(sd, sd->auction.index, sd->auction.amount, 1, DELITEM_SOLD, LOG_TYPE_AUCTION);
sd->auction.amount = 0;
pc->payzeny(sd, zeny, LOG_TYPE_AUCTION, NULL);
@@ -15269,7 +15288,7 @@ void clif_parse_ViewPlayerEquip(int fd, struct map_session_data* sd) {
if( tsd->status.show_equip || pc_has_permission(sd, PC_PERM_VIEW_EQUIPMENT) )
clif->viewequip_ack(sd, tsd);
else
- clif_viewequip_fail(sd);
+ clif->msgtable(sd, MSG_EQUIP_NOT_PUBLIC);
}
@@ -15632,8 +15651,13 @@ void clif_mercenary_skillblock(struct map_session_data *sd)
WFIFOW(fd,len) = id;
WFIFOL(fd,len+2) = skill->get_inf(id);
WFIFOW(fd,len+6) = md->db->skill[j].lv;
- WFIFOW(fd,len+8) = skill->get_sp(id, md->db->skill[j].lv);
- WFIFOW(fd,len+10) = skill->get_range2(&md->bl, id, md->db->skill[j].lv);
+ if ( md->db->skill[j].lv ) {
+ WFIFOW(fd, len + 8) = skill->get_sp(id, md->db->skill[j].lv);
+ WFIFOW(fd, len + 10) = skill->get_range2(&md->bl, id, md->db->skill[j].lv);
+ } else {
+ WFIFOW(fd, len + 8) = 0;
+ WFIFOW(fd, len + 10) = 0;
+ }
safestrncpy((char*)WFIFOP(fd,len+12), skill->get_name(id), NAME_LENGTH);
WFIFOB(fd,len+36) = 0; // Skillable for Mercenary?
len += 37;
@@ -15667,7 +15691,7 @@ void clif_parse_mercenary_action(int fd, struct map_session_data* sd)
/// 3 = Your mercenary soldier has ran away.
void clif_mercenary_message(struct map_session_data* sd, int message)
{
- clif->msg(sd, 1266 + message);
+ clif->msgtable(sd, MSG_MERCENARY_EXPIRED + message);
}
@@ -16701,11 +16725,11 @@ int clif_elementalconverter_list(struct map_session_data *sd) {
WFIFOW(fd, 0)=0x1ad;
for(i=0,c=0;i<MAX_SKILL_PRODUCE_DB;i++){
- if( skill->can_produce_mix(sd,skill->produce_db[i].nameid,23, 1) ){
- if((view = itemdb_viewid(skill->produce_db[i].nameid)) > 0)
+ if( skill->can_produce_mix(sd,skill->dbs->produce_db[i].nameid,23, 1) ){
+ if((view = itemdb_viewid(skill->dbs->produce_db[i].nameid)) > 0)
WFIFOW(fd,c*2+ 4)= view;
else
- WFIFOW(fd,c*2+ 4)= skill->produce_db[i].nameid;
+ WFIFOW(fd,c*2+ 4)= skill->dbs->produce_db[i].nameid;
c++;
}
}
@@ -16903,26 +16927,6 @@ int clif_skill_itemlistwindow( struct map_session_data *sd, uint16 skill_id, uin
return 1;
}
-// msgstringtable.txt
-// 0x291 <line>.W
-void clif_msgtable(int fd, int line) {
- WFIFOHEAD(fd, packet_len(0x291));
- WFIFOW(fd, 0) = 0x291;
- WFIFOW(fd, 2) = line;
- WFIFOSET(fd, packet_len(0x291));
-}
-
-// msgstringtable.txt
-// 0x7e2 <line>.W <value>.L
-void clif_msgtable_num(int fd, int line, int num) {
-#if PACKETVER >= 20090805
- WFIFOHEAD(fd, packet_len(0x7e2));
- WFIFOW(fd, 0) = 0x7e2;
- WFIFOW(fd, 2) = line;
- WFIFOL(fd, 4) = num;
- WFIFOSET(fd, packet_len(0x7e2));
-#endif
-}
/*==========================================
* used by SC_AUTOSHADOWSPELL
* RFIFOL(fd,2) - flag (currently not used)
@@ -17062,7 +17066,7 @@ void clif_favorite_item(struct map_session_data* sd, unsigned short index) {
WFIFOHEAD(fd,packet_len(0x908));
WFIFOW(fd,0) = 0x908;
WFIFOW(fd,2) = index+2;
- WFIFOL(fd,4) = (sd->status.inventory[index].favorite == 1) ? 0 : 1;
+ WFIFOB(fd,4) = (sd->status.inventory[index].favorite == 1) ? 0 : 1;
WFIFOSET(fd,packet_len(0x908));
}
@@ -17093,8 +17097,8 @@ void __attribute__ ((unused)) clif_parse_dull(int fd,struct map_session_data *sd
}
void clif_parse_CashShopOpen(int fd, struct map_session_data *sd) {
- if( map->list[sd->bl.m].flag.nocashshop ) {
- clif->colormes(fd,COLOR_RED,msg_fd(fd,1489)); //Cash Shop is disabled in this map
+ if (map->list[sd->bl.m].flag.nocashshop) {
+ clif->messagecolor_self(fd, COLOR_RED, msg_fd(fd,1489)); //Cash Shop is disabled in this map
return;
}
@@ -17134,8 +17138,8 @@ void clif_parse_CashShopBuy(int fd, struct map_session_data *sd) {
unsigned short limit = RFIFOW(fd, 4), i, j;
unsigned int kafra_pay = RFIFOL(fd, 6);// [Ryuuzaki] - These are free cash points (strangely #CASH = main cash currently for us, confusing)
- if( map->list[sd->bl.m].flag.nocashshop ) {
- clif->colormes(fd,COLOR_RED,msg_fd(fd,1489)); //Cash Shop is disabled in this map
+ if (map->list[sd->bl.m].flag.nocashshop) {
+ clif->messagecolor_self(fd, COLOR_RED, msg_fd(fd,1489)); //Cash Shop is disabled in this map
return;
}
@@ -17536,8 +17540,8 @@ void clif_parse_BankDeposit(int fd, struct map_session_data* sd) {
struct packet_banking_deposit_req *p = P2PTR(fd);
int money;
- if( !battle_config.feature_banking ) {
- clif->colormes(fd,COLOR_RED,msg_fd(fd,1483));
+ if (!battle_config.feature_banking) {
+ clif->messagecolor_self(fd, COLOR_RED, msg_fd(fd,1483));
return;
}
@@ -17550,8 +17554,8 @@ void clif_parse_BankWithdraw(int fd, struct map_session_data* sd) {
struct packet_banking_withdraw_req *p = P2PTR(fd);
int money;
- if( !battle_config.feature_banking ) {
- clif->colormes(fd,COLOR_RED,msg_fd(fd,1483));
+ if (!battle_config.feature_banking) {
+ clif->messagecolor_self(fd, COLOR_RED, msg_fd(fd,1483));
return;
}
@@ -17563,8 +17567,8 @@ void clif_parse_BankWithdraw(int fd, struct map_session_data* sd) {
void clif_parse_BankCheck(int fd, struct map_session_data* sd) {
struct packet_banking_check p;
- if( !battle_config.feature_banking ) {
- clif->colormes(fd,COLOR_RED,msg_fd(fd,1483));
+ if (!battle_config.feature_banking) {
+ clif->messagecolor_self(fd, COLOR_RED, msg_fd(fd,1483));
return;
}
@@ -17639,7 +17643,7 @@ void clif_parse_GMFullStrip(int fd, struct map_session_data *sd) {
for( i = 0; i < EQI_MAX; i++ ) {
if( tsd->equip_index[ i ] >= 0 )
- pc->unequipitem( tsd , tsd->equip_index[ i ] , 2 );
+ pc->unequipitem(tsd, tsd->equip_index[i], PCUNEQUIPITEM_FORCE);
}
}
/**
@@ -18093,6 +18097,157 @@ void clif_roulette_generate_ack(struct map_session_data *sd, unsigned char resul
clif->send(&p,sizeof(p), &sd->bl, SELF);
}
+/**
+* Stackable items merger
+**/
+void clif_openmergeitem(int fd, struct map_session_data *sd)
+{
+ int i = 0, n = 0, j = 0;
+ struct merge_item merge_items[MAX_INVENTORY];
+ struct merge_item *merge_items_[MAX_INVENTORY] = {0};
+
+ memset(&merge_items,'\0',sizeof(merge_items));
+
+ for (i = 0; i < MAX_INVENTORY; i++) {
+ struct item *item_data = &sd->status.inventory[i];
+
+ if (item_data->nameid == 0 || !itemdb->isstackable(item_data->nameid))
+ continue;
+
+ merge_items[n].nameid = item_data->nameid;
+ merge_items[n].position = i + 2;
+ n++;
+
+
+ }
+
+ qsort(merge_items,n,sizeof(struct merge_item),clif->comparemergeitem);
+
+ for (i = 0, j = 0; i < n; i++) {
+ if (i > 0 && merge_items[i].nameid == merge_items[i-1].nameid)
+ {
+ merge_items_[j] = &merge_items[i];
+ j++;
+ continue;
+ }
+
+ if (i < n - 1 && merge_items[i].nameid == merge_items[i+1].nameid)
+ {
+ merge_items_[j] = &merge_items[i];
+ j++;
+ continue;
+ }
+ }
+
+ WFIFOHEAD(fd,2*j+4);
+ WFIFOW(fd,0) = 0x96d;
+ WFIFOW(fd,2) = 2*j+4;
+ for ( i = 0; i < j; i++ )
+ WFIFOW(fd,i*2+4) = merge_items_[i]->position;
+ WFIFOSET(fd,2*j+4);
+}
+
+int clif_comparemergeitem(const void *a, const void *b)
+{
+ const struct merge_item *a_ = a;
+ const struct merge_item *b_ = b;
+
+ if (a_->nameid == b_->nameid)
+ return 0;
+ return a_->nameid > b_->nameid ? -1 : 1;
+}
+
+void clif_ackmergeitems(int fd, struct map_session_data *sd)
+{
+ int i = 0, n = 0, length = 0, count = 0;
+ int16 nameid = 0, indexes[MAX_INVENTORY] = {0}, amounts[MAX_INVENTORY] = {0};
+ struct item item_data;
+
+ length = (RFIFOW(fd,2) - 4)/2;
+
+ if (length >= MAX_INVENTORY || length < 2) {
+ WFIFOHEAD(fd,7);
+ WFIFOW(fd,0) = 0x96f;
+ WFIFOW(fd,2) = 0;
+ WFIFOW(fd,4) = 0;
+ WFIFOB(fd,6) = MERGEITEM_FAILD;
+ WFIFOSET(fd,7);
+ return;
+ }
+
+ for (i = 0, n = 0; i < length; i++) {
+ int16 idx = RFIFOW(fd,i*2+4) - 2;
+ struct item *it = NULL;
+
+ if (idx < 0 || idx >= MAX_INVENTORY)
+ continue;
+
+ it = &sd->status.inventory[idx];
+
+ if (it->nameid == 0 || !itemdb->isstackable(it->nameid))
+ continue;
+
+ if (nameid == 0)
+ nameid = it->nameid;
+
+ if (nameid != it->nameid)
+ continue;
+
+ count += it->amount;
+ indexes[n] = idx;
+ amounts[n] = it->amount;
+ n++;
+ }
+
+
+ if (n < 2 || count == 0) {
+ WFIFOHEAD(fd,7);
+ WFIFOW(fd,0) = 0x96f;
+ WFIFOW(fd,2) = 0;
+ WFIFOW(fd,4) = 0;
+ WFIFOB(fd,6) = MERGEITEM_FAILD;
+ WFIFOSET(fd,7);
+ return;
+ }
+
+ if (count > MAX_AMOUNT) {
+ WFIFOHEAD(fd,7);
+ WFIFOW(fd,0) = 0x96f;
+ WFIFOW(fd,2) = 0;
+ WFIFOW(fd,4) = 0;
+ WFIFOB(fd,6) = MERGEITEM_MAXCOUNTFAILD;
+ WFIFOSET(fd,7);
+ return;
+ }
+
+ for (i = 0; i < n; i++)
+ pc->delitem(sd,indexes[i],amounts[i],0,DELITEM_NORMAL,LOG_TYPE_NPC);
+
+
+ memset(&item_data,'\0',sizeof(item_data));
+
+ item_data.nameid = nameid;
+ item_data.identify = 1;
+ item_data.unique_id = itemdb->unique_id(sd);
+ pc->additem(sd,&item_data,count,LOG_TYPE_NPC);
+
+ ARR_FIND(0,MAX_INVENTORY,i,item_data.unique_id == sd->status.inventory[i].unique_id);
+
+ WFIFOHEAD(fd,7);
+ WFIFOW(fd,0) = 0x96f;
+ WFIFOW(fd,2) = i+2;
+ WFIFOW(fd,4) = count;
+ WFIFOB(fd,6) = MERGEITEM_SUCCESS;
+ WFIFOSET(fd,7);
+
+}
+
+void clif_cancelmergeitem (int fd, struct map_session_data *sd)
+{
+ //Track The merge item cancelation ?
+ return;
+}
+
/* */
unsigned short clif_decrypt_cmd( int cmd, struct map_session_data *sd ) {
if( sd ) {
@@ -18344,21 +18499,11 @@ void clif_bc_ready(void) {
/*==========================================
*
*------------------------------------------*/
-int do_init_clif(bool minimal) {
- const char* colors[COLOR_MAX] = { "0xFF0000", "0x00ff00", "0xffffff" };
- int i;
-
+int do_init_clif(bool minimal)
+{
if (minimal)
return 0;
- /**
- * Setup Color Table (saves unnecessary load of strtoul on every call)
- **/
- for(i = 0; i < COLOR_MAX; i++) {
- color_table[i] = (unsigned int)strtoul(colors[i],NULL,0);
- color_table[i] = (color_table[i] & 0x0000FF) << 16 | (color_table[i] & 0x00FF00) | (color_table[i] & 0xFF0000) >> 16;//RGB to BGR
- }
-
packetdb_loaddb();
set_defaultparse(clif->parse);
@@ -18653,17 +18798,15 @@ void clif_defaults(void) {
clif->disp_message = clif_disp_message;
clif->broadcast = clif_broadcast;
clif->broadcast2 = clif_broadcast2;
+ clif->messagecolor_self = clif_messagecolor_self;
clif->messagecolor = clif_messagecolor;
clif->disp_overhead = clif_disp_overhead;
- clif->msg = clif_msg;
- clif->msg_value = clif_msg_value;
- clif->msg_skill = clif_msg_skill;
+ clif->msgtable_skill = clif_msgtable_skill;
clif->msgtable = clif_msgtable;
clif->msgtable_num = clif_msgtable_num;
clif->message = clif_displaymessage;
clif->messageln = clif_displaymessage2;
clif->messages = clif_displaymessage_sprintf;
- clif->colormes = clif_colormes;
clif->process_message = clif_process_message;
clif->wisexin = clif_wisexin;
clif->wisall = clif_wisall;
@@ -18894,6 +19037,12 @@ void clif_defaults(void) {
/* */
clif->parse_roulette_db = clif_parse_roulette_db;
clif->roulette_generate_ack = clif_roulette_generate_ack;
+ /* Merge Items */
+ clif->openmergeitem = clif_openmergeitem;
+ clif->cancelmergeitem = clif_cancelmergeitem;
+ clif->comparemergeitem = clif_comparemergeitem;
+ clif->ackmergeitems = clif_ackmergeitems;
+
/*------------------------
*- Parse Incoming Packet
*------------------------*/