Jump to content

joecalis

Members
  • Posts

    64
  • Joined

  • Last visited

  • Days Won

    7

Everything posted by joecalis

  1. I don't know what you're trying to accomplish, I thought you wanted party member's hp to be seen even while in gvg map. If you want party member's hp to be seen while cloaked, that's different since it is not visible by party members by default. (Check edit at the bottom) Here is what my unedited server (default settings) look like when a party member is cloaked/hidden. vlc-record-2023-05-13-15h48m49s-2023-05-13 15-46-17.mp4-.mp4 Anyway these are the codes that work for me without the cloaking thing: void clif_hpmeter_single(int fd, int id, unsigned int hp, unsigned int maxhp) { struct map_session_data* sd = map_id2sd(id); struct map_session_data* tsd = (struct map_session_data*)session[fd]->session_data; bool sameparty = false; bool isBg = false; if (sd && tsd && (sd->sc.option & (OPTION_HIDE | OPTION_CLOAK | OPTION_CHASEWALK) || sd->special_state.perfect_hiding || map_flag_gvg(sd->bl.m))) { if (sd->status.party_id && tsd->status.party_id && sd->status.party_id == tsd->status.party_id) sameparty = true; if (sd->bg_id && tsd->bg_id && sd->bg_id == tsd->bg_id) isBg = true; if (!sameparty && !isBg) return; } #if PACKETVER < 20100126 const int cmd = 0x106; #else const int cmd = 0x80e; #endif WFIFOHEAD(fd,packet_len(cmd)); WFIFOW(fd,0) = cmd; WFIFOL(fd,2) = id; #if PACKETVER < 20100126 if( maxhp > INT16_MAX ) {// To correctly display the %hp bar. [Skotlex] WFIFOW(fd,6) = hp/(maxhp/100); WFIFOW(fd,8) = 100; } else { WFIFOW(fd,6) = hp; WFIFOW(fd,8) = maxhp; } #else WFIFOL(fd,6) = hp; WFIFOL(fd,10) = maxhp; #endif WFIFOSET(fd, packet_len(cmd)); } static int clif_hpmeter_sub(struct block_list *bl, va_list ap) { struct map_session_data *sd, *tsd; #if PACKETVER < 20100126 const int cmd = 0x106; #else const int cmd = 0x80e; #endif sd = va_arg(ap, struct map_session_data *); tsd = (TBL_PC *)bl; nullpo_ret(sd); nullpo_ret(tsd); if( !tsd->fd || tsd == sd ) return 0; if (!pc_has_permission(tsd, PC_PERM_VIEW_HPMETER)) return 0; bool sameparty = false; bool isBg = false; if (sd->sc.option & (OPTION_HIDE | OPTION_CLOAK | OPTION_CHASEWALK) || sd->special_state.perfect_hiding || map_flag_gvg(sd->bl.m)) { if (sd->status.party_id && tsd->status.party_id && sd->status.party_id == tsd->status.party_id) sameparty = true; if (sd->bg_id && tsd->bg_id && sd->bg_id == tsd->bg_id) isBg = true; if(!sameparty && !isBg) return 0; } WFIFOHEAD(tsd->fd,packet_len(cmd)); WFIFOW(tsd->fd,0) = cmd; WFIFOL(tsd->fd,2) = sd->status.account_id; #if PACKETVER < 20100126 if( sd->battle_status.max_hp > INT16_MAX ) { //To correctly display the %hp bar. [Skotlex] WFIFOW(tsd->fd,6) = sd->battle_status.hp/(sd->battle_status.max_hp/100); WFIFOW(tsd->fd,8) = 100; } else { WFIFOW(tsd->fd,6) = sd->battle_status.hp; WFIFOW(tsd->fd,8) = sd->battle_status.max_hp; } #else WFIFOL(tsd->fd,6) = sd->battle_status.hp; WFIFOL(tsd->fd,10) = sd->battle_status.max_hp; #endif WFIFOSET(tsd->fd,packet_len(cmd)); return 0; } For the cloaking/hiding I'll have to look at it some other time. Edit: NVM I found an easy fix to the cloaking/hiding thing Find: //Whenever we send "changeoption" to the client, the provoke icon is lost //There is probably an option for the provoke icon, but as we don't know it, we have to do this for now if (sc->data[SC_PROVOKE]) { const struct TimerData *td = get_timer(sc->data[SC_PROVOKE]->timer); clif_status_change(bl, StatusIconChangeTable[SC_PROVOKE], 1, (!td ? INFINITE_TICK : DIFF_TICK(td->tick, gettick())), 0, 0, 0); } Change To: //Whenever we send "changeoption" to the client, the provoke icon is lost //There is probably an option for the provoke icon, but as we don't know it, we have to do this for now if (sc->data[SC_PROVOKE]) { const struct TimerData *td = get_timer(sc->data[SC_PROVOKE]->timer); clif_status_change(bl, StatusIconChangeTable[SC_PROVOKE], 1, (!td ? INFINITE_TICK : DIFF_TICK(td->tick, gettick())), 0, 0, 0); } if (sd) clif_hpmeter(sd); It seems that the party member hp doesn't show when you cloak in front of other party members but if you walk away outside of their screen then walk back it'll show, so I just made it that if you cloak you'll send your hpmeter to everyone in screen range.
  2. Try to change this: if (unit->group->skill_id == PF_SPIDERWEB && unit->bl.id != srcunit->bl.id && unit->group->src_id == src->id) { //skill_delunitgroup(unit->group); // This one is instant Delete unit->limit = min(unit->limit,1000); // This one you can change "1000" to change the timing (lower number = faster deletion) unit->group->limit = unit->limit; return 1; } to this: if (unit->group->skill_id == PF_SPIDERWEB && unit->bl.id != srcunit->bl.id && unit->group->src_id == src->id && unit->group->val2) { //skill_delunitgroup(unit->group); // This one is instant Delete unit->limit = min(unit->limit,1000); // This one you can change "1000" to change the timing (lower number = faster deletion) unit->group->limit = unit->limit; return 1; }
  3. You tried OnPCCalcStatEvent which doesn't exists try: OnPCStatCalcEvent
  4. change this: if(sd && (sd->sc.option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) || sd->special_state.perfect_hiding || map_flag_gvg(sd->bl.m))) return; to this: struct map_session_data* tsd = (struct map_session_data*)session[fd]->session_data; if (sd && tsd && (sd->status.party_id && tsd->status.party_id && sd->status.party_id != tsd->status.party_id) && (sd->sc.option & (OPTION_HIDE | OPTION_CLOAK | OPTION_CHASEWALK) || sd->special_state.perfect_hiding || map_flag_gvg(sd->bl.m))) return; change second code: if (sd->sc.option & (OPTION_HIDE | OPTION_CLOAK | OPTION_CHASEWALK) || sd->special_state.perfect_hiding || map_flag_gvg(sd->bl.m)) return 0; to this: if ((sd->status.party_id && tsd->status.party_id && sd->status.party_id != tsd->status.party_id) && (sd->sc.option & (OPTION_HIDE | OPTION_CLOAK | OPTION_CHASEWALK) || sd->special_state.perfect_hiding || map_flag_gvg(sd->bl.m))) return 0;
  5. In the last code I provided just change this: if(sd && (sd->sc.option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) || sd->special_state.perfect_hiding)) return; to this: if(sd && (sd->sc.option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) || sd->special_state.perfect_hiding || map_flag_gvg(sd->bl.m))) return; then the second one: if (sd->sc.option & (OPTION_HIDE | OPTION_CLOAK | OPTION_CHASEWALK) || sd->special_state.perfect_hiding) return 0; to this: if (sd->sc.option & (OPTION_HIDE | OPTION_CLOAK | OPTION_CHASEWALK) || sd->special_state.perfect_hiding || map_flag_gvg(sd->bl.m)) return 0;
  6. Try this: /*========================================== * Sends HP bar to a single fd. [Skotlex] *------------------------------------------*/ void clif_hpmeter_single(int fd, int id, unsigned int hp, unsigned int maxhp) { struct map_session_data* sd = map_id2sd(id); if(sd && (sd->sc.option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) || sd->special_state.perfect_hiding)) return; #if PACKETVER < 20100126 const int cmd = 0x106; #else const int cmd = 0x80e; #endif WFIFOHEAD(fd,packet_len(cmd)); WFIFOW(fd,0) = cmd; WFIFOL(fd,2) = id; #if PACKETVER < 20100126 if( maxhp > INT16_MAX ) {// To correctly display the %hp bar. [Skotlex] WFIFOW(fd,6) = hp/(maxhp/100); WFIFOW(fd,8) = 100; } else { WFIFOW(fd,6) = hp; WFIFOW(fd,8) = maxhp; } #else WFIFOL(fd,6) = hp; WFIFOL(fd,10) = maxhp; #endif WFIFOSET(fd, packet_len(cmd)); } Then find this: if( !tsd->fd || tsd == sd ) return 0; if (!pc_has_permission(tsd, PC_PERM_VIEW_HPMETER)) return 0; WFIFOHEAD(tsd->fd,packet_len(cmd)); Change it to this: if( !tsd->fd || tsd == sd ) return 0; if (!pc_has_permission(tsd, PC_PERM_VIEW_HPMETER)) return 0; if (sd->sc.option & (OPTION_HIDE | OPTION_CLOAK | OPTION_CHASEWALK) || sd->special_state.perfect_hiding) return 0; WFIFOHEAD(tsd->fd,packet_len(cmd));
  7. in clif.cpp Find: void clif_hpmeter_single( map_session_data& sd, uint32 id, uint32 hp, uint32 maxhp ){ struct PACKET_ZC_NOTIFY_HP_TO_GROUPM p = {}; Change To: void clif_hpmeter_single( map_session_data& sd, uint32 id, uint32 hp, uint32 maxhp ){ struct PACKET_ZC_NOTIFY_HP_TO_GROUPM p = {}; map_session_data* dstsd = map_id2sd(id); if (dstsd && (dstsd->sc.option & (OPTION_HIDE | OPTION_CLOAK | OPTION_CHASEWALK) || dstsd->special_state.perfect_hiding)) return;
  8. Remove what ever code I sent before, and do this instead. in skill.cpp Find: int skill_greed(struct block_list *bl, va_list ap); static int skill_cell_overlap(struct block_list *bl, va_list ap); Change To: int skill_greed(struct block_list *bl, va_list ap); static int skill_web_remover(struct block_list *bl, va_list ap); static int skill_cell_overlap(struct block_list *bl, va_list ap); Find: // Execute on all targets standing on this cell if (range == 0 && active_flag) map_foreachincell(skill_unit_effect,unit->bl.m,unit->bl.x,unit->bl.y,group->bl_flag,&unit->bl,gettick(),1); Change To: if (skill_id == PF_SPIDERWEB) map_foreachinarea(skill_web_remover, src->m, x - 1, y - 1, x + 1, y + 1, BL_SKILL, src, unit); // Execute on all targets standing on this cell if (range == 0 && active_flag) map_foreachincell(skill_unit_effect,unit->bl.m,unit->bl.x,unit->bl.y,group->bl_flag,&unit->bl,gettick(),1); Find: /*========================================== * Check new skill unit cell when overlapping in other skill unit cell. * Catched skill in cell value pushed to *unit pointer. * Set (*alive) to 0 will ends 'new unit' check *------------------------------------------*/ static int skill_cell_overlap(struct block_list *bl, va_list ap) Change To: static int skill_web_remover(struct block_list* bl, va_list ap) { struct block_list* src; struct skill_unit* srcunit; struct skill_unit* unit; src = va_arg(ap, struct block_list*); srcunit = va_arg(ap, struct skill_unit*); unit = (struct skill_unit*)bl; if (unit == NULL || unit->group == NULL) return 0; if (unit->group->skill_id == PF_SPIDERWEB && unit->bl.id != srcunit->bl.id && unit->group->src_id == src->id) { //skill_delunitgroup(unit->group); // This one is instant Delete unit->limit = min(unit->limit,1000); // This one you can change "1000" to change the timing (lower number = faster deletion) unit->group->limit = unit->limit; return 1; } return 0; } /*========================================== * Check new skill unit cell when overlapping in other skill unit cell. * Catched skill in cell value pushed to *unit pointer. * Set (*alive) to 0 will ends 'new unit' check *------------------------------------------*/ static int skill_cell_overlap(struct block_list *bl, va_list ap) This line you can change depending on what you prefer. //skill_delunitgroup(unit->group); // This one is instant Delete unit->limit = min(unit->limit,1000); // This one you can change "1000" to change the timing (lower number = faster deletion) unit->group->limit = unit->limit; If you want to make web instantly vanish remove the "//" before the skill_delunitgroup then put "//" before unit->limit and unit->group->limit If you want to change the speed of when it disappears edit the "1000" to any number you want, it's in milliseconds. This however deletes nearby webs even if you don't have a target and will only delete your own web vlc-record-2023-05-10-17h19m40s-2023-05-10 17-17-32.mp4-.mp4
  9. no it's not. The bubblegum you are using adds 100% drop chance that's why it's the same. Try using bubblegum id: 12264 that one adds 200% drop chance
  10. in unit.cpp Find: // SC_MAGICPOWER needs to switch states at start of cast skill_toggle_magicpower(src, skill_id); Change To: // SC_MAGICPOWER needs to switch states at start of cast skill_toggle_magicpower(src, skill_id); if (sd && skill_id == PF_SPIDERWEB && !skill_pos_maxcount_check(src, skill_x, skill_y, skill_id, skill_lv, BL_PC, false)) { int oldweb = -1; int webid = 0; for (int i = 0; i < MAX_SKILLUNITGROUP && sd->ud.skillunit[i]; i++) { if (sd->ud.skillunit[i]->skill_id == skill_id) { if (webid == 0) { webid = sd->ud.skillunit[i]->group_id; oldweb = i; } else if (webid != 0 && sd->ud.skillunit[i]->group_id < webid) { webid = sd->ud.skillunit[i]->group_id; oldweb = i; } } } if (oldweb >= 0) { skill_delunitgroup(sd->ud.skillunit[oldweb]); } } This will delete the oldest active spider web when you try to cast it while it is at max count. You can change the maxcount in skill_db.txt to any number under 25 to raise the limit before web deletion. Edit: Sorry I placed the code before requirement checks, but its fixed now.
  11. in status.cpp Find: case SC_SIGNUMCRUCIS: // Only affects demons and undead element (but not players) if((!undead_flag && status->race!=RC_DEMON) || bl->type == BL_PC) return 0; break; Change To: case SC_SIGNUMCRUCIS: // Now affects all monsters (but not players) if(bl->type == BL_PC) return 0; break;
  12. change to this: for (i = 0; i < MAX_MOB_DROP_TOTAL; i++) { if (mob->dropitem[i].nameid == 0 || mob->dropitem[i].rate < 1) continue; std::shared_ptr<item_data> id = item_db.find(mob->dropitem[i].nameid); if (id == nullptr) continue; int droprate = apply_rate(mob->dropitem[i].rate, drop_modifier); //mob_getdroprate( &sd->bl, mob, mob->dropitem[i].rate, drop_modifier ); // Cap it to 100% droprate = min(droprate, 10000); // If the monster's drop rate can become 0 if (battle_config.drop_rate0item) { droprate = max(droprate, 0); } else { // If not - cap to 0.01% drop rate - as on official servers droprate = max(droprate, 1); } int dropbonus = 0; if (pc_isvip(sd)) dropbonus += (battle_config.vip_drop_increase * droprate) / 100; dropbonus += (sd->sc.getSCE(SC_ITEMBOOST) ? ((droprate * sd->sc.getSCE(SC_ITEMBOOST)->val1) / 100) : 0); sprintf(atcmd_output2, (dropbonus > 0 ? " - %s %02.02f%% + (%02.02f%%)" : " - %s %02.02f%%"), item_db.create_item_link(id).c_str(), (float)droprate / 100, (float)dropbonus / 100); strcat(atcmd_output, atcmd_output2); clif_displaymessage(fd, atcmd_output); strcpy(atcmd_output, " "); } if (j == 0) clif_displaymessage(fd, msg_txt(sd,1246)); // This monster has no drops. // mvp if( mob->get_bosstype() == BOSSTYPE_MVP ){ float mvppercent, mvpremain; sprintf(atcmd_output, msg_txt(sd,1247), mob->mexp); // MVP Bonus EXP:%llu clif_displaymessage(fd, atcmd_output); strcpy(atcmd_output, msg_txt(sd,1248)); // MVP Items: clif_displaymessage(fd, atcmd_output); strcpy(atcmd_output, " "); mvpremain = 100.0; //Remaining drop chance for official mvp drop mode j = 0; for (i = 0; i < MAX_MVP_DROP_TOTAL; i++) { if (mob->mvpitem[i].nameid == 0) continue; std::shared_ptr<item_data> id = item_db.find(mob->mvpitem[i].nameid); if (id == nullptr) continue; //Because if there are 3 MVP drops at 50%, the first has a chance of 50%, the second 25% and the third 12.5% mvppercent = (float)mob->mvpitem[i].rate * mvpremain / 10000.0f; if(battle_config.item_drop_mvp_mode == 0) { mvpremain -= mvppercent; } if (mvppercent > 0) { j++; sprintf(atcmd_output2, " - %s %02.02f%%", item_db.create_item_link( id ).c_str(), mvppercent); strcat(atcmd_output, atcmd_output2); clif_displaymessage(fd, atcmd_output); strcpy(atcmd_output, " "); } } if (j == 0) clif_displaymessage(fd, msg_txt(sd,1249)); // This monster has no MVP prizes. } } return 0; }
  13. try this: struct item_data * item_data = item_array[i]; sprintf(atcmd_output, "Item: '%s'/'%s' (%hu) Type: %s", // msg_txt(sd, 1277) item_data->name,createItemLink(item_data->nameid, 0, NULL).c_str(),item_data->nameid, (item_data->type != IT_AMMO) ? itemdb_typename((enum item_types)item_data->type) : itemdb_typename_ammo((enum e_item_ammo)item_data->look));
  14. If you have itemlink commands by Cydh implemented you just have to edit in atcommand.cpp Find: struct item_data * item_data = item_array[i]; sprintf(atcmd_output, msg_txt(sd,1277), // Item: '%s'/'%s'[%d] (%hu) Type: %s | Extra Effect: %s item_data->name,item_data->jname,item_data->slot,item_data->nameid, (item_data->type != IT_AMMO) ? itemdb_typename((enum item_types)item_data->type) : itemdb_typename_ammo((enum e_item_ammo)item_data->look), (item_data->script==NULL)? msg_txt(sd,1278) : msg_txt(sd,1279) // None / With script ); Change To: struct item_data * item_data = item_array[i]; sprintf(atcmd_output, "Item: '%s'/'%s' (%hu)", // msg_txt(sd, 1277) item_data->name, createItemLink(item_data->nameid, 0, NULL).c_str(),item_data->nameid);
  15. in atcommand.cpp Find: for (j=0; j < MAX_SEARCH && item_data->mob[j].chance > 0; j++) { int dropchance = item_data->mob[j].chance; Change To: for (j=0; j < MAX_SEARCH && item_data->mob[j].chance > 0; j++) { int dropchance = item_data->mob[j].chance; int dropbonus = 0; Find: #endif if (pc_isvip(sd)) // Display item rate increase for VIP dropchance += (dropchance * battle_config.vip_drop_increase) / 100; sprintf(atcmd_output, "- %s (%d): %02.02f%%", mob_db(item_data->mob[j].id)->jname, item_data->mob[j].id, dropchance/100.); Change To: #endif if(sd->sc.count && sd->sc.data[SC_ITEMBOOST]) // Display drop rate increase for SC_ITEMBOOST eg. Bubblegum dropbonus += (dropchance * sd->sc.data[SC_ITEMBOOST]->val1) / 100; if (pc_isvip(sd)) // Display item rate increase for VIP dropbonus += (dropchance * battle_config.vip_drop_increase) / 100; if(dropbonus) sprintf(atcmd_output, "- %s (%d): %02.02f%% + (%02.02f%%)", mob_db(item_data->mob[j].id)->jname, item_data->mob[j].id, dropchance/100., dropbonus/100.); else sprintf(atcmd_output, "- %s (%d): %02.02f%%", mob_db(item_data->mob[j].id)->jname, item_data->mob[j].id, dropchance/100.);
  16. in src\map\script_constants.hpp Find: export_constant(MF_NODYNAMICNPC); Change To: export_constant(MF_NODYNAMICNPC); export_constant(MF_VIEW_HPMETER); in src\map\map.hpp Find: MF_NODYNAMICNPC, MF_MAX Change To: MF_NODYNAMICNPC, MF_VIEW_HPMETER, MF_MAX in src\map\npc.cpp Find: switch( mapflag ){ case MF_INVALID: Change To: switch( mapflag ){ case MF_VIEW_HPMETER: if (state) { union u_mapflag_args args = {}; if (sscanf(w4, "%11d", &args.flag_val) < 1) args.flag_val = 0; // No level specified, allow everyone. map_setmapflag_sub(m, MF_VIEW_HPMETER, true, &args); } else map_setmapflag(m, MF_VIEW_HPMETER, false); break; case MF_INVALID: in src\map\map.cpp Find: case MF_NOCOMMAND: if (status) { nullpo_retr(false, args); mapdata->flag[mapflag] = ((args->flag_val <= 0) ? 100 : args->flag_val); } else mapdata->flag[mapflag] = false; break; Change To: case MF_NOCOMMAND: case MF_VIEW_HPMETER: if (status) { nullpo_retr(false, args); mapdata->flag[mapflag] = ((args->flag_val <= 0 && mapflag != MF_VIEW_HPMETER) ? 100 : args->flag_val); } else mapdata->flag[mapflag] = false; break; Find: // additional mapflag data mapdata->zone = 0; // restricted mapflag zone mapdata->flag[MF_NOCOMMAND] = false; // nocommand mapflag level Change To: // additional mapflag data mapdata->zone = 0; // restricted mapflag zone mapdata->flag[MF_NOCOMMAND] = false; // nocommand mapflag level mapdata->flag[MF_VIEW_HPMETER] = 99; // viewhpmeter mapflag level (Blocks everyone except Admin by default) in src\map\atcommand.cpp Find: if (map_getmapflag(m_id, MF_NOCOSTUME)) strcat(atcmd_output, " NoCostume |"); clif_displaymessage(fd, atcmd_output); Change To: if (map_getmapflag(m_id, MF_NOCOSTUME)) strcat(atcmd_output, " NoCostume |"); if (map_getmapflag(m_id, MF_VIEW_HPMETER)) strcat(atcmd_output, " ViewHPMeter |"); clif_displaymessage(fd, atcmd_output); in src\map\pc.cpp Find: /*========================================== * pc Init/Terminate *------------------------------------------*/ void do_final_pc(void) { Change To: bool pc_can_view_hpmeter(struct map_session_data *sd){ if(!sd) return false; if(pc_has_permission(sd,PC_PERM_VIEW_HPMETER) && pc_get_group_level(sd) >= map_getmapflag(sd->bl.m, MF_VIEW_HPMETER)) return true; return false; } /*========================================== * pc Init/Terminate *------------------------------------------*/ void do_final_pc(void) { in src\map\pc.hpp Find: #endif /* PC_HPP */ Change To: bool pc_can_view_hpmeter(struct map_session_data *sd); #endif /* PC_HPP */ in src\map\clif.cpp Find: if( pc_has_permission( tsd, PC_PERM_VIEW_HPMETER ) ){ clif_hpmeter_single( *tsd, sd->status.account_id, sd->battle_status.hp, sd->battle_status.max_hp ); } Change to: if( pc_can_view_hpmeter( tsd ) ){ clif_hpmeter_single( *tsd, sd->status.account_id, sd->battle_status.hp, sd->battle_status.max_hp ); } Find: if( (sd->status.party_id && dstsd->status.party_id == sd->status.party_id) || //Party-mate, or hpdisp setting. (sd->bg_id && sd->bg_id == dstsd->bg_id) || //BattleGround pc_has_permission(sd, PC_PERM_VIEW_HPMETER) ) Change To: if( (sd->status.party_id && dstsd->status.party_id == sd->status.party_id) || //Party-mate, or hpdisp setting. (sd->bg_id && sd->bg_id == dstsd->bg_id) || //BattleGround pc_can_view_hpmeter(sd) ) Find: if( pc_has_permission(sd,PC_PERM_VIEW_HPMETER) ) { mapdata->hpmeter_visible++; sd->state.hpmeter_visible = 1; } Change To: if( pc_can_view_hpmeter(sd) ) { mapdata->hpmeter_visible++; sd->state.hpmeter_visible = 1; } Usage: <mapname><tab>mapflag<tab>view_hpmeter<tab><group_level> This should set a map with the mapflag to enable view_hpmeter that players with higher or equal to the specified group_level can bypass. To block everyone set the group_level to 100. ***Note: You still need to add "view_hpmeter: true" to the group permissions on the groups.yml file.***
  17. For Hit calculation, if you are on Renewal (150 + Dex + Level) is the right formula as it says here on the code: // Hit stat = status->hit; stat += level + status->dex + (bl->type == BL_PC ? status->luk / 3 + 175 : 150); //base level + ( every 1 dex = +1 hit ) + (every 3 luk = +1 hit) + 175 for BL_PC(Player) types otherwise base level + dex + 150 (175 + Dex + Level + Floor(Luk / 3)) Formula only applies to BL_PC types aka Players If you are on Pre-Renewal it's just (Level + Dex): // Hit stat = status->hit; stat += level + status->dex; For Flee on Renewal is (Level + Agi + 100): // Flee stat = status->flee; stat += level + status->agi + (bl->type == BL_MER ? 0 : bl->type == BL_PC ? status->luk / 5 : 0) + 100; //base level + ( every 1 agi = +1 flee ) + (every 5 luk = +1 flee) + 100 of BL_PC(Player) otherwise base level + agi + 100 and on Pre-Renewal is (Level + Agi): // Flee stat = status->flee; stat += level + status->agi;
  18. The one I quoted, replace all of that with this: case RG_BACKSTAP: { uint8 dir = map_calc_dir(src, bl->x, bl->y), t_dir = unit_getdir(bl); if (!check_distance_bl(src, bl, 0) || bl->type == BL_SKILL) { status_change_end(src, SC_HIDING, INVALID_TIMER); dir = dir < 4 ? dir+4 : dir-4; // change direction [Celest] unit_setdir(bl,dir); skill_attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag); } else if (sd) clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); } break;
  19. in your skill.cpp search all the "case RG_BACKSTAP:" copy it all until the "break;" and paste all the codes here, maybe it's checking the direction somewhere else.
  20. Try this: case RG_BACKSTAP: { if (!check_distance_bl(src, bl, 0)) { #ifdef RENEWAL uint8 dir = map_calc_dir(src, bl->x, bl->y); short x, y; if (dir > 0 && dir < 4) x = -1; else if (dir > 4) x = 1; else x = 0; if (dir > 2 && dir < 6) y = -1; else if (dir == 7 || dir < 2) y = 1; else y = 0; if (battle_check_target(src, bl, BCT_ENEMY) > 0 && unit_movepos(src, bl->x + x, bl->y + y, 2, true)) { // Display movement + animation. #else uint8 dir = map_calc_dir(src, bl->x, bl->y), t_dir = unit_getdir(bl); if (bl->type == BL_SKILL) { // Changed Here (Removed Direction Check) #endif status_change_end(src, SC_HIDING, INVALID_TIMER); dir = dir < 4 ? dir+4 : dir-4; // change direction [Celest] unit_setdir(bl,dir); #ifdef RENEWAL clif_blown(src); #endif skill_attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag); } else if (sd) clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); } } break;
  21. in battle.cpp Find: if (dist <= 0 || (!map_check_dir(dir,t_dir) && dist <= tstatus->rhw.range+1)) { uint16 skill_lv = tsc->getSCE(SC_AUTOCOUNTER)->val1; Change to: if (dist <= 0 || (dist <= tstatus->rhw.range+1)) { uint16 skill_lv = tsc->getSCE(SC_AUTOCOUNTER)->val1; I guess you can delete these too since it's not getting used: uint8 dir = map_calc_dir(target,src->x,src->y); int t_dir = unit_getdir(target);
  22. If you're on the latest version of Rathena, you can go to db/pre-re or db/re folder and open the status.yml Find: - Status: Berserk Icon: EFST_BERSERK DurationLookup: LK_BERSERK States: NoCast: true NoChat: true NoEquipItem: true NoUnEquipItem: true NoConsumeItem: true Delete this: NoConsumeItem: true if you're on the older versions and don't have this file, goto src/map folder and open pc.cpp Find: if( sd->md->sc.data[SC_BERSERK] ) return false; Delete it, then find this: if (sd->sc.count && ( sd->sc.data[SC_BERSERK] || sd->sc.data[SC_SATURDAYNIGHTFEVER] || Change it to this: if (sd->sc.count && ( sd->sc.data[SC_SATURDAYNIGHTFEVER] ||
  23. Idk if this is what you want but this disables /guildinvite and even the right-click guildinvite. in clif.cpp Find: // Helper function for guild invite functions int clif_sub_guild_invite(int fd, struct map_session_data *sd, struct map_session_data *t_sd) { if (t_sd == NULL) // not online or does not exist return 1; Change to: // Helper function for guild invite functions int clif_sub_guild_invite(int fd, struct map_session_data *sd, struct map_session_data *t_sd) { return 1; if (t_sd == NULL) // not online or does not exist return 1; If you want to disable the /guildinvite only then you need to hex the client. Find: 2F 67 75 69 6C 64 69 6E 76 69 74 65 Replace: 00 00 00 00 00 00 00 00 00 00 00 00
  24. There's an easy trick to achieve somewhat of a similar result, but it won't be perfect since it will say the skill name twice (before and after casting) because it is hard coded into the client to display skill name when "clif_skill"(tells client to display casting sprite animation and effects) is sent. in unit.cpp Find: // In official this is triggered even if no cast time. clif_skillcasting(src, src->id, target_id, 0,0, skill_id, skill_get_ele(skill_id, skill_lv), casttime); Change it to: if(src->type == BL_MOB) clif_showscript(src, skill_get_desc(skill_id), AREA); // In official this is triggered even if no cast time. clif_skillcasting(src, src->id, target_id, 0,0, skill_id, skill_get_ele(skill_id, skill_lv), casttime); That should show the skill name before casting for mobs only. And if you want it to work on certain skills only, change it to this: if(src->type == BL_MOB){ switch(skill_id){ case NPC_EARTHQUAKE: case NPC_DARKBREATH: case NPC_HALLUCINATION: // Add skill here clif_showscript(src, skill_get_desc(skill_id), AREA); break; } } // In official this is triggered even if no cast time. clif_skillcasting(src, src->id, target_id, 0,0, skill_id, skill_get_ele(skill_id, skill_lv), casttime);
  25. In the latest version of Rathena this is already implemented. If you're using an older version you might have to diff patch the itemlink commands by Cydh. The older rathena versions supports the "itemlink-20190319-e6f1f21d.diff" Then you would have to edit the atcommand.cpp in ACMD_FUNC(mobinfo) Find: for (i = 0; i < MAX_MOB_DROP_TOTAL; i++) { int droprate; if (mob->dropitem[i].nameid <= 0 || mob->dropitem[i].p < 1 || (item_data = itemdb_exists(mob->dropitem[i].nameid)) == NULL) continue; droprate = mob->dropitem[i].p; #ifdef RENEWAL_DROP if( battle_config.atcommand_mobinfo_type ) { droprate = droprate * pc_level_penalty_mod(mob->lv - sd->status.base_level, mob->status.class_, mob->status.mode, 2) / 100; if (droprate <= 0 && !battle_config.drop_rate0item) droprate = 1; } #endif if (pc_isvip(sd)) // Display drop rate increase for VIP droprate += (droprate * battle_config.vip_drop_increase) / 100; if (item_data->slot) sprintf(atcmd_output2, " - %s[%d] %02.02f%%", item_data->jname, item_data->slot, (float)droprate / 100); else sprintf(atcmd_output2, " - %s %02.02f%%", item_data->jname, (float)droprate / 100); strcat(atcmd_output, atcmd_output2); if (++j % 3 == 0) { clif_displaymessage(fd, atcmd_output); strcpy(atcmd_output, " "); } } if (j == 0) clif_displaymessage(fd, msg_txt(sd,1246)); // This monster has no drops. else if (j % 3 != 0) clif_displaymessage(fd, atcmd_output); // mvp if (mob->mexp) { float mvppercent, mvpremain; sprintf(atcmd_output, msg_txt(sd,1247), mob->mexp); // MVP Bonus EXP:%u clif_displaymessage(fd, atcmd_output); strcpy(atcmd_output, msg_txt(sd,1248)); // MVP Items: mvpremain = 100.0; //Remaining drop chance for official mvp drop mode j = 0; for (i = 0; i < MAX_MVP_DROP_TOTAL; i++) { if (mob->mvpitem[i].nameid <= 0 || (item_data = itemdb_exists(mob->mvpitem[i].nameid)) == NULL) continue; //Because if there are 3 MVP drops at 50%, the first has a chance of 50%, the second 25% and the third 12.5% mvppercent = (float)mob->mvpitem[i].p * mvpremain / 10000.0f; if(battle_config.item_drop_mvp_mode == 0) { mvpremain -= mvppercent; } if (mvppercent > 0) { j++; if (j == 1) { if (item_data->slot) sprintf(atcmd_output2, " %s[%d] %02.02f%%", item_data->jname, item_data->slot, mvppercent); else sprintf(atcmd_output2, " %s %02.02f%%", item_data->jname, mvppercent); } else { if (item_data->slot) sprintf(atcmd_output2, " - %s[%d] %02.02f%%", item_data->jname, item_data->slot, mvppercent); else sprintf(atcmd_output2, " - %s %02.02f%%", item_data->jname, mvppercent); } strcat(atcmd_output, atcmd_output2); } } if (j == 0) clif_displaymessage(fd, msg_txt(sd,1249)); // This monster has no MVP prizes. else clif_displaymessage(fd, atcmd_output); } Change to: for (i = 0; i < MAX_MOB_DROP_TOTAL; i++) { int droprate; int dropbonus = 0; if (mob->dropitem[i].nameid <= 0 || mob->dropitem[i].p < 1 || (item_data = itemdb_exists(mob->dropitem[i].nameid)) == NULL) continue; droprate = mob->dropitem[i].p; #ifdef RENEWAL_DROP if( battle_config.atcommand_mobinfo_type ) { droprate = droprate * pc_level_penalty_mod(mob->lv - sd->status.base_level, mob->status.class_, mob->status.mode, 2) / 100; if (droprate <= 0 && !battle_config.drop_rate0item) droprate = 1; } #endif if((sd->sc.count && sd->sc.data[SC_ITEMBOOST])) // Display drop rate increase for SC_ITEMBOOST eg. Bubblegum dropbonus += (droprate * sd->sc.data[SC_ITEMBOOST]->val1) / 100; if (pc_isvip(sd)) // Display drop rate increase for VIP dropbonus += (droprate * battle_config.vip_drop_increase) / 100; if (dropbonus) sprintf(atcmd_output2, " %s %02.02f%% + (%02.02f%%)", createItemLink(item_data->nameid, 0, NULL).c_str(), (float)droprate / 100, (float)dropbonus / 100); else sprintf(atcmd_output2, " %s %02.02f%%", createItemLink(item_data->nameid, 0, NULL).c_str(), (float)droprate / 100); strcat(atcmd_output, atcmd_output2); j++; clif_displaymessage(fd, atcmd_output); strcpy(atcmd_output, " "); } if (j == 0) clif_displaymessage(fd, msg_txt(sd,1246)); // This monster has no drops. // mvp if (mob->mexp) { float mvppercent, mvpremain; sprintf(atcmd_output, msg_txt(sd,1247), mob->mexp); // MVP Bonus EXP:%u clif_displaymessage(fd, atcmd_output); strcpy(atcmd_output, msg_txt(sd,1248)); // MVP Items: clif_displaymessage(fd, atcmd_output); strcpy(atcmd_output, " "); mvpremain = 100.0; //Remaining drop chance for official mvp drop mode j = 0; for (i = 0; i < MAX_MVP_DROP_TOTAL; i++) { if (mob->mvpitem[i].nameid <= 0 || (item_data = itemdb_exists(mob->mvpitem[i].nameid)) == NULL) continue; //Because if there are 3 MVP drops at 50%, the first has a chance of 50%, the second 25% and the third 12.5% mvppercent = (float)mob->mvpitem[i].p * mvpremain / 10000.0f; if(battle_config.item_drop_mvp_mode == 0) { mvpremain -= mvppercent; } if (mvppercent > 0) { j++; sprintf(atcmd_output2, " %s %02.02f%%", createItemLink(item_data->nameid, 0, NULL).c_str(), mvppercent); strcat(atcmd_output, atcmd_output2); clif_displaymessage(fd, atcmd_output); strcpy(atcmd_output, " "); } } if (j == 0) clif_displaymessage(fd, msg_txt(sd,1249)); // This monster has no MVP prizes. }
×
×
  • Create New...