RECENT NEWS
📢 𝟑𝟎% Discount for all ads only this month ❄️

[Ruse] Hp Overlay, and Damage Hit Mask \"Fixes\"

AlienGP
power_settings_new
Seen 2 days ago
Mithril Warrior (21/30)
Mithril Warrior
0
0
0
21 Posts
Posts
0
Warning level
2
Likes
0
Dislikes
Joined: 2022-04-24

Hi All,
Sorry if this is in the wrong section. This is my first time posting a thread on the forums here.

A few months back I was browsing this forum and came across a help thread asking for help displaying numbers over 65535 on Hp Overlays. I explained the issue, and how to fix it. However, Multiple people ended up DMing me on here asking for help fixing it. So I figured I should take the time to fix this properly. However, after starting to fix this, anther person had DMed me asking for information on how to fix Damage masks showing more damage than 65535 (6553 Non x10 Hitting). So without further ado, The "Fixes".

*Disclaimer: There is no reason to implement this if you are not using this for a custom server with insane amounts of strength.

The Issues:
HP over 65535 (6553 Non x10 Hitting) would not display correctly, and cause the bar to Constantly grow and shrink on each combat tick.
Damage over 65535 (6553 Non x10 Hitting) would not display correctly, causing confusion when an enemy dies quicker than the damage displaying.

The Fix (This does fix both things as their both handled in the same packet):
To Start, Were going to be making changes to the server, then the client to keep things a bit easier. The first thing were going to do is stop packet 207 from sending from the server to the client. Go into PacketSender.java, and locate the void "sendEntityInterface"
It should look something like this:

Code:
    public PacketSender sendEntityInterface(int flag, int maxHealth, int currentHealth, String entityName) {
        PacketBuilder out = new PacketBuilder(207);
        out.putShort(flag);
        out.putShort(maxHealth);
        out.putShort(currentHealth);
        player.getSession().queueMessage(out);
        sendEntityName(entityName);
        player.sendParallellInterfaceVisibility(41020, true);
        return this;
        
    }

Delete the entire void.

Now while still in PacketSender, Go to the void "sendEntityName", It should look like this.

Code:
    public PacketSender sendEntityName(String name) {
        PacketBuilder out = new PacketBuilder(205, PacketType.BYTE);
        out.putString(name);
        player.getSession().queueMessage(out);
        return this;
    }

Replace with:

Code:
    public PacketSender sendEntityInterface(String name) {
        PacketBuilder out = new PacketBuilder(205, PacketType.BYTE);
        out.putString(name);
        player.getSession().queueMessage(out);
        player.sendParallellInterfaceVisibility(41020, true);
        return this;
    }

Now there are going to be a few errors in CombatHitTask, Open CombatHitTask.java, and go to the void "handleEntityInterface".
The current code should look something like:

Code:
    public void handleEntityInterface(Character attacker, Character victim, int damage) {
        if (attacker.isPlayer()) {
            Player p = (Player) attacker;
            
            if (victim.isPlayer()) {//plrs
                Player v = (Player) victim;
                int maximumHealth = v.getSkillManager().getMaxLevel(Skill.CONSTITUTION);
                int currentHealth = v.getSkillManager().getCurrentLevel(Skill.CONSTITUTION);
                String entityName = v.getUsername();
                p.getPacketSender().sendEntityInterface(victim.isPlayer() ? 1 : 0, maximumHealth, currentHealth, entityName);
            } else if (victim.isNpc()) {//npcs
                NPC v = (NPC) victim;
                int maximumHealth = v.getDefaultConstitution();
                int currentHealth = v.getConstitution();
                String entityName = v.getDefinition().getName();
                p.getPacketSender().sendEntityInterface(victim.isPlayer() ? 1 : 0, maximumHealth, currentHealth, entityName);
            }
        }
    }

Replace it with:

