Jump to content

joecalis

Members
  • Posts

    64
  • Joined

  • Last visited

  • Days Won

    7

Posts 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.

    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.

    • Love 1
  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;
    	}
    	

     

    • Love 1
  3. 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;

     

  4. 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;

     

    • Love 1
  5. 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));

     

    • Love 1
  6. 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;

     

  7. 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

     

     

    • MVP 1
  8. 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. /no1

    • MVP 3
  9. 4 hours ago, kidsada said:

    Find:

    		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 = mob_getdroprate( &sd->bl, mob, mob->dropitem[i].rate, drop_modifier );
              
              			sprintf(atcmd_output2, " - %s  %02.02f%%", item_db.create_item_link( id ).c_str(), (float)droprate / 100);
    			strcat(atcmd_output, atcmd_output2);
    			if (++j % 1 == 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->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:
    			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++;
    					if (j == 1) {
    						sprintf(atcmd_output2, " %s  %02.02f%%", item_db.create_item_link( id ).c_str(), mvppercent);
    					} else {
    						sprintf(atcmd_output2, " - %s  %02.02f%%", item_db.create_item_link( id ).c_str(), 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);
    		}
    	}
    	return 0;
    }

    my Code 

    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;
    }

     

  10. 4 hours ago, Gidz Cross said:

    @joecalis Hey apologies for the multiple mentions. XD

    How about retaining the Item Type? I am playing with it but all my attempts are failing. So the src code retains to read msg_txt(sd, 1277) but only will display the item type. 

    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));

     

    • MVP 1
  11. 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);

     

    • MVP 1
  12. 28 minutes ago, Gidz Cross said:


    Hey mate! Thank you for this. I wish that this can be implemented to @whodrops as well.

    *EDIT

    Item linking is not necessary for @whodrops. Just the original drop rate + (bonuses) when you are on VIP or consumed Bubblegums. 

    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.);

     

    • MVP 1
  13. 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.***

    • Love 1
    • MVP 1
  14. 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;

     

    • Upvote 2
    • Love 1
  15. 8 minutes ago, Notorius said:

     

    This is the one that changed but the skill stopped working so I returned it to how it is, that is, like 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 (!map_check_dir(dir, t_dir) || bl->type == BL_SKILL) {
    #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;

    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;

     

  16. 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;

     

  17. 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);

     

  18. 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] ||

     

  19. 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

     

  20. 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);

     

    • Love 1
  21. 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.
    		}

     

    • Upvote 1
    • MVP 1
×
×
  • Create New...