-
Posts
629 -
Joined
-
Last visited
-
Days Won
83
Tokei last won the day on August 6
Tokei had the most liked content!
Profile Information
-
Gender
Male
-
Location
Canada
Tokei's Achievements
-
This should be fixed now, sorry about that: 1.8.5.3
-
I added the encryption commands (setKey, encrypt, decrypt) to it in 1.8.5.1. Here's an example: -open test.thor -setKey mykey.grfkey -encrypt -save Where the mykey.grfkey is the file version of your password. You can generate this file via Tool > GRF Encryption:
-
Well, it seems there's a problem with the custom decompression library you're using...? Not sure what's up there, but you'll probably want to change it to the default compression library. If you have issues loading the default compression library, you'll need to install some VC++ libraries: For Gravity Official Zlib Library (cps.dll), you'll have to install VC++ 2010 (x86). For LZMA Library (by Curiosity, lzma.dll), you'll have to install VC++ 2005 (x86). Same issue as above (most likely). lzma.dll requires VC++ 2005 (x86). You only appear to have x64, which is not compatible.
-
Error when unloading and reloading script need '('
Tokei replied to kalabasa's question in Scripting Support
Functions don't get unloaded when you reload a script. So the script engine thinks that Class_Mastery is a function since it was previously defined here: function script Class_Mastery { But you're using it as a constant variable... everywhere. Either change the names around, like F_Class_Mastery, or remove the function altogether. It feels like you're using this function on an item script, so changing it to F_Class_Mastery would be enough. (Also, you might want to use proper formatting, it's very hard to read.) -
If they aren't in your data.grf, then your data.grf isn't the latest. You have a few options available. The easiest option is to download one of the "latest" kRO full client on rAthena, this thread appears to be the most active one: Then use Ragnarok.exe to patch your game afterwards. If your "latest" kRO full client above didn't bother to add the official Gravity patcher (Ragnarok.exe), then you can use the one from Ai4rei here: http://nn.ai4rei.net/dev/rsu/#download (use kRO RAG) and patch the data.grf directly with it. By the looks of it though, the thread above provided the rsu patcher directly so might as well use that. The harder option is to go on https://ro.gnjoy.com and download the official RO game (though I think you have to register first, which may be a problem? Not sure, haven't done that in a while).
-
Missing LUB files most likely. Seeing as the error title is "package item", I'm assuming there's something wrong with this file: data\luafiles514\lua files\selectpackage\selectpackageitem.lub That'd be my guess.
-
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; }
-
Hello, the final GRF size is the problem here and your texture GRF being 800MB on its own doesn't mean much without knowing the size of the base GRF. That error is shown if the file table offset in the final GRF goes past the 4GB size limit. There's not much I can tell without more information on your end though. Perhaps your GRFs are compacted using the "redirect indexes" option, which makes them seem smaller than they really are. When merging, if the conditions aren't perfect, the GRFs will be unpacted first and then merged together which can trigger the 4GB limit more easily. It's either that or the base GRF size is near 3.4+GB. None of that is helpful at the end of the day though, it seems like you will have to make a new GRF alongside instead of trying to keep compressing/removing stuff in it. There's really not much to do once you reach the size limit and the obvious solution is simply to have another GRF in your RO folder to save a lot of future headaches.
-
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
-
Heya, There isn't anything you can do from the STR file itself. I remember ez2streffect.bson allowing you to change that behavior, but I believe you can't add custom skills in there. So that won't do. Your atlernative is to use hat effects, with "isRenderBeforeCharacter = true" (mini-guide below). Though that requires a lot more source edits on your end since there is currently no support for that behavior (and it's not that well known apparently?). To be clear, yes this can be used on a targeted cell and not only on top of your character. It creates a dummy hidden NPC on the cell and then show a hat effect on that NPC instead. Here's the end result: Mini-guide: Add the effect via data\luafiles514\lua files\hateffectinfo\hateffectinfo.lub using a "reasonable" ID (some IDs just don't work, who knows why). For example: [100] = { resourceFileName = "new_earthdrive\\new_earthdrive_bottom\\new_earthdrive_bottom.str", hatEffectPos = -4, hatEffectPosX = 0, isRenderBeforeCharacter = true, isIgnoreRiding = true, isAdjustPositionWhenShrinkState = false, isAdjustSizeWhenShrinkState = false }, Apply these changes: diff --git a/db/re/skill_db.yml b/db/re/skill_db.yml index cfd23900c..fbb59d834 100644 --- a/db/re/skill_db.yml +++ b/db/re/skill_db.yml @@ -46484,3 +46484,11 @@ Body: Duration1: 10000 Cooldown: 60000 Status: Emergency_Move + - Id: 10100 + Name: NPC_HATEFFECT_POS + Description: Hateffect Pos + MaxLevel: 1 + TargetType: Self + DamageFlags: + NoDamage: true + diff --git a/src/map/clif.cpp b/src/map/clif.cpp index 991b5b1b8..1540d9083 100644 --- a/src/map/clif.cpp +++ b/src/map/clif.cpp @@ -5449,6 +5449,26 @@ void clif_getareachar_skillunit(struct block_list *bl, struct skill_unit *unit, if (bl->type == BL_PC) fd = ((TBL_PC*)bl)->fd; + if (unit->group->skill_id == NPC_HATEFFECT_POS) { + // Comment below if you want the effect to show up after using @refresh (not default behavior for skills, that's only the case for ground units) + if (target == SELF) { + return; + } + + struct npc_data npc; + + memset(&npc, 0, sizeof(struct npc_data)); + + npc.bl = unit->bl; + npc.bl.type = BL_NPC; + npc.name[0] = '\0'; + npc.vd.class_ = 139; + + clif_set_unit_idle(&npc.bl, false, target, bl); + clif_hat_effects2(bl, &unit->bl, unit->group->skill_lv, true, target); + return; + } + if (unit->group->state.guildaura) return; @@ -5564,6 +5584,14 @@ void clif_skill_delunit(struct skill_unit *unit) nullpo_retv(unit); + if (unit->group && unit->group->skill_id == NPC_HATEFFECT_POS) { + WBUFW(buf, 0) = 0x80; + WBUFL(buf, 2) = unit->bl.id; + WBUFB(buf, 6) = CLR_OUTSIGHT; + clif_send(buf, packet_len(0x80), &unit->bl, ALL_SAMEMAP); + return; + } + WBUFW(buf, 0)=0x120; WBUFL(buf, 2)=unit->bl.id; clif_send(buf,packet_len(0x120),&unit->bl,AREA); @@ -21218,6 +21246,25 @@ void clif_hat_effects( map_session_data* sd, struct block_list* bl, enum send_ta #endif } +/// Send hat effects to the client (ZC_HAT_EFFECT). +/// 0A3B <Length>.W <AID>.L <Status>.B { <HatEffectId>.W } +void clif_hat_effects2(struct block_list* src, struct block_list* effect_bl, uint16 effect_id, bool enable, enum send_target target) { +#if PACKETVER_MAIN_NUM >= 20150507 || PACKETVER_RE_NUM >= 20150429 || defined(PACKETVER_ZERO) + unsigned char buf[13]; + + if (!effect_bl || !src) + return; + + WBUFW(buf, 0) = 0xa3b; + WBUFW(buf, 2) = 13; + WBUFL(buf, 4) = effect_bl->id; + WBUFB(buf, 8) = enable; + WBUFL(buf, 9) = effect_id; + + clif_send(buf, 13, src, target); +#endif +} + void clif_hat_effect_single( map_session_data* sd, uint16 effectId, bool enable ){ #if PACKETVER_MAIN_NUM >= 20150507 || PACKETVER_RE_NUM >= 20150429 || defined(PACKETVER_ZERO) nullpo_retv( sd ); diff --git a/src/map/clif.hpp b/src/map/clif.hpp index 1bf10b262..c8f47b049 100644 --- a/src/map/clif.hpp +++ b/src/map/clif.hpp @@ -802,6 +802,7 @@ 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_effects2(struct block_list* src, struct block_list* effect_bl, uint16 effect_id, bool enable, enum send_target target); void clif_hat_effect_single( map_session_data* sd, uint16 effectId, bool enable ); void clif_item_skill(map_session_data *sd,uint16 skill_id,uint16 skill_lv); diff --git a/src/map/script.cpp b/src/map/script.cpp index 027587945..a261e64ec 100644 --- a/src/map/script.cpp +++ b/src/map/script.cpp @@ -26896,6 +26896,36 @@ BUILDIN_FUNC(getfamerank) { return SCRIPT_CMD_SUCCESS; } +BUILDIN_FUNC(showhateffectpos) { + int hat_effect_id = script_getnum(st, 2); + int x = script_getnum(st, 3); + int y = script_getnum(st, 4); + int duration = script_getnum(st, 5); + struct block_list* bl; + + if (script_hasdata(st, 6)) { + bl = map_id2bl(script_getnum(st, 6)); + } + else { + bl = map_id2bl(st->oid); + } + + if (!bl) { + return SCRIPT_CMD_FAILURE; + } + + std::shared_ptr<s_skill_unit_group> group = skill_unitsetting(bl, NPC_HATEFFECT_POS, hat_effect_id, x, y, duration); + + if (group != NULL) { + script_pushint(st, group->group_id); + } + else { + script_pushint(st, -1); + } + + return SCRIPT_CMD_SUCCESS; +} + BUILDIN_FUNC(isdead) { map_session_data *sd; @@ -27680,6 +27710,7 @@ struct script_function buildin_func[] = { BUILDIN_DEF(getfame, "?"), BUILDIN_DEF(getfamerank, "?"), BUILDIN_DEF(isdead, "?"), + BUILDIN_DEF(showhateffectpos, "iiii?"), BUILDIN_DEF(macro_detector, "?"), #include <custom/script_def.inc> diff --git a/src/map/skill.cpp b/src/map/skill.cpp index 611aff452..c9a695768 100755 --- a/src/map/skill.cpp +++ b/src/map/skill.cpp @@ -15058,6 +15058,12 @@ std::shared_ptr<s_skill_unit_group> skill_unitsetting(struct block_list *src, ui case WH_FLAMETRAP: limit += 3000 * (sd ? pc_checkskill(sd, WH_ADVANCED_TRAP) : 5); break; + case NPC_HATEFFECT_POS: + limit = flag; + interval = flag + 1000; + flag = 0; + val2 = skill_lv; + break; } // Init skill unit group @@ -15702,6 +15708,9 @@ int skill_unit_onplace_timer(struct skill_unit *unit, struct block_list *bl, t_t case UNT_DUMMYSKILL: switch (sg->skill_id) { + case NPC_HATEFFECT_POS: + // don't do anything for this skill + break; case SG_SUN_WARM: //SG skills [Komurka] case SG_MOON_WARM: case SG_STAR_WARM: { @@ -20500,6 +20509,9 @@ int skill_delunit(struct skill_unit* unit) tsc->getSCE(SC__MANHOLE)->val4 = 0; // Remove the Unit ID } break; + case NPC_HATEFFECT_POS: + clif_hat_effects2(&unit->bl, &unit->bl, unit->group->skill_lv, false, ALL_SAMEMAP); + break; } clif_skill_delunit(unit); @@ -20734,6 +20746,9 @@ int skill_delunitgroup_(std::shared_ptr<s_skill_unit_group> group, const char* f } } break; + case NPC_HATEFFECT_POS: + clif_hat_effects2(&group->unit->bl, &group->unit->bl, group->skill_lv, false, ALL_SAMEMAP); + break; } if (src->type==BL_PC && group->state.ammo_consume) diff --git a/src/map/skill.hpp b/src/map/skill.hpp index c22e0ad70..04dc782d9 100644 --- a/src/map/skill.hpp +++ b/src/map/skill.hpp @@ -2494,6 +2494,8 @@ enum e_skill { ABR_NET_REPAIR, ABR_NET_SUPPORT, ABR_INFINITY_BUSTER, + + NPC_HATEFFECT_POS = 10100, }; /// The client view ids for land skills. Call the effect from the source with something like this (100 being your effect ID): case NPC_CUSTOM_SKILL: // skill related stuff... skill_unitsetting(src, NPC_HATEFFECT_POS, 100, x, y, 2000); break; or if you want to test first with the script command .@effect_id = 100; .@x = 152; .@y = 187; .@duration = 2000; showhateffectpos .@effect_id, .@x, .@y, .@duration; The downside of this method is that the hat effects always loop. So you have to know in advance the duration of the effect. You also probably want to add some empty frames at the end of your STR animation for some buffer and prevent the loop from showing up at all. Best solution I can think of, goodluck! hateffectpos.diff
-
Well, the error itself isn't too helpful. 0x8b3 is clif_showscript. So one of the possible cause is a script sending "showscript" (a script command) to a player too many times, probably in an infinity loop would be my guess. Though, the error message only shows the last packet that exceeded the length of the connection buffer, so a prior packet could be responsible too. It's hard to know for sure. If the error is somewhat new, then you should know if this rings a bell or not. If you still can't figure it out, then you could dump the last packet in your console (in socket.cpp): ShowDump(s->wdata + s->wdata_size, len); ShowError("WFIFOSET: Maximum write buffer size for client connection %d exceeded, most likely caused by packet 0x%04x (len=%" PRIuPTR ", ip=%lu.%lu.%lu.%lu).\n", fd, WFIFOW(fd,0), len, CONVIP(s->client_addr)); Then you can see what the string used by showscript was and track down the issue a bit more easily. If nothing else, then you'd have to dump the entire write butter, but hopefully you won't have to do that. Goodluck!
-
Well your links are not uploaded properly, so I can't see. Though, the gif format doesn't allow transparency. Most people will simply pick a black background as it is what would yield the best results.
-
Well, ground units (Land Protector and traps) do disappear by themselves when you change map. That is the default behavior and it's handled by this code in pc_setpos: if (battle_config.clear_unit_onwarp&BL_PC) skill_clear_unitgroup(&sd->bl); You can copy this code in pc_dead if you want to do make ground units disappear on player death as well.
-
That's not really possible without rewritting most of the emulator. Everything is made with the assumption that the account ID is unique to a player. A simple example would be a script function like "rid2name". Which name should that return, since they both players have the same rid (the rid is the account ID, to be clear)? Plus, that's the easy part. Imagine using a storage on two characters in the same account; you'd be able to dupe items left and right and that's just one scenario.
-
Well, it looks like it managed to read the GRF fine so someone probably just changed the header for whatever reason. It gives you that error because that's not what is expected at all from the GRF format. You can hex the file manually and change the start to "Master of Magic\0". You might be able to just save the GRF again as well and it will fix the issue...? It managed to load it anyway, so you could just keep using the GRF normally.