Code:
    public void handleEntityInterface(Character attacker, Character victim, int damage) {
        if (attacker.isPlayer()) {
            Player p = (Player) attacker;
            if (victim.isPlayer()) {//plrs
                Player v = (Player) victim;
                String entityName = v.getUsername();
                p.getPacketSender().sendEntityInterface(entityName);
            } else if (victim.isNpc()) {//npcs
                NPC v = (NPC) victim;
                String entityName = v.getDefinition().getName();
                p.getPacketSender().sendEntityInterface(entityName);
            }
        }
    }

So far what we have done is disabled the packet 207 from sending, and moved the code that actually displays the interface into packet 205 (Sending the Entity Name. i.e Npc Name or Player Name depending on circumstances, However the way we will be sending hp will only be for NPC's. With a bit of knowledge can be expanded to players as well.

Now were going to start sending the currentEntityHealth, and maximumEntityHealth through an entityUpdate. Which is already done for HP Bar drawing, Not to be confused with the overlay were currently fixing.

Open up NPCUpdating.java, Go to the void "updateSingleHit", It should look like this:

Code:
	private static void updateSingleHit(PacketBuilder builder, NPC npc) {
		builder.putShort(npc.getPrimaryHit().getDamage(), ValueType.A);
		builder.put(npc.getPrimaryHit().getHitmask().ordinal(), ValueType.C);
		builder.put(npc.getPrimaryHit().getCombatIcon().ordinal() - 1);
		builder.putShort(npc.getConstitution(), ValueType.A);
		builder.putShort(npc.getDefaultConstitution(), ValueType.A);
	}

Now, change all the builder.putShort to builder.putInt, Then remove all the code after the first comma in the parentheses. The code should now look like this:

Code:
	private static void updateSingleHit(PacketBuilder builder, NPC npc) {
		builder.putInt(npc.getPrimaryHit().getDamage());
		builder.put(npc.getPrimaryHit().getHitmask().ordinal(), ValueType.C);
		builder.put(npc.getPrimaryHit().getCombatIcon().ordinal() - 1);
		builder.putInt(npc.getConstitution());
		builder.putInt(npc.getDefaultConstitution());
	}

Now while still in CombatHitTask, go to the void "updateDoubleHit", and do the exact same things you had just done to "updateSingleHit", to "updateDoubleHit". "updateDoubleHit" should now look like this:

Code:
	private static void updateDoubleHit(PacketBuilder builder, NPC npc) {
		builder.putInt(npc.getSecondaryHit().getDamage());
		builder.put(npc.getSecondaryHit().getHitmask().ordinal(), ValueType.S);
		builder.put(npc.getSecondaryHit().getCombatIcon().ordinal() - 1);
		builder.putInt(npc.getConstitution());
		builder.putInt(npc.getDefaultConstitution());
	}

We have officially finished the server portion of the code for the fix. What we have done is updated the packets to send higher values to the client, as well as made it so all the interface showing, is mostly handled when the entityname is sent.

Now were going to start making changes to the client, to be able to read, and understand the higher values coming from the server.

Open Client.java, and search for the void "drawHpBar" it should look something like this:

Code:
	private void drawHpBar() {
		RSInterface iface = RSInterface.interfaceCache[41020];

		if (!parallelWidgetList.contains(iface)) {
			return;
		}

		float percentage = ((float) currentEntityHealth / (float) maximumEntityHealth) * (float) 100;
		DrawingArea.drawPixels(16, iface.y + 30, iface.x, 0x00b300, (int) percentage * 7/6);
		// drawPixels(int height_, int yPos, int xPos, int color, int width_)

		TextDrawingArea.drawAlphaFilledPixels(iface.x, iface.y + 30, 117, 16, 0xff000d, 50);
		// int xPos, int yPos,
		// int pixelWidth, int pixelHeight, int color, int alpha) {// method586
		RSInterface text = RSInterface.interfaceCache[41023];
		newSmallFont.drawCenteredString(iface.message, 63, 52, 0xffffff, 1);
	}

What were going to do is add the ability for the currentEntityHealth, and maximumEntityHealth to be drawn at the same time the green portions of the hp overlay is drawn based on percent of hp left.

Replace the current drawHpBar code with this code below:

Code:
	private void drawHpBar() {
		RSInterface iface = RSInterface.interfaceCache[41020];

		if (!parallelWidgetList.contains(iface)) {
			return;
		}
		int current = currentEntityHealth;
		int max  = maximumEntityHealth;
		if (!getOption("constitution")) {
			current = current / 10;
			max = max / 10;
		}
		float percentage = ((float) currentEntityHealth / (float) maximumEntityHealth) * (float) 100;
		DrawingArea.drawPixels(16, iface.y + 30, iface.x, 0x00b300, (int) percentage * 7/6);
		// drawPixels(int height_, int yPos, int xPos, int color, int width_)
		iface.message = current + " / " + max;
		TextDrawingArea.drawAlphaFilledPixels(iface.x, iface.y + 30, 117, 16, 0xff000d, 50);
		// int xPos, int yPos,
		// int pixelWidth, int pixelHeight, int color, int alpha) {// method586
		RSInterface text = RSInterface.interfaceCache[41023];
		newSmallFont.drawCenteredString(iface.message, 63, 52, 0xffffff, 1);
	}

Now we need to tell the client how much currentEntityHealth, and maximumEntityHealth the entity has.

While still in Client.java, Were going to update the hitmask to get be able to read the data from the server being sent (see NPCUpdating Section) search for "((l & 8) != 0)". the code should look something like this.

Code:
			if ((l & 8) != 0) {
				int j1 = inStream.readByteA();
				int j2 = stream.nglb();
				int icon = stream.readUnsignedByte();
				npc.updateHitData(j2, j1, loopCycle, icon, 0);
				npc.loopCycleStatus = loopCycle + 300;
				npc.currentHealth = inStream.readByteA();
				npc.maxHealth = inStream.readByteA();
			}

Replace with

Code:
			if ((l & 8) != 0) {
				int j1 = inStream.readInt();
				int j2 = stream.nglb();
				int icon = stream.readUnsignedByte();
				npc.updateHitData(j2, j1, loopCycle, icon, 0);
				npc.loopCycleStatus = loopCycle + 300;
				npc.currentHealth = inStream.readInt();
				npc.maxHealth = inStream.readInt();
				currentEntityHealth = npc.currentHealth;
				maximumEntityHealth = npc.maxHealth;
			}

Now search for "(l & 0x40) != 0" the code should look identical to the first mask we editted:

Code:
			if ((l & 0x40) != 0) {
				int l1 = inStream.readByteA();
				int k2 = stream.readByteS();
				int icon = stream.readUnsignedByte();
				npc.updateHitData(k2, l1, loopCycle, icon, 0);
				npc.loopCycleStatus = loopCycle + 300;
				npc.currentHealth = inStream.readByteA();
				npc.maxHealth = inStream.readByteA();
			}

Replace with

Code:
			if ((l & 0x40) != 0) {
				int l1 = inStream.readInt();
				int k2 = stream.readByteS();
				int icon = stream.readUnsignedByte();
				npc.updateHitData(k2, l1, loopCycle, icon, 0);
				npc.loopCycleStatus = loopCycle + 300;
				npc.currentHealth = inStream.readInt();
				npc.maxHealth = inStream.readInt();
				currentEntityHealth = npc.currentHealth;
				maximumEntityHealth = npc.maxHealth;
			}

Now save and compile everything, and run your server and client. You should now be able to see the HPOverlay with correct constitution values, as well as hit masks with damage over 65535.
If you have any issues implementing this, or something doesn't work, Feel free to scream at me in DMs.

Teaser of End Product:

00
  • Like
Reactions: