Staredit Network > Forums > Modding Discussion > Topic: Hardened Shield
Hardened Shield
Oct 11 2012, 9:53 pm
By: Raygoza  

Oct 11 2012, 9:53 pm Raygoza Post #1



Hi I wonder how you'd make an Immortal Shield.
I know a little bit about programming in AS3 and I'm 99% sure this can be done.
If damage exceeds 9 on shields, take 10 damage on shields and play a chosen effect.

My friend told me that this is probably possible but if two zerglings attack the immortal at the same frame they would activate the hardened shield together, or if two sieged tanks damages it at the same time the shield would only take 10 damage and only one tank would be revealed.

How do you guys think this can be dealt with?
I need to know how the hardened shield could be made to react on each incoming attack separately.
Any ideas?



None.

Oct 11 2012, 10:01 pm Oh_Man Post #2

Find Me On Discord (Brood War UMS Community & Staredit Network)

OK now I may or may not have no idea what I'm talking about but couldn't you do something like this:
IF damage exceeds 9 on shields, SUBTRACT 1 shield damage
IF damage exceeds 9 on shields, SUBTRACT 1 shield damage
IF damage exceeds 9 on shields, SUBTRACT 1 shield damage
repeat until...
IF damage EQUALS 9 on shields, subtract 9 shield damage.




Oct 12 2012, 9:13 pm Raygoza Post #3



Let's say we do your way, if two weak attacks hit the shield simultaneously it seems like they get added up and activate the hardened shield instead og doing the damage of two low damage attacks.
This especially happens if an Immortal comes in rage of let's say three lumped tanks, they'll hit it simultaneously but only one tank will be revealed and the hardened shield would only be activated once meaning that Each tank that hits the Immortal at the same time gets all their combined damage reduced to 10 combined.

This creates a big issue which I have no idea how to solve, the hardened shield has to react on each attack separately meaning that if there are several things damaging under 10 it should react like any other unit, if a high damage unit and a low damage unit is damaging the Immortal the low damage should do it's full damage and the High damage should reduce the damage to 10 from the specified attack only, if two high damage units attack the Immortal the hardened shield should activate and reduce the damage for 10 but for each attack not for both if they happen to damage the immortal simultaneously.



None.

Oct 12 2012, 9:13 pm Sand Wraith Post #4

she/her

I don't think it's possible to get around the problem as long as splash damage or projectiles are in the game. Even then, you would have to consider a lot of factors such as weapon, shield, and armour upgrades.




Oct 13 2012, 11:36 am Raygoza Post #5



How does the shield upgrade work for the Immortal in SC2 if anyone knows, not even I know how to find out.
I think that if the shield armor level limites the damage made to the unit's shield and if that exceedes 9 the hardened shield would be activated.
About incoming damage it's very easy, as the damage exceeds the limit the hardened shield would be activated.

This is how I think it works and should make that the hardened shield isn't constantly used, this also means that if incoming attack deals like 12 damage and the shield upgrade is at level 3 assuming it adds +1 for each level, then that damage would be reduced to 9 and the hardened shield would not activate.
Does this sound right?
I think it is because how else would the Immortal make use of the hardened shield without it being constantly triggered by upgraded attacks.

Post has been edited 1 time(s), last time on Oct 13 2012, 12:00 pm by Raygoza.



None.

Oct 13 2012, 4:32 pm Pr0nogo Post #6



You could make part of the Hardened Shield ability the prevention of multiple attacks. That'd solve your problem.




Oct 16 2012, 8:11 pm Raygoza Post #7



A friend of mine says that that only works on Melee attack or instant attacks and not on projectile kind of damage nor splash damage.
Do you know of a solution to this?
I'd prefer that tank fire wont add up to get their damage reduced to 10.



None.

Oct 16 2012, 11:06 pm Observer12425 Post #8



It doesn't matter if two attacks occur on the same frame, they're still evaluated separately; two tanks firing on the same frame will inflict a net of 20 damage. Additionally, in triggers, multiple instances occurring simultaneously will still run as separate instances.

As for the shield upgrade, the damage is reduced before hardened shield is taken into consideration.



None.

Oct 17 2012, 4:24 am Sand Wraith Post #9

she/her

I don't know if it's possible to detect the separate evaluations though. I don't know of a hook to the damage evaluation function.




Oct 18 2012, 1:04 pm Raygoza Post #10



Observer, said that every attacking thing will have it's damage made calculated separately and even activate the hardened shield separately, does this even apply to the splash damage of siege tanks?
Meaning that the unit with this shield isn't the targeted one and is just getting hurt by the splash nearby.

Anyone may answer the question by the way.

To avoid duble posting here's my friend who is struggling with this and said this
The damage instances are calculated separately in game, but with plugins i can see what happens from frame to frame, so that is why i can not identify every damage instance. So unless i find a way to intercept the doWeaponDamage function used by SC i cannot be able to replicate the immortal shield.

How I ask your people, do you know how to find the doweapon Damage function taht is used by StarCraft?

Post has been edited 2 time(s), last time on Oct 20 2012, 7:49 pm by Raygoza.



None.

Oct 22 2012, 12:43 am pastelmind Post #11



You need to use JmpCallPatch() to hijack the doWeaponDamage() function, as well as write some custom assembly code.

Here's how I did the "Plasma Shields receive only 50% damage from independent-damage weapons" thing in my mini-mod.

Note: This code goes in game.h
Code
const DWORD DamagePlasmaShieldsInject     = 0x004799F7;
const DWORD DamagePlasmaShieldsReturn     = 0x00479A01;

void __declspec(naked) DamagePlasmaShields() {
    __asm {
        MOVZX eax, BYTE PTR [ebp+8]         ; Weapon ID
        MOV edx, [WeaponsDat_DamageType]     ; The address for this table is defined elsewhere...see BWAPI's Offsets.h for more info
        MOVZX edx, BYTE PTR [edx+eax]     ; Damage type
        CMP edx, 0                         ; Independent damage
        JNE IsNotVenomousDamage
        SAR esi, 1
IsNotVenomousDamage:
        CMP esi, 128                     ; This part also fixes the Irradiate/D-Matrix/Plasma Shields bug
        JGE DoDamageToShields
        MOV esi, 128
DoDamageToShields:
        CMP esi, ecx                     ; ESI = damage amount, ECX = shield amount
        MOV ebx, ecx                     ; EBX = amount of shields reduced
        JG HasMoreShieldsThanDamage
        MOV ebx, esi
HasMoreShieldsThanDamage:
        SUB esi, ebx
        CMP edx, 0                         ; Independent damage
        JNE ReturnToSC
        SAL esi, 1
ReturnToSC:
        JMP [DamagePlasmaShieldsReturn]
    }
}


Note: this code goes in qdp.cpp, inside the InitializePlugin() function code:
Code
    JmpCallPatch(DamagePlasmaShields, DamagePlasmaShieldsInject);


P.S. I personally think the Immortal in SC2 is a crappily-designed unit made by someone thinking "ooh siege tanks so IMBA, they melt all my dragoons when I A-move...let's make them resistant to tank fire so I can A-move and win heh heh". SRSLY all they're good for is (1) saying F-you to Terran mech and positional play (2) kill Zerg in all-in pushes.

Post has been edited 1 time(s), last time on Oct 22 2012, 12:54 am by RadiganP.



None.

Oct 22 2012, 2:41 pm Raygoza Post #12



You're probably right about the Immortal, Dragoons in SC1 died easily from a group of sieged tanks, seeems that's the only reason they made the Immortal in teh first place.
And thanks a lot for the help, how did you learn all this by the way?

I mean knowing stuff like this allows for advanced functions.

Post has been edited 4 time(s), last time on Oct 28 2012, 7:47 am by Raygoza.



None.

Oct 26 2012, 8:37 am pastelmind Post #13



