ebx is an assembly register, it contains a memory direction. When you search what writes to HP value you get some assembly code that writes your desired address, that is the same for those who contains hp values in the game.
EBX + 4 points to HP value of any entity (you can set a breakpoint and check and the value of ebx won't be the same if you press button 1 / 2 / 3 / 4 because are different addresses, you need to find a way to check if is your team or is enemy team.
When you dissect data structure you found that your team id offset is 0xC, that offset is from HP address that if u remember in the assembly code is EBX+4+C -> EBX+10 is team id.
Now you can inject some code:
mov [ebx+04],eax
fldz
This code is responsible of removing life when you press the Attack button.
eax is the value of life you are removing from the entity's HP and fldz don't know but doesn't matter.
So we know how to get team id,
[ebx+10]
we can do something like this:
Assembly code:
cmp [ebx+10],1
jne originalcode
fldz
we compare that value (TEAM ID) with 1 -> OUR TEAM ID
jne -> conditional jump if NOT EQUAL jump.
If is our team we don't execute the original code, if not we do.
Our assembly code looks now like this:
0 cmp [ebx+10],1
1 jne originalcode
2 fldz
3 mov [ebx+04],eax //ORIGINAL CODE
4 fldz
5 jmp ...
you will notice if we don't take the jump (JNE) original code will be executed,
and we don't want that, we can fix that with a jump.
So where we jump?. simple count bytes of original code (5 bytes)
Assembly is hard at the begining