Jump to content
  • 0

how to use "hateffect" in the monster ?


kpcamber

Question


  • Group:  Members
  • Topic Count:  3
  • Topics Per Day:  0.01
  • Content Count:  11
  • Reputation:   0
  • Joined:  03/13/23
  • Last Seen:  

how to use "hateffect" in the monster ?

Please help me !

Link to comment
Share on other sites

9 answers to this question

Recommended Posts

  • 0

  • Group:  Members
  • Topic Count:  16
  • Topics Per Day:  0.00
  • Content Count:  662
  • Reputation:   671
  • Joined:  11/12/12
  • Last Seen:  

Unfortunately, hat effects were implemented on the map_session_data (player) on the emulator, while it should have been on the unit_data structure instead, which is shared by all object types. So you'll need a lot of modifications to get this working on monsters. If you apply the changes below, you'll be able to add a hat effect with this command:

	monster "prontera", 154, 182, "--ja--", 1002, 1;
	hateffect 12, true, $@mobid;

Changes:

diff --git a/src/map/clif.cpp b/src/map/clif.cpp
index 991b5b1b8..f2fece16d 100644
--- a/src/map/clif.cpp
+++ b/src/map/clif.cpp
@@ -1733,7 +1733,7 @@ int clif_spawn( struct block_list *bl, bool walking ){
 			if (sd->status.robe)
 				clif_refreshlook(bl,bl->id,LOOK_ROBE,sd->status.robe,AREA);
 			clif_efst_status_change_sub(bl, bl, AREA);
-			clif_hat_effects(sd,bl,AREA);
+			clif_hat_effects(bl, bl, true, AREA);
 		}
 		break;
 	case BL_MOB:
@@ -1745,6 +1745,7 @@ int clif_spawn( struct block_list *bl, bool walking ){
 				clif_specialeffect(&md->bl,EF_BABYBODY2,AREA);
 			if ( md->special_state.ai == AI_ABR || md->special_state.ai == AI_BIONIC )
 				clif_summon_init(*md);
+			clif_hat_effects(bl, bl, true, AREA);
 		}
 		break;
 	case BL_NPC:
@@ -1756,6 +1757,7 @@ int clif_spawn( struct block_list *bl, bool walking ){
 				clif_specialeffect(&nd->bl,EF_BABYBODY2,AREA);
 			clif_efst_status_change_sub(bl, bl, AREA);
 			clif_progressbar_npc_area(nd);
+			clif_hat_effects(bl, bl, true, AREA);
 		}
 		break;
 	case BL_PET:
@@ -5104,7 +5106,7 @@ void clif_getareachar_unit( map_session_data* sd,struct block_list *bl ){
 			if ( tsd->status.robe )
 				clif_refreshlook(&sd->bl,bl->id,LOOK_ROBE,tsd->status.robe,SELF);
 			clif_efst_status_change_sub(&sd->bl, bl, SELF);
-			clif_hat_effects(sd,bl,SELF);
+			clif_hat_effects(&sd->bl, bl, true, SELF);
 		}
 		break;
 	case BL_MER: // Devotion Effects
@@ -5122,6 +5124,7 @@ void clif_getareachar_unit( map_session_data* sd,struct block_list *bl ){
 				clif_specialeffect_single(bl,EF_BABYBODY2,sd->fd);
 			clif_efst_status_change_sub(&sd->bl, bl, SELF);
 			clif_progressbar_npc(nd, sd);
+			clif_hat_effects(&sd->bl, bl, true, SELF);
 		}
 		break;
 	case BL_MOB:
@@ -5139,6 +5142,7 @@ void clif_getareachar_unit( map_session_data* sd,struct block_list *bl ){
 						clif_monster_hp_bar(md, sd->fd);
 			}
 #endif
+			clif_hat_effects(&sd->bl, bl, true, SELF);
 		}
 		break;
 	case BL_PET:
@@ -21184,53 +21188,46 @@ void clif_navigateTo(map_session_data *sd, const char* mapname, uint16 x, uint16
 
 /// Send hat effects to the client (ZC_HAT_EFFECT).
 /// 0A3B <Length>.W <AID>.L <Status>.B { <HatEffectId>.W }
-void clif_hat_effects( map_session_data* sd, struct block_list* bl, enum send_target target ){
+void clif_hat_effects(struct block_list* src, struct block_list* bl, bool enable, enum send_target target ){
 #if PACKETVER_MAIN_NUM >= 20150507 || PACKETVER_RE_NUM >= 20150429 || defined(PACKETVER_ZERO)
-	map_session_data *tsd;
-	struct block_list* tbl;
-
-	if( target == SELF ){
-		tsd = BL_CAST(BL_PC,bl);
-		tbl = &sd->bl;
-	}else{
-		tsd = sd;
-		tbl = bl;
-	}
-
-	nullpo_retv( tsd );
-
-	if( tsd->hatEffects.empty() || map_getmapdata(tbl->m)->getMapFlag(MF_NOCOSTUME) ){
+	struct unit_data* ud;
+	
+	if (!src || !bl || !(ud = unit_bl2ud(bl)))
 		return;
-	}
-
+	
+	if (ud->hatEffects.empty() || map_getmapdata(src->m)->getMapFlag(MF_NOCOSTUME)) {
+ 		return;
+ 	}
+	
 	struct PACKET_ZC_EQUIPMENT_EFFECT* p = (struct PACKET_ZC_EQUIPMENT_EFFECT*)packet_buffer;
-
-	p->packetType = HEADER_ZC_EQUIPMENT_EFFECT;
-	p->packetLength = (int16)( sizeof( struct PACKET_ZC_EQUIPMENT_EFFECT ) + sizeof( int16 ) * tsd->hatEffects.size() );
-	p->aid = tsd->bl.id;
-	p->status = 1;
-
-	for( size_t i = 0; i < tsd->hatEffects.size(); i++ ){
-		p->effects[i] = tsd->hatEffects[i];
-	}
-
-	clif_send( p, p->packetLength, tbl, target );
+ 
+ 	p->packetType = HEADER_ZC_EQUIPMENT_EFFECT;
+	
+	p->packetLength = (int16)( sizeof( struct PACKET_ZC_EQUIPMENT_EFFECT ) + sizeof( int16 ) * ud->hatEffects.size() );
+	p->aid = bl->id;
+	p->status = enable;
+	
+	for (size_t i = 0; i < ud->hatEffects.size(); i++) {
+		p->effects[i] = ud->hatEffects[i];
+ 	}
+	
+	clif_send(p, p->packetLength, src, target);
 #endif
 }
 
-void clif_hat_effect_single( map_session_data* sd, uint16 effectId, bool enable ){
+void clif_hat_effect_single( struct block_list* bl, uint16 effectId, bool enable ){
 #if PACKETVER_MAIN_NUM >= 20150507 || PACKETVER_RE_NUM >= 20150429 || defined(PACKETVER_ZERO)
-	nullpo_retv( sd );
-
-	struct PACKET_ZC_EQUIPMENT_EFFECT* p = (struct PACKET_ZC_EQUIPMENT_EFFECT*)packet_buffer;
-
-	p->packetType = HEADER_ZC_EQUIPMENT_EFFECT;
-	p->packetLength = (int16)( sizeof( struct PACKET_ZC_EQUIPMENT_EFFECT ) + sizeof( int16 ) );
-	p->aid = sd->bl.id;
-	p->status = enable;
-	p->effects[0] = effectId;
-
-	clif_send( p, p->packetLength, &sd->bl, AREA );
+	nullpo_retv(bl);
+ 
+ 	struct PACKET_ZC_EQUIPMENT_EFFECT* p = (struct PACKET_ZC_EQUIPMENT_EFFECT*)packet_buffer;
+ 
+ 	p->packetType = HEADER_ZC_EQUIPMENT_EFFECT;
+ 	p->packetLength = (int16)( sizeof( struct PACKET_ZC_EQUIPMENT_EFFECT ) + sizeof( int16 ) );
+	p->aid = bl->id;
+ 	p->status = enable;
+ 	p->effects[0] = effectId;
+ 
+	clif_send( p, p->packetLength, bl, AREA );
 #endif
 }
 
diff --git a/src/map/clif.hpp b/src/map/clif.hpp
index 1bf10b262..f6ba450b2 100644
--- a/src/map/clif.hpp
+++ b/src/map/clif.hpp
@@ -801,8 +801,8 @@ void clif_item_repair_list(map_session_data *sd, map_session_data *dstsd, int lv
 void clif_item_repaireffect(map_session_data *sd, int idx, int flag);
 void clif_item_damaged(map_session_data* sd, unsigned short position);
 void clif_item_refine_list(map_session_data *sd);
-void clif_hat_effects( map_session_data* sd, struct block_list* bl, enum send_target target );
-void clif_hat_effect_single( map_session_data* sd, uint16 effectId, bool enable );
+void clif_hat_effects(struct block_list* src, struct block_list* bl, bool enable, enum send_target target);
+void clif_hat_effect_single(struct block_list* bl, uint16 effectId, bool enable);
 
 void clif_item_skill(map_session_data *sd,uint16 skill_id,uint16 skill_lv);
 
diff --git a/src/map/pc.cpp b/src/map/pc.cpp
index 1cb25fad6..c2e9b2cc2 100755
--- a/src/map/pc.cpp
+++ b/src/map/pc.cpp
@@ -2220,10 +2220,6 @@ bool pc_authok(map_session_data *sd, uint32 login_id2, time_t expiration_time, i
 	// Initialize BG queue
 	sd->bg_queue_id = 0;
 
-#if PACKETVER_MAIN_NUM >= 20150507 || PACKETVER_RE_NUM >= 20150429 || defined(PACKETVER_ZERO)
-	sd->hatEffects = {};
-#endif
-
 	sd->catch_target_class = PET_CATCH_FAIL;
 
 	// Check EXP overflow, since in previous revision EXP on Max Level can be more than 'official' Max EXP
diff --git a/src/map/pc.hpp b/src/map/pc.hpp
index c37cd4fb5..3f4ceb943 100644
--- a/src/map/pc.hpp
+++ b/src/map/pc.hpp
@@ -922,10 +922,6 @@ public:
 
 	short setlook_head_top, setlook_head_mid, setlook_head_bottom, setlook_robe; ///< Stores 'setlook' script command values.
 
-#if PACKETVER_MAIN_NUM >= 20150507 || PACKETVER_RE_NUM >= 20150429 || defined(PACKETVER_ZERO)
-	std::vector<int16> hatEffects;
-#endif
-
 	struct{
 		int tid;
 		uint16 skill_id;
diff --git a/src/map/script.cpp b/src/map/script.cpp
index 027587945..72a1382f1 100644
--- a/src/map/script.cpp
+++ b/src/map/script.cpp
@@ -24268,39 +24268,31 @@ BUILDIN_FUNC(recalculatestat) {
 
 BUILDIN_FUNC(hateffect){
 #if PACKETVER_MAIN_NUM >= 20150507 || PACKETVER_RE_NUM >= 20150429 || defined(PACKETVER_ZERO)
-	map_session_data* sd;
-
-	if( !script_rid2sd(sd) )
-		return SCRIPT_CMD_FAILURE;
-
-	int16 effectID = script_getnum(st,2);
-	bool enable = script_getnum(st,3) ? true : false;
-
-	if( effectID <= HAT_EF_MIN || effectID >= HAT_EF_MAX ){
-		ShowError( "buildin_hateffect: unsupported hat effect id %d\n", effectID );
-		return SCRIPT_CMD_FAILURE;
-	}
-
-	auto it = util::vector_get( sd->hatEffects, effectID );
-
-	if( enable ){
-		if( it != sd->hatEffects.end() ){
-			return SCRIPT_CMD_SUCCESS;
-		}
-
-		sd->hatEffects.push_back( effectID );
-	}else{
-		if( it == sd->hatEffects.end() ){
-			return SCRIPT_CMD_SUCCESS;
-		}
-
-		util::vector_erase_if_exists( sd->hatEffects, effectID );
-	}
-
-	if( !sd->state.connect_new ){
-		clif_hat_effect_single( sd, effectID, enable );
-	}
-
+ 	int16 effectID = script_getnum(st,2);
+ 	bool enable = script_getnum(st,3) ? true : false;
+ 
+	// This is unecessary and annoying half the time
+	//if( effectID <= HAT_EF_MIN || effectID >= HAT_EF_MAX ){
+	//	ShowError( "buildin_hateffect: unsupported hat effect id %d\n", effectID );
+	//	return SCRIPT_CMD_FAILURE;
+	//}
+ 
+	struct block_list* bl;
+	bool send = true;
+ 
+	if (script_hasdata(st, 4)) {
+		bl = map_id2bl(script_getnum(st, 4));
+ 	}
+	else {
+		bl = map_id2bl(st->rid);
+		map_session_data* sd = BL_CAST(BL_PC, bl);
+ 
+		if (sd && sd->state.connect_new) {
+			send = false;
+		}
+ 	}
+ 
+	unit_hateffect(bl, effectID, enable, send);
 #endif
 	return SCRIPT_CMD_SUCCESS;
 }
@@ -27566,7 +27558,7 @@ struct script_function buildin_func[] = {
 	BUILDIN_DEF(adopt,"vv"),
 	BUILDIN_DEF(getexp2,"ii?"),
 	BUILDIN_DEF(recalculatestat,""),
-	BUILDIN_DEF(hateffect,"ii"),
+	BUILDIN_DEF(hateffect,"ii?"),
 	BUILDIN_DEF(getrandomoptinfo, "i"),
 	BUILDIN_DEF(getequiprandomoption, "iii?"),
 	BUILDIN_DEF(setrandomoption,"iiiii?"),
diff --git a/src/map/unit.cpp b/src/map/unit.cpp
index f90529926..f57fcde6c 100644
--- a/src/map/unit.cpp
+++ b/src/map/unit.cpp
@@ -2964,6 +2964,9 @@ void unit_dataset(struct block_list *bl)
 	ud->attackabletime =
 	ud->canact_tick    =
 	ud->canmove_tick   = gettick();
+#if PACKETVER_MAIN_NUM >= 20150507 || PACKETVER_RE_NUM >= 20150429 || defined(PACKETVER_ZERO)
+	ud->hatEffects = {};
+#endif
 }
 
 /**
@@ -3461,10 +3464,6 @@ int unit_free(struct block_list *bl, clr_type clrtype)
 
 			sd->qi_display.clear();
 
-#if PACKETVER_MAIN_NUM >= 20150507 || PACKETVER_RE_NUM >= 20150429 || defined(PACKETVER_ZERO)
-			sd->hatEffects.clear();
-#endif
-
 			if (sd->achievement_data.achievements)
 				achievement_free(sd);
 
@@ -3645,6 +3644,14 @@ int unit_free(struct block_list *bl, clr_type clrtype)
 			break;
 		}
 	}
+	
+ 
+	if (ud) {
+#if PACKETVER_MAIN_NUM >= 20150507 || PACKETVER_RE_NUM >= 20150429 || defined(PACKETVER_ZERO)
+		ud->hatEffects.clear();
+#endif
+	}
+
 
 	map_deliddb(bl);
 
@@ -3656,6 +3663,39 @@ int unit_free(struct block_list *bl, clr_type clrtype)
 	return 0;
 }
 
+
+void unit_hateffect(struct block_list* bl, int16 effectID, bool enable, bool send)
+{
+	struct unit_data* ud;
+	map_session_data* sd;
+
+	if (!bl || !(ud = unit_bl2ud(bl)))
+		return;
+
+	sd = BL_CAST(BL_PC, bl);
+	auto it = util::vector_get(ud->hatEffects, effectID);
+
+	if (enable) {
+		if (it != ud->hatEffects.end()) {
+			return;
+		}
+
+		ud->hatEffects.push_back(effectID);
+	}
+	else {
+		if (it == ud->hatEffects.end()) {
+			return;
+		}
+
+		util::vector_erase_if_exists(ud->hatEffects, effectID);
+	}
+
+	if (send || !enable) {
+		clif_hat_effect_single(bl, effectID, enable);
+	}
+}
+
+
 static TIMER_FUNC(unit_shadowscar_timer) {
 	block_list *bl = map_id2bl(id);
 
diff --git a/src/map/unit.hpp b/src/map/unit.hpp
index cfd932615..0964d7438 100644
--- a/src/map/unit.hpp
+++ b/src/map/unit.hpp
@@ -65,6 +65,9 @@ struct unit_data {
 	int32 group_id;
 
 	std::vector<int> shadow_scar_timer;
+#if PACKETVER_MAIN_NUM >= 20150507 || PACKETVER_RE_NUM >= 20150429 || defined(PACKETVER_ZERO)
+	std::vector<int16> hatEffects;
+#endif
 };
 
 struct view_data {
@@ -115,6 +118,7 @@ bool unit_run(struct block_list *bl, map_session_data *sd, enum sc_type type);
 int unit_calc_pos(struct block_list *bl, int tx, int ty, uint8 dir);
 TIMER_FUNC(unit_delay_walktoxy_timer);
 TIMER_FUNC(unit_delay_walktobl_timer);
+void unit_hateffect(struct block_list* bl, int16 effectID, bool enable, bool send);
 
 // Causes the target object to stop moving.
 int unit_stop_walking(struct block_list *bl,int type);

You'll be able to use hat effects on NPCs as well. Goodluck.

Edit: Updated diff to fix an error with the script function.

hateffects.diff

Edited by Tokei
  • Upvote 1
  • Love 1
  • MVP 2
Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  3
  • Topics Per Day:  0.01
  • Content Count:  11
  • Reputation:   0
  • Joined:  03/13/23
  • Last Seen:  

Thank you very much,
I've tried it and it works!

 

Hello everyone, I want to use this hateffect on NPC OnInit, and I have tried to put it in OnInit event. But it doesn't work. Are there any ways to make it work? How can I do?

Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  16
  • Topics Per Day:  0.00
  • Content Count:  662
  • Reputation:   671
  • Joined:  11/12/12
  • Last Seen:  

6 hours ago, kpcamber said:

Hello everyone, I want to use this hateffect on NPC OnInit, and I have tried to put it in OnInit event. But it doesn't work. Are there any ways to make it work? How can I do?

Ah, that's my bad, I apparently didn't remove the player check in the script function. Change it to:

BUILDIN_FUNC(hateffect){
#if PACKETVER_MAIN_NUM >= 20150507 || PACKETVER_RE_NUM >= 20150429 || defined(PACKETVER_ZERO)
 	int16 effectID = script_getnum(st,2);
 	bool enable = script_getnum(st,3) ? true : false;
 
	// This is unecessary and annoying half the time
	//if( effectID <= HAT_EF_MIN || effectID >= HAT_EF_MAX ){
	//	ShowError( "buildin_hateffect: unsupported hat effect id %d\n", effectID );
	//	return SCRIPT_CMD_FAILURE;
	//}
 
	struct block_list* bl;
	bool send = true;
 
	if (script_hasdata(st, 4)) {
		bl = map_id2bl(script_getnum(st, 4));
 	}
	else {
		bl = map_id2bl(st->rid);
		map_session_data* sd = BL_CAST(BL_PC, bl);
 
		if (sd && sd->state.connect_new) {
			send = false;
		}
 	}
 
	unit_hateffect(bl, effectID, enable, send);
#endif
	return SCRIPT_CMD_SUCCESS;
}
Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  3
  • Topics Per Day:  0.01
  • Content Count:  11
  • Reputation:   0
  • Joined:  03/13/23
  • Last Seen:  

Thank you very much. I will try it.

Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  48
  • Topics Per Day:  0.02
  • Content Count:  180
  • Reputation:   6
  • Joined:  10/22/18
  • Last Seen:  

On 7/30/2023 at 10:53 PM, kpcamber said:

Hello everyone, I want to use this hateffect on NPC OnInit, and I have tried to put it in OnInit event. But it doesn't work. Are there any ways to make it work? How can I do?

how do you use it on NPC OnInit event? mind to show the examples of the script commands?

thanks

Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  1
  • Topics Per Day:  0.00
  • Content Count:  4
  • Reputation:   1
  • Joined:  06/20/18
  • Last Seen:  

prontera,155,185,5	script	TEST	1_F_MARIA,{
    monster "prontera", 154, 182, "--ja--", 1002, 1;
    hateffect 12, true, $@mobid;

OnInit:
	.@npc_id = getnpcid(0);
	hateffect 12, true, .@npc_id;
	end;
}

Example for applying on NPC/Monsters

Edited by My Memory
  • Upvote 1
Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  48
  • Topics Per Day:  0.02
  • Content Count:  180
  • Reputation:   6
  • Joined:  10/22/18
  • Last Seen:  

10 minutes ago, My Memory said:
prontera,155,185,5	script	TEST	1_F_MARIA,{
    monster "prontera", 154, 182, "--ja--", 1002, 1;
    hateffect 12, true, $@mobid;

OnInit:
	.@npc_id = getnpcid(0);
	hateffect 12, true, .@npc_id;
	end;
}

Example for applying on NPC/Monsters

Cool. Thanks mate 

Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  3
  • Topics Per Day:  0.01
  • Content Count:  11
  • Reputation:   0
  • Joined:  03/13/23
  • Last Seen:  

On 7/31/2023 at 5:09 AM, Tokei said:

Ah, that's my bad, I apparently didn't remove the player check in the script function. Change it to:

BUILDIN_FUNC(hateffect){
#if PACKETVER_MAIN_NUM >= 20150507 || PACKETVER_RE_NUM >= 20150429 || defined(PACKETVER_ZERO)
 	int16 effectID = script_getnum(st,2);
 	bool enable = script_getnum(st,3) ? true : false;
 
	// This is unecessary and annoying half the time
	//if( effectID <= HAT_EF_MIN || effectID >= HAT_EF_MAX ){
	//	ShowError( "buildin_hateffect: unsupported hat effect id %d\n", effectID );
	//	return SCRIPT_CMD_FAILURE;
	//}
 
	struct block_list* bl;
	bool send = true;
 
	if (script_hasdata(st, 4)) {
		bl = map_id2bl(script_getnum(st, 4));
 	}
	else {
		bl = map_id2bl(st->rid);
		map_session_data* sd = BL_CAST(BL_PC, bl);
 
		if (sd && sd->state.connect_new) {
			send = false;
		}
 	}
 
	unit_hateffect(bl, effectID, enable, send);
#endif
	return SCRIPT_CMD_SUCCESS;
}

Thanks bro, it's working now.

Link to comment
Share on other sites

  • 0

  • Group:  Members
  • Topic Count:  4
  • Topics Per Day:  0.00
  • Content Count:  11
  • Reputation:   1
  • Joined:  06/26/18
  • Last Seen:  

Hello friend, good evening, could you help me with the system you posted about hateffect? I use a 2021 emulator so I'm getting an error in the script you posted

My git : https://github.com/rathena/rathena/tree/d6a1c03b390a0b40c2657d26429ac85056ce8cd7

Please Help. Thanks

Captura de tela 2024-01-04 144638.png

@Tokei please help

Edited by gabrielks
  • Upvote 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...