Heinermann, the lead(?) developer of BWAPI, has been working on analyzing StarCraft's internal functions for quite a while. He was kind enough to send me a partial analysis of StarCraft.exe. To read it, you need a copy of IDA Pro + Hex-Rays plug-in.



None.

Oct 27 2012, 7:18 am Raygoza Post #14



Also how could you import triggers in a mod?
The code you posted may need some tweaks because it seem to work for every unit with shields, what's needed is to identify the unit who it is receiving the damage so only immortals activate the effect. sS my friend is also investigating assembly and the internal functions of SC to see what can be done.
But for the moment there's no solution.



None.

Oct 31 2012, 9:05 am pastelmind Post #15



Okay...how's about this? I haven't tested but it should work :)

Code
const DWORD DamagePlasmaShieldsInject     = 0x004799F7;
const DWORD DamagePlasmaShieldsReturn     = 0x00479A01;

void __declspec(naked) DamagePlasmaShields() {
   __asm {
       ; Register data at this point:
       ;
       ;   ESI: Damage amount, after subtracting Defensive Matrix and Plasma Shields upgrades
       ;   EDI: Pointer to the unit being hit
       ;   ECX: Current amount of shields
       ;
       ; Stack data at this point:
       ;
       ;   BYTE PTR  [EBP + 0x8] : Weapon ID
       ;   DWORD PTR [EBP + 0x14]: Pointer to the attacking unit (note: this may be NULL!)
       ;
       ; Goals:
       ;   (1) Store the amount of Plasma Shields subtracted in the EBX register
       ;   (2) Subtract the damage dealt to shields from the ESI register
       ;   (3) It's okay to use EAX/ECX/EDX, don't touch anything else!

       MOVZX eax, WORD PTR [edi+0x64]   ; EAX <- Victim unit's ID

       CMP eax, Immortal_unitID_1
       JE Is_Immortal
       CMP eax, Immortal_unitID_2
       JE Is_Immortal
       ; Repeat above 2 lines as many times as needed

Unit_Is_Not_Immortal:
       JMP DoDamageToShields

Unit_Is_Immortal:
       CMP esi, 2560                    ; ESI = damage amount. Let's say we want minimum damage to be 10, just like in StarCraft 2.
       JBE DoDamageToShields
       MOV esi, 2560                    ; Set damage to 10

DoDamageToShields:
       CMP esi, ecx                     ; ESI = damage amount, ECX = shield amount
       MOV ebx, ecx                     ; EBX = amount of shields reduced
       JG HasMoreShieldsThanDamage
       MOV ebx, esi
HasMoreShieldsThanDamage:
       SUB esi, ebx
       JMP [DamagePlasmaShieldsReturn]
   }
}




None.

Options
  Back to forum
Please log in to reply to this topic or to report it.
Members in this topic: None.
[11:50 pm]
O)FaRTy1billion[MM] -- nice, now i have more than enough
[11:49 pm]
O)FaRTy1billion[MM] -- if i don't gamble them away first
[11:49 pm]
O)FaRTy1billion[MM] -- o, due to a donation i now have enough minerals to send you minerals
[2024-4-17. : 3:26 am]
O)FaRTy1billion[MM] -- i have to ask for minerals first tho cuz i don't have enough to send
[2024-4-17. : 1:53 am]
Vrael -- bet u'll ask for my minerals first and then just send me some lousy vespene gas instead
[2024-4-17. : 1:52 am]
Vrael -- hah do you think I was born yesterday?
[2024-4-17. : 1:08 am]
O)FaRTy1billion[MM] -- i'll trade you mineral counts
[2024-4-16. : 5:05 pm]
Vrael -- Its simple, just send all minerals to Vrael until you have 0 minerals then your account is gone
[2024-4-16. : 4:31 pm]
Zoan -- where's the option to delete my account
[2024-4-16. : 4:30 pm]
Zoan -- goodbye forever
Please log in to shout.


Members Online: X405, Oh_Man