summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/script_commands.txt7
-rw-r--r--src/map/clif.c59
-rw-r--r--src/map/clif.h3
-rw-r--r--src/map/pc.c1
-rw-r--r--src/map/pc.h3
-rw-r--r--src/map/script.c39
-rw-r--r--src/map/unit.c1
7 files changed, 113 insertions, 0 deletions
diff --git a/doc/script_commands.txt b/doc/script_commands.txt
index e14e80444..d69322745 100644
--- a/doc/script_commands.txt
+++ b/doc/script_commands.txt
@@ -3271,6 +3271,13 @@ produced). It's useful for when you want to check whether an item contains
cards or if it's signed.
---------------------------------------
+
+*hateffect(<Hat Effect ID>, <State>)
+
+This will set a Hat Effect onto the player. The state field allows you to
+enable (true) or disable (false) the effect on the player.
+
+---------------------------------------
//=====================================
2.1 - End of Item-Related Commands
//=====================================
diff --git a/src/map/clif.c b/src/map/clif.c
index 8adb1ae58..4efd00713 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -1539,6 +1539,7 @@ bool clif_spawn(struct block_list *bl)
clif->spiritcharm(sd);
if (sd->status.look.robe != 0)
clif->refreshlook(bl, bl->id, LOOK_ROBE, sd->status.look.robe, AREA);
+ clif->hat_effect(bl, NULL, AREA);
}
break;
case BL_MOB:
@@ -4395,6 +4396,7 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl) {
clif->sendbgemblem_single(sd->fd,tsd);
if (tsd->status.look.robe != 0)
clif->refreshlook(&sd->bl, bl->id, LOOK_ROBE, tsd->status.look.robe, SELF);
+ clif->hat_effect(bl, &sd->bl, SELF);
}
break;
case BL_MER: // Devotion Effects
@@ -20105,6 +20107,60 @@ void clif_skill_scale(struct block_list *bl, int src_id, int x, int y, uint16 sk
#endif
}
+/// Send hat effects to the client (ZC_HAT_EFFECT).
+/// 0A3B <Length>.W <AID>.L <Status>.B { <HatEffectId>.W }
+void clif_hat_effect(struct block_list *bl, struct block_list *tbl, enum send_target target)
+{
+#if PACKETVER >= 20150422
+ unsigned char *buf;
+ int len, i;
+ struct map_session_data *sd;
+
+ nullpo_retv(bl);
+
+ sd = BL_CAST(BL_PC, bl);
+
+ nullpo_retv(sd);
+
+ len = 9 + VECTOR_LENGTH(sd->hatEffectId) * 2;
+
+ buf = (unsigned char*)aMalloc(len);
+
+ WBUFW(buf, 0) = 0xa3b;
+ WBUFW(buf, 2) = len;
+ WBUFL(buf, 4) = bl->id;
+ WBUFB(buf, 8) = 1;
+
+ for( i = 0; i < VECTOR_LENGTH(sd->hatEffectId); i++ ){
+ WBUFW(buf, 9 + i * 2) = VECTOR_INDEX(sd->hatEffectId, i);
+ }
+
+ if (tbl != NULL) {
+ clif->send(buf, len, tbl, target);
+ } else {
+ clif->send(buf, len, bl, target);
+ }
+
+ aFree(buf);
+#endif
+}
+
+void clif_hat_effect_single(struct block_list *bl, uint16 effectId, bool enable){
+#if PACKETVER >= 20150422
+ unsigned char buf[13];
+
+ nullpo_retv(bl);
+
+ WBUFW(buf,0) = 0xa3b;
+ WBUFW(buf,2) = 13;
+ WBUFL(buf,4) = bl->id;
+ WBUFB(buf,8) = enable;
+ WBUFL(buf,9) = effectId;
+
+ clif_send(buf, 13, bl, AREA);
+#endif
+}
+
/*==========================================
* Main client packet processing function
*------------------------------------------*/
@@ -21195,4 +21251,7 @@ void clif_defaults(void) {
clif->clan_leave = clif_clan_leave;
clif->clan_message = clif_clan_message;
clif->pClanMessage = clif_parse_ClanMessage;
+ // -- Hat Effect
+ clif->hat_effect = clif_hat_effect;
+ clif->hat_effect_single = clif_hat_effect_single;
}
diff --git a/src/map/clif.h b/src/map/clif.h
index c393c4f64..d6fbc3990 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -1413,6 +1413,9 @@ struct clif_interface {
void (*clan_leave) (struct map_session_data *sd);
void (*clan_message) (struct clan *c, const char *mes, int len);
void (*pClanMessage) (int fd, struct map_session_data* sd);
+ /* Hat Effect */
+ void (*hat_effect) (struct block_list *bl, struct block_list *tbl, enum send_target target);
+ void (*hat_effect_single) (struct block_list *bl, uint16 effectId, bool enable);
};
#ifdef HERCULES_CORE
diff --git a/src/map/pc.c b/src/map/pc.c
index c18fdee9e..cf3444538 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -1293,6 +1293,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
VECTOR_INIT(sd->script_queues);
VECTOR_INIT(sd->storage.item); // initialize storage item vector.
+ VECTOR_INIT(sd->hatEffectId);
sd->state.dialog = 0;
diff --git a/src/map/pc.h b/src/map/pc.h
index a01152df5..e699e5750 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -618,6 +618,9 @@ END_ZEROED_BLOCK;
const char* delunit_prevfile;
int delunit_prevline;
+ // HatEffect
+ VECTOR_DECL(int) hatEffectId;
+
};
#define EQP_WEAPON EQP_HAND_R
diff --git a/src/map/script.c b/src/map/script.c
index 36f37abb9..58083a3a2 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -23965,6 +23965,42 @@ BUILDIN(clan_master)
}
/**
+ * hateffect(EffectID, Enable_State)
+ */
+BUILDIN(hateffect)
+{
+#if PACKETVER >= 20150422
+ struct map_session_data *sd = script_rid2sd(st);
+ int effectId, enabled = 0;
+ int i;
+
+ if (sd == NULL)
+ return false;
+
+ effectId = script_getnum(st, 2);
+ enabled = script_getnum(st, 3);
+
+ for (i = 0; i < VECTOR_LENGTH(sd->hatEffectId); ++i) {
+ if (VECTOR_INDEX(sd->hatEffectId, i) == effectId) {
+ if (enabled == 1) { // Already Enabled
+ return true;
+ } else { // Remove
+ VECTOR_ERASE(sd->hatEffectId, i);
+ clif->hat_effect_single(&sd->bl, effectId, enabled);
+ return true;
+ }
+ }
+ }
+
+ VECTOR_ENSURE(sd->hatEffectId, 1, 1);
+ VECTOR_PUSH(sd->hatEffectId, effectId);
+
+ clif->hat_effect_single(&sd->bl, effectId, enabled);
+#endif
+ return true;
+}
+
+/**
* Adds a built-in script function.
*
* @param buildin Script function data
@@ -24679,6 +24715,9 @@ void script_parse_builtin(void) {
BUILDIN_DEF2(rodex_sendmail2, "rodex_sendmail_acc2", "isss?????????????????????????????????????????"),
BUILDIN_DEF(_,"s"),
BUILDIN_DEF2(_, "_$", "s"),
+
+ // -- HatEffect
+ BUILDIN_DEF(hateffect, "ii"),
};
int i, len = ARRAYLENGTH(BUILDIN);
RECREATE(script->buildin, char *, script->buildin_count + len); // Pre-alloc to speed up
diff --git a/src/map/unit.c b/src/map/unit.c
index 6e98fc093..fcad73188 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -2760,6 +2760,7 @@ int unit_free(struct block_list *bl, clr_type clrtype)
}
VECTOR_CLEAR(sd->script_queues);
VECTOR_CLEAR(sd->storage.item);
+ VECTOR_CLEAR(sd->hatEffectId);
sd->storage.received = false;
if( sd->quest_log != NULL ) {
aFree(sd->quest_log);