From 1f78dc3468f1a4afe1f8bd09ea340a715af1d206 Mon Sep 17 00:00:00 2001
From: Andrei Karas <akaras@inbox.ru>
Date: Thu, 28 Nov 2019 04:24:37 +0300
Subject: Add script function specialeffectnum

---
 doc/effect_list.md      |  2 +-
 doc/script_commands.txt |  9 +++++++++
 src/map/clif.c          | 19 ++++++++++++++++++
 src/map/clif.h          |  1 +
 src/map/script.c        | 51 +++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 81 insertions(+), 1 deletion(-)

diff --git a/doc/effect_list.md b/doc/effect_list.md
index 8ba8d36c9..b16839d41 100644
--- a/doc/effect_list.md
+++ b/doc/effect_list.md
@@ -21,7 +21,7 @@ The following is a compiled list of visual and sound effects which the client
 can produce. Each list entry contains a number and a short description of the
 effect. You can produce these effects ingame by using the `@effect` atcommand.
 It's also possible to attach effects to item/npc scripts by using the
-`specialeffect()` script command.
+`specialeffect()` or `specialeffectnum()` script commands.
 
   ID | Constant Name                  | Description
  --: | :----------------------------- | :----------------------------------
diff --git a/doc/script_commands.txt b/doc/script_commands.txt
index 45636f23b..b55afb0f2 100644
--- a/doc/script_commands.txt
+++ b/doc/script_commands.txt
@@ -6231,6 +6231,15 @@ Example usage:
 
 ---------------------------------------
 
+*specialeffectnum(<effect number>, <num1>, <num2>{, <send_target>{, <unit id>{, <account id>}}})
+*specialeffectnum(<effect number>, <num1>, <num2>{, <send_target>{, "<NPC Name>"{, <account id>}}})
+
+Works same as specialeffect but also send effect numbers to client.
+For PACKETVER >= 20191127 support two numbers (num1, num2).
+For older packet versions only num1 supported.
+
+---------------------------------------
+
 *removespecialeffect(<effect number>{, <send_target>{, <unit id>{, <account id>}}})
 *removespecialeffect(<effect number>{, <send_target>{, "<NPC Name>"{, <account id>}}})
 
diff --git a/src/map/clif.c b/src/map/clif.c
index bfbb88c71..ade56b53b 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -9109,6 +9109,24 @@ static void clif_specialeffect_value(struct block_list *bl, int effect_id, uint6
 #endif
 }
 
+static void clif_specialeffect_value_single(struct block_list *bl, int effect_id, uint64 num, int fd)
+{
+#if PACKETVER_MAIN_NUM >= 20060911 || defined(PACKETVER_RE) || defined(PACKETVER_ZERO)
+	WFIFOHEAD(fd, sizeof(struct PACKET_ZC_NOTIFY_EFFECT3));
+
+	struct PACKET_ZC_NOTIFY_EFFECT3 *packet = WFIFOP(fd, 0);
+	packet->packetType = HEADER_ZC_NOTIFY_EFFECT3;
+	packet->aid = bl->id;
+	packet->effectId = effect_id;
+#if PACKETVER >= 20191127
+	packet->num = num;
+#else
+	packet->num = (uint32)num;
+#endif
+	WFIFOSET(fd, sizeof(struct PACKET_ZC_NOTIFY_EFFECT3));
+#endif
+}
+
 /// Remove special effects (ZC_REMOVE_EFFECT).
 /// 0b0d <id>.L <effect id>.L
 /// effect id:
@@ -24069,6 +24087,7 @@ void clif_defaults(void)
 	clif->specialeffect = clif_specialeffect;
 	clif->specialeffect_single = clif_specialeffect_single;
 	clif->specialeffect_value = clif_specialeffect_value;
+	clif->specialeffect_value_single = clif_specialeffect_value_single;
 	clif->removeSpecialEffect = clif_removeSpecialEffect;
 	clif->removeSpecialEffect_single = clif_removeSpecialEffect_single;
 	clif->millenniumshield = clif_millenniumshield;
diff --git a/src/map/clif.h b/src/map/clif.h
index 498cbc046..14a7997a1 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -1031,6 +1031,7 @@ struct clif_interface {
 	void (*specialeffect) (struct block_list* bl, int type, enum send_target target);
 	void (*specialeffect_single) (struct block_list* bl, int type, int fd);
 	void (*specialeffect_value) (struct block_list* bl, int effect_id, uint64 num, send_target target);
+	void (*specialeffect_value_single) (struct block_list *bl, int effect_id, uint64 num, int fd);
 	void (*removeSpecialEffect) (struct block_list *bl, int effectId, enum send_target target);
 	void (*removeSpecialEffect_single) (struct block_list *bl, int effectId, struct block_list *targetBl);
 	void (*millenniumshield) (struct block_list *bl, short shields );
diff --git a/src/map/script.c b/src/map/script.c
index 16336b46d..396d084a3 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -15815,6 +15815,56 @@ static BUILDIN(specialeffect)
 	return true;
 }
 
+/*==========================================
+ * Special effects with num [4144]
+ *------------------------------------------*/
+static BUILDIN(specialeffectnum)
+{
+	struct block_list *bl = NULL;
+	int type = script_getnum(st, 2);
+	int num = script_getnum(st, 3);
+	int num2 = script_getnum(st, 4);
+	enum send_target target = AREA;
+
+	if (script_hasdata(st, 5)) {
+		target = script_getnum(st, 5);
+	}
+
+	if (script_hasdata(st, 6)) {
+		if (script_isstringtype(st, 6)) {
+			struct npc_data *nd = npc->name2id(script_getstr(st, 6));
+			if (nd != NULL) {
+				bl = &nd->bl;
+			}
+		} else {
+			bl = map->id2bl(script_getnum(st, 6));
+		}
+	} else {
+		bl = map->id2bl(st->oid);
+	}
+
+	if (bl == NULL) {
+		return true;
+	}
+
+	uint64 bigNum = ((uint64)num2) * 0xffffffff + num;
+	if (target == SELF) {
+		struct map_session_data *sd;
+		if (script_hasdata(st, 7)) {
+			sd = map->id2sd(script_getnum(st, 7));
+		} else {
+			sd = script->rid2sd(st);
+		}
+		if (sd != NULL) {
+			clif->specialeffect_value_single(bl, type, bigNum, sd->fd);
+		}
+	} else {
+		clif->specialeffect_value(bl, type, bigNum, target);
+	}
+
+	return true;
+}
+
 static BUILDIN(specialeffect2)
 {
 	struct map_session_data *sd;
@@ -26369,6 +26419,7 @@ static void script_parse_builtin(void)
 		BUILDIN_DEF(skilleffect,"vi"), // skill effect [Celest]
 		BUILDIN_DEF(npcskilleffect,"viii"), // npc skill effect [Valaris]
 		BUILDIN_DEF(specialeffect,"i???"), // npc skill effect [Valaris]
+		BUILDIN_DEF(specialeffectnum,"iii???"), // npc skill effect with num [4144]
 		BUILDIN_DEF(removespecialeffect,"i???"),
 		BUILDIN_DEF_DEPRECATED(specialeffect2,"i??"), // skill effect on players[Valaris]
 		BUILDIN_DEF(nude,""), // nude command [Valaris]
-- 
cgit v1.2.3-70-g09d2