kpcamber Posted July 7, 2023 Group: Members Topic Count: 3 Topics Per Day: 0.00 Content Count: 11 Reputation: 0 Joined: 03/13/23 Last Seen: Wednesday at 12:45 AM Share Posted July 7, 2023 how to use "hateffect" in the monster ? Please help me ! Quote Link to comment Share on other sites More sharing options...
1 Tokei Posted July 7, 2023 Group: Members Topic Count: 16 Topics Per Day: 0.00 Content Count: 695 Reputation: 721 Joined: 11/12/12 Last Seen: Friday at 09:15 PM Share Posted July 7, 2023 (edited) 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 July 30, 2023 by Tokei 1 2 2 Quote Link to comment Share on other sites More sharing options...
1 gabrielks Posted December 18, 2023 Group: Members Topic Count: 4 Topics Per Day: 0.00 Content Count: 11 Reputation: 2 Joined: 06/26/18 Last Seen: 1 hour ago Share Posted December 18, 2023 (edited) 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 @Tokei please help Edited January 4, 2024 by gabrielks 2 Quote Link to comment Share on other sites More sharing options...
0 kpcamber Posted July 30, 2023 Group: Members Topic Count: 3 Topics Per Day: 0.00 Content Count: 11 Reputation: 0 Joined: 03/13/23 Last Seen: Wednesday at 12:45 AM Author Share Posted July 30, 2023 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? Quote Link to comment Share on other sites More sharing options...
0 Tokei Posted July 30, 2023 Group: Members Topic Count: 16 Topics Per Day: 0.00 Content Count: 695 Reputation: 721 Joined: 11/12/12 Last Seen: Friday at 09:15 PM Share Posted July 30, 2023 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; } 1 Quote Link to comment Share on other sites More sharing options...
0 kpcamber Posted August 1, 2023 Group: Members Topic Count: 3 Topics Per Day: 0.00 Content Count: 11 Reputation: 0 Joined: 03/13/23 Last Seen: Wednesday at 12:45 AM Author Share Posted August 1, 2023 Thank you very much. I will try it. Quote Link to comment Share on other sites More sharing options...
0 Frost Diver Posted August 5, 2023 Group: Members Topic Count: 48 Topics Per Day: 0.02 Content Count: 188 Reputation: 7 Joined: 10/22/18 Last Seen: 17 hours ago Share Posted August 5, 2023 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 Quote Link to comment Share on other sites More sharing options...
0 Haydrich Posted August 9, 2023 Group: Members Topic Count: 1 Topics Per Day: 0.00 Content Count: 4 Reputation: 2 Joined: 06/20/18 Last Seen: Saturday at 05:55 PM Share Posted August 9, 2023 (edited) 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 August 9, 2023 by My Memory 2 Quote Link to comment Share on other sites More sharing options...
0 Frost Diver Posted August 9, 2023 Group: Members Topic Count: 48 Topics Per Day: 0.02 Content Count: 188 Reputation: 7 Joined: 10/22/18 Last Seen: 17 hours ago Share Posted August 9, 2023 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 Quote Link to comment Share on other sites More sharing options...
0 kpcamber Posted August 26, 2023 Group: Members Topic Count: 3 Topics Per Day: 0.00 Content Count: 11 Reputation: 0 Joined: 03/13/23 Last Seen: Wednesday at 12:45 AM Author Share Posted August 26, 2023 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. Quote Link to comment Share on other sites More sharing options...
Question
kpcamber
how to use "hateffect" in the monster ?
Please help me !
Link to comment
Share on other sites
9 answers to this question
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.