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.c305
1 files changed, 218 insertions, 87 deletions
diff --git a/src/map/clif.c b/src/map/clif.c
index 3533c7eff..bfe78a58d 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -36,6 +36,7 @@
#include "homunculus.h"
#include "instance.h"
#include "mercenary.h"
+#include "elemental.h"
#include "log.h"
#include "clif.h"
#include "mail.h"
@@ -273,7 +274,7 @@ static inline unsigned char clif_bl_type(struct block_list *bl) {
case BL_PET: return pcdb_checkid(status_get_viewdata(bl)->class_)?0x0:0x7; //NPC_PET_TYPE
case BL_HOM: return 0x8; //NPC_HOM_TYPE
case BL_MER: return 0x9; //NPC_MERSOL_TYPE
-// case BL_ELEM: return 0xA; //NPC_ELEMENTAL_TYPE
+ case BL_ELEM: return 0xa; //NPC_ELEMENTAL_TYPE
default: return 0x1; //NPC_TYPE
}
}
@@ -5193,44 +5194,60 @@ void clif_skill_produce_mix_list(struct map_session_data *sd, int skillid , int
/// 4 = GN_MIX_COOKING
/// 5 = GN_MAKEBOMB
/// 6 = GN_S_PHARMACY
-void clif_cooking_list(struct map_session_data *sd, int trigger)
+void clif_cooking_list(struct map_session_data *sd, int trigger, int skill_id, int qty, int list_type)
{
int fd;
int i, c;
int view;
-
+
nullpo_retv(sd);
fd = sd->fd;
-
- WFIFOHEAD(fd, 6 + 2*MAX_SKILL_PRODUCE_DB);
+
+ WFIFOHEAD(fd, 6 + 2 * MAX_SKILL_PRODUCE_DB);
WFIFOW(fd,0) = 0x25a;
- WFIFOW(fd,4) = 1; // list type
-
+ WFIFOW(fd,4) = list_type; // list type
+
c = 0;
- for( i = 0; i < MAX_SKILL_PRODUCE_DB; i++ )
- {
- if( !skill_can_produce_mix(sd,skill_produce_db[i].nameid,trigger, 1) )
+ for( i = 0; i < MAX_SKILL_PRODUCE_DB; i++ ) {
+ if( !skill_can_produce_mix(sd,skill_produce_db[i].nameid,trigger, qty) )
continue;
-
+
if( (view = itemdb_viewid(skill_produce_db[i].nameid)) > 0 )
- WFIFOW(fd, 6+2*c)= view;
+ WFIFOW(fd, 6 + 2 * c) = view;
else
- WFIFOW(fd, 6+2*c)= skill_produce_db[i].nameid;
-
+ WFIFOW(fd, 6 + 2 * c) = skill_produce_db[i].nameid;
+
c++;
}
-
- WFIFOW(fd,2) = 6 + 2*c;
- WFIFOSET(fd,WFIFOW(fd,2));
-
- //TODO: replace with proper solution
- if( c > 0 )
- {
- sd->menuskill_id = AM_PHARMACY;
+
+ if( skill_id == AM_PHARMACY ) { // Only send it while Cooking else check for c.
+ WFIFOW(fd,2) = 6 + 2 * c;
+ WFIFOSET(fd,WFIFOW(fd,2));
+ }
+
+ if( c > 0 ) {
+ sd->menuskill_id = skill_id;
sd->menuskill_val = trigger;
+ if( skill_id != AM_PHARMACY ) {
+ sd->menuskill_val2 = qty; // amount.
+ WFIFOW(fd,2) = 6 + 2 * c;
+ WFIFOSET(fd,WFIFOW(fd,2));
+ }
+ } else {
+ clif_menuskill_clear(sd);
+ if( skill_id != AM_PHARMACY ) { // AM_PHARMACY is used to Cooking.
+ // It fails.
+#if PACKETVER >= 20090922
+ clif_msg_skill(sd,skill_id,0x625);
+#else
+ WFIFOW(fd,2) = 6 + 2 * c;
+ WFIFOSET(fd,WFIFOW(fd,2));
+#endif
+ }
}
}
+
/// Notifies clients of a status change.
/// 0196 <index>.W <id>.L <state>.B (ZC_MSG_STATE_CHANGE) [used for ending status changes and starting them on non-pc units (when needed)]
/// 043f <index>.W <id>.L <state>.B <remain msec>.L { <val>.L }*3 (ZC_MSG_STATE_CHANGE2) [used exclusively for starting statuses on pcs]
@@ -8107,11 +8124,12 @@ void clif_refresh(struct map_session_data *sd)
clif_refreshlook(&sd->bl,sd->bl.id,LOOK_CLOTHES_COLOR,sd->vd.cloth_color,SELF);
if(merc_is_hom_active(sd->hd))
clif_send_homdata(sd,SP_ACK,0);
- if( sd->md )
- {
+ if( sd->md ) {
clif_mercenary_info(sd);
clif_mercenary_skillblock(sd);
}
+ if( sd->ed )
+ clif_elemental_info(sd);
map_foreachinrange(clif_getareachar,&sd->bl,AREA_SIZE,BL_ALL,sd);
clif_weather_check(sd);
if( sd->chatID )
@@ -8255,6 +8273,9 @@ void clif_charnameack (int fd, struct block_list *bl)
// memcpy(WBUFP(buf,6), (struct chat*)->title, NAME_LENGTH);
// break;
return;
+ case BL_ELEM:
+ memcpy(WBUFP(buf,6), ((TBL_ELEM*)bl)->db->name, NAME_LENGTH);
+ break;
default:
ShowError("clif_charnameack: bad type %d(%d)\n", bl->type, bl->id);
return;
@@ -9082,14 +9103,22 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
skill_unit_move(&sd->hd->bl,gettick(),1); // apply land skills immediately
}
- if( sd->md )
- {
+ if( sd->md ) {
map_addblock(&sd->md->bl);
clif_spawn(&sd->md->bl);
clif_mercenary_info(sd);
clif_mercenary_skillblock(sd);
}
+ if( sd->ed ) {
+ map_addblock(&sd->ed->bl);
+ clif_spawn(&sd->ed->bl);
+ clif_elemental_info(sd);
+ clif_elemental_updatestatus(sd,SP_HP);
+ clif_hpmeter_single(sd->fd,sd->ed->bl.id,sd->ed->battle_status.hp,sd->ed->battle_status.matk_max);
+ clif_elemental_updatestatus(sd,SP_SP);
+ }
+
if(sd->state.connect_new) {
int lv;
sd->state.connect_new = 0;
@@ -10587,15 +10616,13 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd)
if( sd->sc.data[SC_BASILICA] && (skillnum != HP_BASILICA || sd->sc.data[SC_BASILICA]->val4 != sd->bl.id) )
return; // On basilica only caster can use Basilica again to stop it.
- if( sd->menuskill_id )
- {
- if( sd->menuskill_id == SA_TAMINGMONSTER )
- sd->menuskill_id = sd->menuskill_val = 0; //Cancel pet capture.
- else if( sd->menuskill_id != SA_AUTOSPELL )
+ if( sd->menuskill_id ) {
+ if( sd->menuskill_id == SA_TAMINGMONSTER ) {
+ clif_menuskill_clear(sd); //Cancel pet capture.
+ } else if( sd->menuskill_id != SA_AUTOSPELL )
return; //Can't use skills while a menu is open.
}
- if( sd->skillitem == skillnum )
- {
+ if( sd->skillitem == skillnum ) {
if( skilllv != sd->skillitemlv )
skilllv = sd->skillitemlv;
if( !(tmp&INF_SELF_SKILL) )
@@ -10606,15 +10633,12 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd)
sd->skillitem = sd->skillitemlv = 0;
- if( skillnum >= GD_SKILLBASE )
- {
+ if( skillnum >= GD_SKILLBASE ) {
if( sd->state.gmaster_flag )
skilllv = guild_checkskill(sd->state.gmaster_flag, skillnum);
else
skilllv = 0;
- }
- else
- {
+ } else {
tmp = pc_checkskill(sd, skillnum);
if( skilllv > tmp )
skilllv = tmp;
@@ -10661,10 +10685,8 @@ static void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, sho
if( sd->ud.skilltimer != INVALID_TIMER )
return;
- if( DIFF_TICK(tick, sd->ud.canact_tick) < 0 )
- {
- if( sd->skillitem != skillnum )
- {
+ if( DIFF_TICK(tick, sd->ud.canact_tick) < 0 ) {
+ if( sd->skillitem != skillnum ) {
clif_skill_fail(sd, skillnum, USESKILL_FAIL_SKILLINTERVAL, 0);
return;
}
@@ -10676,28 +10698,23 @@ static void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, sho
if( sd->sc.data[SC_BASILICA] && (skillnum != HP_BASILICA || sd->sc.data[SC_BASILICA]->val4 != sd->bl.id) )
return; // On basilica only caster can use Basilica again to stop it.
- if( sd->menuskill_id )
- {
- if( sd->menuskill_id == SA_TAMINGMONSTER )
- sd->menuskill_id = sd->menuskill_val = 0; //Cancel pet capture.
- else if( sd->menuskill_id != SA_AUTOSPELL )
+ if( sd->menuskill_id ) {
+ if( sd->menuskill_id == SA_TAMINGMONSTER ) {
+ clif_menuskill_clear(sd); //Cancel pet capture.
+ } else if( sd->menuskill_id != SA_AUTOSPELL )
return; //Can't use skills while a menu is open.
}
pc_delinvincibletimer(sd);
- if( sd->skillitem == skillnum )
- {
+ if( sd->skillitem == skillnum ) {
if( skilllv != sd->skillitemlv )
skilllv = sd->skillitemlv;
unit_skilluse_pos(&sd->bl, x, y, skillnum, skilllv);
- }
- else
- {
+ } else {
int lv;
sd->skillitem = sd->skillitemlv = 0;
- if( (lv = pc_checkskill(sd, skillnum)) > 0 )
- {
+ if( (lv = pc_checkskill(sd, skillnum)) > 0 ) {
if( skilllv > lv )
skilllv = lv;
unit_skilluse_pos(&sd->bl, x, y, skillnum,skilllv);
@@ -10759,9 +10776,8 @@ void clif_parse_UseSkillMap(int fd, struct map_session_data* sd)
if(skill_num != sd->menuskill_id)
return;
- if( pc_cant_act(sd) )
- {
- sd->menuskill_id = sd->menuskill_val = 0;
+ if( pc_cant_act(sd) ) {
+ clif_menuskill_clear(sd);
return;
}
@@ -10795,12 +10811,12 @@ void clif_parse_ProduceMix(int fd,struct map_session_data *sd)
if (pc_istrading(sd)) {
//Make it fail to avoid shop exploits where you sell something different than you see.
clif_skill_fail(sd,sd->ud.skillid,USESKILL_FAIL_LEVEL,0);
- sd->menuskill_val = sd->menuskill_id = 0;
+ clif_menuskill_clear(sd);
return;
}
if( skill_can_produce_mix(sd,RFIFOW(fd,2),sd->menuskill_val, 1) )
skill_produce_mix(sd,0,RFIFOW(fd,2),RFIFOW(fd,4),RFIFOW(fd,6),RFIFOW(fd,8), 1);
- sd->menuskill_val = sd->menuskill_id = 0;
+ clif_menuskill_clear(sd);
}
@@ -10813,24 +10829,22 @@ void clif_parse_ProduceMix(int fd,struct map_session_data *sd)
/// 4 = GN_MIX_COOKING
/// 5 = GN_MAKEBOMB
/// 6 = GN_S_PHARMACY
-void clif_parse_Cooking(int fd,struct map_session_data *sd)
-{
- //int type = RFIFOW(fd,2);
+void clif_parse_Cooking(int fd,struct map_session_data *sd) {
+ int type = RFIFOW(fd,2);
int nameid = RFIFOW(fd,4);
-
- if( sd->menuskill_id != AM_PHARMACY ) {
+ int amount = sd->menuskill_val2?sd->menuskill_val2:1;
+ if( type == 6 && sd->menuskill_id != GN_MIX_COOKING && sd->menuskill_id != GN_S_PHARMACY )
return;
- }
-
+
if (pc_istrading(sd)) {
//Make it fail to avoid shop exploits where you sell something different than you see.
clif_skill_fail(sd,sd->ud.skillid,USESKILL_FAIL_LEVEL,0);
- sd->menuskill_val = sd->menuskill_id = 0;
+ clif_menuskill_clear(sd);
return;
}
- if( skill_can_produce_mix(sd,nameid,sd->menuskill_val, 1) )
- skill_produce_mix(sd,0,nameid,0,0,0,1);
- sd->menuskill_val = sd->menuskill_id = 0;
+ if( skill_can_produce_mix(sd,nameid,sd->menuskill_val, amount) )
+ skill_produce_mix(sd,sd->menuskill_id,nameid,0,0,0,amount);
+ clif_menuskill_clear(sd);
}
@@ -10843,11 +10857,11 @@ void clif_parse_RepairItem(int fd, struct map_session_data *sd)
if (pc_istrading(sd)) {
//Make it fail to avoid shop exploits where you sell something different than you see.
clif_skill_fail(sd,sd->ud.skillid,USESKILL_FAIL_LEVEL,0);
- sd->menuskill_val = sd->menuskill_id = 0;
+ clif_menuskill_clear(sd);
return;
}
skill_repairweapon(sd,RFIFOW(fd,2));
- sd->menuskill_val = sd->menuskill_id = 0;
+ clif_menuskill_clear(sd);
}
@@ -10862,12 +10876,12 @@ void clif_parse_WeaponRefine(int fd, struct map_session_data *sd)
if (pc_istrading(sd)) {
//Make it fail to avoid shop exploits where you sell something different than you see.
clif_skill_fail(sd,sd->ud.skillid,USESKILL_FAIL_LEVEL,0);
- sd->menuskill_val = sd->menuskill_id = 0;
+ clif_menuskill_clear(sd);
return;
}
idx = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]);
skill_weaponrefine(sd, idx-2);
- sd->menuskill_val = sd->menuskill_id = 0;
+ clif_menuskill_clear(sd);
}
@@ -10952,13 +10966,12 @@ void clif_parse_ItemIdentify(int fd,struct map_session_data *sd)
if (sd->menuskill_id != MC_IDENTIFY)
return;
- if( idx == -1 )
- {// cancel pressed
- sd->menuskill_val = sd->menuskill_id = 0;
+ if( idx == -1 ) {// cancel pressed
+ clif_menuskill_clear(sd);
return;
}
skill_identify(sd,idx-2);
- sd->menuskill_val = sd->menuskill_id = 0;
+ clif_menuskill_clear(sd);
}
@@ -10969,7 +10982,7 @@ void clif_parse_SelectArrow(int fd,struct map_session_data *sd)
if (pc_istrading(sd)) {
//Make it fail to avoid shop exploits where you sell something different than you see.
clif_skill_fail(sd,sd->ud.skillid,USESKILL_FAIL_LEVEL,0);
- sd->menuskill_val = sd->menuskill_id = 0;
+ clif_menuskill_clear(sd);
return;
}
switch( sd->menuskill_id ) {
@@ -10990,7 +11003,7 @@ void clif_parse_SelectArrow(int fd,struct map_session_data *sd)
break;
}
- sd->menuskill_val = sd->menuskill_id = 0;
+ clif_menuskill_clear(sd);
}
@@ -11001,7 +11014,7 @@ void clif_parse_AutoSpell(int fd,struct map_session_data *sd)
if (sd->menuskill_id != SA_AUTOSPELL)
return;
skill_autospell(sd,RFIFOL(fd,2));
- sd->menuskill_val = sd->menuskill_id = 0;
+ clif_menuskill_clear(sd);
}
@@ -12074,7 +12087,7 @@ void clif_parse_SelectEgg(int fd, struct map_session_data *sd)
return;
}
pet_select_egg(sd,RFIFOW(fd,2)-2);
- sd->menuskill_val = sd->menuskill_id = 0;
+ clif_menuskill_clear(sd);
}
@@ -13038,7 +13051,7 @@ void clif_parse_FeelSaveOk(int fd,struct map_session_data *sd)
// clif_misceffect2(&sd->bl, 0x1b0);
// clif_misceffect2(&sd->bl, 0x21f);
clif_feel_info(sd, i, 0);
- sd->menuskill_val = sd->menuskill_id = 0;
+ clif_menuskill_clear(sd);
}
@@ -15051,6 +15064,94 @@ void clif_parse_LessEffect(int fd, struct map_session_data* sd)
sd->state.lesseffect = ( isLess != 0 );
}
+/// S 07e4 <length>.w <option>.l <val>.l {<index>.w <amount>.w).4b*
+void clif_parse_ItemListWindowSelected(int fd, struct map_session_data* sd) {
+ int n = (RFIFOW(fd,2)-12) / 4;
+ int type = RFIFOL(fd,4);
+ int flag = RFIFOL(fd,8); // Button clicked: 0 = Cancel, 1 = OK
+ unsigned short* item_list = (unsigned short*)RFIFOP(fd,12);
+
+ if( sd->state.trading || sd->npc_shopid )
+ return;
+
+ if( flag == 0 || n == 0) {
+ clif_menuskill_clear(sd);
+ return; // Canceled by player.
+ }
+
+ if( sd->menuskill_id != SO_EL_ANALYSIS && sd->menuskill_id != GN_CHANGEMATERIAL ) {
+ clif_menuskill_clear(sd);
+ return; // Prevent hacking.
+ }
+
+ switch( type ) {
+ case 0: // Change Material
+ skill_changematerial(sd,n,item_list);
+ break;
+ case 1: // Level 1: Pure to Rough
+ case 2: // Level 2: Rough to Pure
+ skill_elementalanalysis(sd,n,type,item_list);
+ break;
+ }
+ clif_menuskill_clear(sd);
+
+ return;
+}
+
+/*==========================================
+ * Elemental System
+ *==========================================*/
+void clif_elemental_updatestatus(struct map_session_data *sd, int type) {
+ struct elemental_data *ed;
+ struct status_data *status;
+ int fd;
+
+ if( sd == NULL || (ed = sd->ed) == NULL )
+ return;
+
+ fd = sd->fd;
+ status = &ed->battle_status;
+ WFIFOHEAD(fd,8);
+ WFIFOW(fd,0) = 0x81e;
+ WFIFOW(fd,2) = type;
+ switch( type ) {
+ case SP_HP:
+ WFIFOL(fd,4) = status->hp;
+ break;
+ case SP_MAXHP:
+ WFIFOL(fd,4) = status->max_hp;
+ break;
+ case SP_SP:
+ WFIFOL(fd,4) = status->sp;
+ break;
+ case SP_MAXSP:
+ WFIFOL(fd,4) = status->max_sp;
+ break;
+ }
+ WFIFOSET(fd,8);
+}
+
+void clif_elemental_info(struct map_session_data *sd) {
+ int fd;
+ struct elemental_data *ed;
+ struct status_data *status;
+
+ if( sd == NULL || (ed = sd->ed) == NULL )
+ return;
+
+ fd = sd->fd;
+ status = &ed->battle_status;
+
+ WFIFOHEAD(fd,22);
+ WFIFOW(fd, 0) = 0x81d;
+ WFIFOL(fd, 2) = ed->bl.id;
+ WFIFOL(fd, 6) = status->hp;
+ WFIFOL(fd,10) = status->max_hp;
+ WFIFOL(fd,14) = status->sp;
+ WFIFOL(fd,18) = status->max_sp;
+ WFIFOSET(fd,22);
+}
+
/// Buying Store System
///
@@ -15762,6 +15863,35 @@ int clif_autoshadowspell_list(struct map_session_data *sd) {
return 1;
}
+/*===========================================
+ * Skill list for Four Elemental Analysis
+ * and Change Material skills.
+ *------------------------------------------*/
+int clif_skill_itemlistwindow( struct map_session_data *sd, int skill_id, int skill_lv )
+{
+#if PACKETVER >= 20090922
+ int fd;
+
+ nullpo_ret(sd);
+
+ sd->menuskill_id = skill_id; // To prevent hacking.
+ sd->menuskill_val = skill_lv;
+
+ if( skill_id == GN_CHANGEMATERIAL )
+ skill_lv = 0; // Changematerial
+
+ fd = sd->fd;
+ WFIFOHEAD(fd,packet_len(0x7e3));
+ WFIFOW(fd,0) = 0x7e3;
+ WFIFOL(fd,2) = skill_lv;
+ WFIFOL(fd,4) = 0;
+ WFIFOSET(fd,packet_len(0x7e3));
+
+#endif
+
+ return 1;
+
+}
/**
* Sends a new status without a tick (currently used by the new mounts)
**/
@@ -15826,11 +15956,11 @@ void clif_parse_SkillSelectMenu(int fd, struct map_session_data *sd) {
if( pc_istrading(sd) ) {
clif_skill_fail(sd,sd->ud.skillid,0,0);
- sd->menuskill_val = sd->menuskill_id = 0;
+ clif_menuskill_clear(sd);
return;
}
skill_select_menu(sd,RFIFOL(fd,2),RFIFOW(fd,6));
- sd->menuskill_val = sd->menuskill_id = 0;
+ clif_menuskill_clear(sd);
}
/*==========================================
@@ -16202,13 +16332,13 @@ static int packetdb_readdb(void)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
//#0x07C0
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
#if PACKETVER < 20090617
6, 2, -1, 4, 4, 4, 4, 8, 8,254, 6, 8, 6, 54, 30, 54,
#else // 0x7d9 changed
6, 2, -1, 4, 4, 4, 4, 8, 8,268, 6, 8, 6, 54, 30, 54,
#endif
- 0, 15, 8, 0, 0, 8, 8, 32, -1, 5, 0, 0, 0, 0, 0, 0,
+ 0, 15, 8, 6, -1, 8, 8, 32, -1, 5, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 14, -1, -1, -1, 8, 25, 0, 0, 26, 0,
//#0x0800
#if PACKETVER < 20091229
@@ -16406,6 +16536,7 @@ static int packetdb_readdb(void)
{clif_parse_mercenary_action,"mermenu"},
{clif_parse_progressbar,"progressbar"},
{clif_parse_SkillSelectMenu,"skillselectmenu"},
+ {clif_parse_ItemListWindowSelected,"itemlistwindowselected"},
#if PACKETVER >= 20091229
{clif_parse_PartyBookingRegisterReq,"bookingregreq"},
{clif_parse_PartyBookingSearchReq,"bookingsearchreq"},