|
There are probably plenty more mistakes on Liquipedia but this one is quite big.
It assumes Stim Pack doubles the rate of fire which after testing it does not.
This page: Talk:Marine already mentions it and previous revisions claims too low DPS so i was wondering if someone could look into the code to find the true values?
Seeing as its quite a big difference between RoF +100% vs +65-70%, DPS 19.047 vs DPS 15.71 - 16.189 (33 or 34 hits per stim for 12.6 sec)
DPS without stim is accurate.
In a second test i got 78 shots in 30 seconds: RoF +63.87%, DPS 15.6, 32.76 shots per stim.
|
Netherlands4014 Posts
From playing a lot of UMS I have noticed that hold position units have a higher cooldown RoF (slower attack speed) than stopped/attack move units. This is especially noticable in marines and I believe it also affects melee units.
If someone is diving into this, it would also be interesting to see double check how Ensnare affects that...
|
On January 08 2023 16:48 Peeano wrote: From playing a lot of UMS I have noticed that hold position units have a higher cooldown RoF (slower attack speed) than stopped/attack move units. This is especially noticable in marines and I believe it also affects melee units.
If someone is diving into this, it would also be interesting to see double check how Ensnare affects that...
I know for sure Hold position is especially bad if you are switching target very often, like if you have a lot of marines and your target dies very fast. Its maybe because "Hold" incurs some extra penalty in target acquisition because its static state. Im just guessing here.
I even made a video about this 4 years ago: https://www.twitch.tv/videos/448085144
Ive not noticed any other unit in Hold to be affected.
Edit: I just remembered that Wraiths (probably any flying unit) when using Hold spreads the damage out (less overkill) so maybe it has something to do with it why its so slow at finding a new target.
|
Netherlands4014 Posts
The marines in your clip seems to acquire a new target in the same manner, I don't see any obvious difference anyway. I'm pretty sure it is not (only) target acquiring, but (also) RoF that is different.
For example on Poker D maps where you attack the lurker egg for the quest, I could see a notable difference in RoF between using attack/stop vs hold position.
|
On January 08 2023 18:48 Peeano wrote: The marines in your clip seems to acquire a new target in the same manner, I don't see any obvious difference anyway. I'm pretty sure it is not (only) target acquiring, but (also) RoF that is different.
For example on Poker D maps where you attack the lurker egg for the quest, I could see a notable difference in RoF between using attack/stop vs hold position.
Replay: https://repmastered.app/game/fNo8kfvZhPU1BDBip_w2KtQkX5VkAKxR4DXINR_9umU
Couldnt find any difference Hold vs Stop on a single target.
|
From OpenBW code (https://github.com/OpenBW/openbw/blob/master/bwgame.h#L13390):
int get_modified_weapon_cooldown(const unit_t* u, const weapon_type_t* weapon) const { int cooldown = weapon->cooldown; if (u->acid_spore_count) { cooldown += std::max(cooldown / 8, 3) * u->acid_spore_count; } int mod = 0; (1) if (u->stim_timer) ++mod; (1) if (u_cooldown_upgrade(u)) ++mod; (1) if (u->ensnare_timer) --mod; (2) if (mod > 0) cooldown /= 2; (3) if (mod < 0) cooldown += cooldown / 4; if (cooldown > 250) cooldown = 250; (4) if (cooldown < 5) cooldown = 5; return cooldown; }
This function handles unit base cooldowns: (1) if the unit is stimmed or has a cooldown upgrade (read: Adrenal Glands), one modifier is added. If the unit is ensnared, one modifier is subtracted
- This means that Ensnare directly counteracts the effects of Stim Packs and Adrenal Glands.
(2) If there is a positive modifier (if the unit has increased attack speed from Stim or Adrenal Glands), its base cooldown is halved (calculation in integers, so rounded down):
(3) For positive modifiers (unit ensnared and no attack speed upgrades), the base cooldown increases by 25% (also rounded down). (4) Base cooldown cannot be less than 5
- This means Cracklings have an actual base cooldown of 5.
|
The actual attack in the code (https://github.com/OpenBW/openbw/blob/master/bwgame.h#L2848):
void attack_unit_fire_weapon(unit_t* u) { st.prev_bullet_source_unit = nullptr; if (u_cannot_attack(u)) return; unit_t* target = u->order_target.unit; const weapon_type_t* weapon; int cooldown; int anim; if (target && u_flying(target)) { weapon = unit_air_weapon(u); cooldown = u->air_weapon_cooldown; anim = iscript_anims::AirAttkRpt; } else { weapon = unit_ground_weapon(u); cooldown = u->ground_weapon_cooldown; anim = iscript_anims::GndAttkRpt; } if (!weapon) return; if (cooldown != 0) { (5) if (u->order_process_timer > cooldown - 1) u->order_process_timer = cooldown - 1; return; } if (!unit_can_fire_weapon(u, weapon)) return; u_set_movement_flag(u, 8); (6) cooldown = get_modified_weapon_cooldown(u, weapon) + (lcg_rand(12) & 3) - 1; u->ground_weapon_cooldown = cooldown; u->air_weapon_cooldown = cooldown; sprite_run_anim(u->sprite, anim); } (5) This is where things start to get less straight forward. The game has a "hidden" "order process timer", that usually refreshes every 9 frames, but for attacking units is (supposed to be, at least) synchronized with the cooldown, so units do not have to wait for the 9 frames to expire before they can repeat attacking. However, the attack function is only run at each cycle reset. That means that cooldowns below 9 frames cannot be synchronized, and thus the effective cooldown defaults to the order refresh cycle length of 9 frames.. (6) The actual cooldown gets randomized within [base cooldown (-1/+2)], so on average it is expected to be .5 over the base cooldown.
|
The third factor that needs to be considered when calculating unit DPS is the length of its attack animation. This is determined by unit's attack iscript, which generally consists of 3 parts: an initialization (e.g. "Marine lifts rifle" - only some units have this), a repeating part (e.g. "Rifle fires") and a back-to-idle part (e.g. "Marine lowers rifle" - only some units have this).
- This is how the Marine's attack iscript looks like:
MarineGndAttkInit: playfram 0x00 # frame set 0 wait 1 playfram 0x11 # frame set 1 wait 1 playfram 0x22 # frame set 2 MarineGndAttkRpt: wait 1 nobrkcodestart playsnd 69 # Bullet\TMaFir00.wav attackwith 1 playfram 0x33 # frame set 3 wait 1 playfram 0x22 # frame set 2 wait 1 playfram 0x33 # frame set 3 wait 1 playfram 0x22 # frame set 2 wait 1 playfram 0x33 # frame set 3 wait 1 playfram 0x22 # frame set 2 wait 1 nobrkcodeend gotorepeatattk ignorerest MarineGndAttkToIdle: playfram 0x11 # frame set 1 wait 1 playfram 0x00 # frame set 0 wait 1 goto MarineWalkingToIdle We can determine the frame duration by simply summing up the the "wait" durations in each part, so there is a 2 frame attack initiation animation, then a repeating attack part of 8 frames, and a 2 frame back-to-idle animation. However, when processing iscripts, the game engine actually uses up two animation frames in the first game frame of the animation, so effectively animations are 1 frame shorter than their iscript suggests. This means a Marine's first attack on a target takes 2+8-1 = 9 frames to finish, any following repeating attack takes 7 frames.
- For the Firebat we get:
FirebatGndAttkInit: playfram 0x00 # frame set 0 FirebatGndAttkRpt: wait 1 nobrkcodestart imgol 421 0 0 # FlameThrower (thingy\flamer.grp) playfram 0x11 # frame set 1 attkshiftproj 24 wait 1 attkshiftproj 52 wait 1 attkshiftproj 80 wait 5 playfram 0x00 # frame set 0 wait 2 ignorerest FirebatGndAttkToIdle: goto FirebatWalkingToIdle
So there is no initiation animation in this case, and each attack repeat animation lasts for a total of 10-1 = 9 frames.
- The Zergling does not have any additional initiation frames, so every attack has an animation duration of 5-1 = 4 frames:
ZerglingGndAttkInit: playfram 0x00 # frame set 0 wait 1 nobrkcodestart playfram 0x11 # frame set 1 wait 1 playfram 0x22 # frame set 2 attackmelee 1 894 # Zerg\Ultra\zulHit00.WAV wait 1 playfram 0x33 # frame set 3 wait 1 playfram 0x44 # frame set 4 wait 1 nobrkcodeend gotorepeatattk goto ZerglingGndAttkToIdle
|
Now, to sum everything up, for a unit to initialize an attack, 3 conditions need to be met:
- Its attack cooldown timer must be 0.
- Its order process timer must be 0.
- Its previous animation (in case of a repeat attack, that is its previous attack animation) must be finished.
If the order process timer hits 0 and the unit is still in an active animation, the next attack cannot be executed and instead the order process timer will be reset to enter its next 9 frame cycle.
Let's summarize all the relevant unit stats from the previous posts:
UNIT_TYPE BASE_CD MIN_CD MAX_CD AVG_CD INIT_ANIMATION REPEAT_ANIMATION Marine 15 14 17 15.5 9 7 Marine (stimmed) 7 6* 9 7.5* 9 7 Firebat 22 21 24 22.5 9 9 Firebat (stimmed) 11 10 13 11.5 9 9 Zergling 8 7 10 8.5 4 4 Crackling 5 4 7 5.5 4 4
*less than 9-frame order process timer cycle!
So with all this information one can finally determine actual attack rates for units:
- For Marines, we get an average cooldown of 15.5 frames. However, when stimmed, the possible cooldowns 6,7,8,9 drop below the duration of the 9 frame order process timer cycle, so after each attack the game actually waits for the next reset of that cycle to initialize the next attack, making the effective cooldown 9.
This gives us an attack rate (and hence DPS) increase of 15.5/9 - 1 = 72.22…%
- For Firebats we get an effective DPS increase of 22.5/11.5 - 1 = 95.65…%
- For Cracklings the DPS increase is 8.5/5.5 - 1 = 54.5454…%
Note: There is also an additional 150 frame cycle for each unit in which its order process timer gets reset to a random value, which would lead to occasional irregularities in the attack cycle, further complicating matters and slightly distorting the result.
Some observations:
- One can easily observe that Marines under the effect of Stim have uniform cooldowns of 9 frames by attacking a high HP target. All Marines will fire at it in perfect unison.
- The effect of an attack animation exceeding the duration of the unit's cooldown can best be observed with the Ultralisk, which has a base attack cooldown of 15 frames, exactly the same as its attack animation. This means that its cooldown rolls of {14, 15, 16, 17}, with a theoretical average of 15.5, will effectively be executed as {23, 15, 16, 17}, with an average of 17.75.
This is the reason behind the irregular attack pattern one can observe with this unit, with a noticeable pause every 4 attacks, on average. This also explains why Ultralisk DPS is virtually unaffected by the effect of Ensnare. Ensnare increases the Ultralisk's base cooldown to 15 + ⌊15/4⌋ = 15+3 = 18, making {17,18,19,20} the possible cooldown rolls, with an average of 18.5, only slightly more than an unaffected Ultra.
- Another irregularity can be observed with Corsairs, which have a theoretical base cooldown of 8, less than the order process cycle, turning their theoretical {7, 8, 9, 10} rolls into effective cooldowns of {9, 9, 9, 10}, thus reducing their DPS by some 8% compared to what the unit stat suggests, as well as effectively lessening the effect Ensnare has, as it sets the base cooldown to 10, thus only causing a 1 - 9.25/10.5 = 11.90…% DPS reduction, as opposed to the nominal 20%.
Special thanks to Ankmairdor on the SSCAIT Discord, who helped me sort out all the nitty-gritty details
Here are some additional helpful sources for unit attack stats: https://docs.google.com/spreadsheets/d/1YWFzY0_MEE4fOy9HrvZCYSpRqjgSBdCeRYVxB6zmJpQ/edit#gid=0 and for animation durations: https://docs.google.com/spreadsheets/d/1bsvPvFil-kpvEUfSG74U3E5PLSTC02JxSkiR8QdLMuw/edit#gid=0
|
Super thanks for explaining this.
|
On January 08 2023 16:48 Peeano wrote: From playing a lot of UMS I have noticed that hold position units have a higher cooldown RoF (slower attack speed) than stopped/attack move units. This is especially noticable in marines and I believe it also affects melee units.
If someone is diving into this, it would also be interesting to see double check how Ensnare affects that...
On January 08 2023 18:28 MeSaber wrote:Show nested quote +On January 08 2023 16:48 Peeano wrote: From playing a lot of UMS I have noticed that hold position units have a higher cooldown RoF (slower attack speed) than stopped/attack move units. This is especially noticable in marines and I believe it also affects melee units.
If someone is diving into this, it would also be interesting to see double check how Ensnare affects that... I know for sure Hold position is especially bad if you are switching target very often, like if you have a lot of marines and your target dies very fast. Its maybe because "Hold" incurs some extra penalty in target acquisition because its static state. Im just guessing here. I even made a video about this 4 years ago: https://www.twitch.tv/videos/448085144Ive not noticed any other unit in Hold to be affected. Edit: I just remembered that Wraiths (probably any flying unit) when using Hold spreads the damage out (less overkill) so maybe it has something to do with it why its so slow at finding a new target.
This affects all units. I can't find the BWAPI guide online anymore, but from the downloaded copy of their FAQ this helps explain the context.
-- What are the differences between Stop and Hold Position? The difference will impact your unit's rate of fire. Hold position will make your unit's first shot faster, but consecutive shots will be slower, and Stop will make your unit's consecutive shots faster, but your first shot slower. When a unit is ordered to Hold Position, it runs a loop to acquire a target, perform the attack, and then stop moving, the additional command to stop moving requires additional frames, making your unit's consecutive attacks slower, but because Hold Position first acquires a target, its initial attack will be faster. Stop will order your unit to first stop doing everything immediately, which also stops it from acquiring a first target until it goes idle, increasing the time for a first attack, however it will not order your unit to stop moving after every attack, making consecutive attacks faster.
The below explanation may not represent the exact behaviour, but here is the short version: Stop: Stop -> Go to Idle -> Acquire Target -> Attack -> Attack -> ...• Hold Position: Stop -> Acquire Target -> Attack -> Stop -> Attack -> Stop -> ...
|
So ive concluded with this test that the difference Stop vs Hold only (at least from a meaningful standpoint) affects target changing. Shooting the same target until it dies is seemingly unaffected which is why we dont see a clear difference.
Stop vs Hold on a stimmed Marine however is the biggest difference where the Hold:ed Marine RoF is close to same as unstimmed.
As for goons target changing, they are already so slow that they seem unaffected. Unstimmed Marines however shows a clear difference as this video demonstrates. (its also shown in the replay killing half the lings unstimmed)
|
I propose that MeSaber gets a star for his contributions !
|
On January 11 2023 16:20 prosatan wrote: I propose that MeSaber gets a star for his contributions !
I already did. Thanks again Peeano! =)
|
Did u guys every dig on how it works for goliaths as they have different guns for ground and air atacks (this is also instant attack vs projectile)? I remember hearing somewhere that goliaths can somehow prioritize zealots (or i guess any other closest ground unit) while fighting carrieres + ground Ps army, but i never tested anything with it. Killing zealots 1st during fighjts against carriers would be actually useful.
|
On January 28 2023 10:19 WolFix wrote: Did u guys every dig on how it works for goliaths as they have different guns for ground and air atacks (this is also instant attack vs projectile)? I remember hearing somewhere that goliaths can somehow prioritize zealots (or i guess any other closest ground unit) while fighting carrieres + ground Ps army, but i never tested anything with it. Killing zealots 1st during fighjts against carriers would be actually useful.
Watch this: https://repmastered.app/game/Slpmy1-z47a5531VsWMY5RUMa1hO_VQLfrlkcscbCTg
Im explaining as i go.
I will make a better dedicated post about it soon.
|
Wow, thanks MeSaber! I learned something new today
|
Howdy, I've been working on putting together a document to explain some of the mechanics of attack orders with a focus on the timings. It addresses some closely related mechanics like target selection, but does not do much related to unit movement as that is usually trivial or quite difficult. I assumed that readers would have some familiarity with most concepts, so it skips some basic explanations to focus on the technical details. If something isn't clear or I forgot to explain something, please let me know so I can improve it.
I haven't got around to setting up Starcraft for my current computer, so I haven't verified it in-game or viewed the UMS replays.
I plan to add more unit types and a sheet for mid-attack target switching, but haven't got around to it yet as it took a while to assemble and proofread what I have already. If there are requests for certain units or scenarios I may try to include those.
https://docs.google.com/spreadsheets/d/1LhC8rdqHTrhze6Gh7HitemGs-g2Xq-hVRDaA6X4bBnM/edit?usp=sharing
|
Be sure to post that in an own thread. Solid info. *Keeps reading*
Hold position attacks random target is really something, can you elaborate why its random? As my Replay above show its not random for turret units (it does follow target priority though, workers are ignored if a higher priority target is available) but i presume it is for all others. What i mean by not random is that once a target has been selected, consecutive Hold commands wont change target.
I would love to see overkill examples.
Ie 12 gols firing at a group of lings/rines attack vs hold, how much overkill (wasted dmg) would it do.
Which units to use idle/attack and which to use Hold.
Hold seems to be better for some units say goon/gol, while its bad on rines.
I will do some experiments on this. Thank You!
|
On February 02 2023 14:28 MeSaber wrote:Be sure to post that in an own thread. Solid info. *Keeps reading* Hold position attacks random target is really something, can you elaborate why its random? As my Replay above show its not random for turret units (it does follow target priority though, workers are ignored if a higher priority target is available) but i presume it is for all others. What i mean by not random is that once a target has been selected, consecutive Hold commands wont change target. I would love to see overkill examples. Ie 12 gols firing at a group of lings/rines attack vs hold, how much overkill (wasted dmg) would it do. Which units to use idle/attack and which to use Hold. Hold seems to be better for some units say goon/gol, while its bad on rines. I will do some experiments on this. Thank You!  This document was mostly made in response to the questions and test cases posed by this thread, but it has already been posted as a resource on https://www.starcraftai.com/wiki/Main_Page.
Hold position calls a function that sorts potential targets into the lists by priority and then selects a random target from the highest priority non-empty list. This much was explained in the middle of the first page. It is not a pure random selection in the sense that if there are only two targets of different priorities then it will only select the higher priority one. If there are only two targets with the same priority, then the unit will have a 50% chance of selecting either one.
I have not yet covered any of the special case attack orders (unless we count Medics). If by turret units you mean structures that attack then those are not included yet. Structures use Tower Guard, which is very similar to Hold Position. If by turret units you mean the top half of goliaths and siege tanks, then those units have their own peculiarities and at a first glance they cannot Hold Position(Edit: verified, valid_for_turret is false) so no random targeting, only nearest targeting. So not only do they use orders that I have not covered, but the orders I have covered don't apply the same way to them.
The problem with calculating overkill with groups of units is the large number of unconstrained variables. Hold Position does random targeting, so you might get a good distribution, a bad distribution, or somewhere in between. Idle or Attack Move use nearest targeting, so the distribution depends on relative unit positions with two parallel lines having good distribution and two lines extending away from the center having bad distribution. The combination of random variations in cooldowns and the potential for target denial(1 frame window to kill a new found target and have to wait on another search cooldown without attacking) by your own units can become chaotic with many branching results. It's easy to do some basic damage distribution for one wave of attacks for Hold Position and trivial for other orders, but a full battle with so many units is more in the realm of stochastic measurements from simulations.
You cannot precisely determine what is the best command to use based only on the unit types. I provided the one-hit kill and two-hit kill scenarios to demonstrate this point. While units generally do not one-hit kill in game, a group of units can land enough hits on targets to result in the target dying from one hit from each attacker.
In the one-hit kill scenario there is a significant difference in timings between the orders for faster attacking units, but far less difference for slower units. Stop and Attack Unit (Once) are consistently slower than orders like idle or Attack Move and Hold position is usually the slowest.
In the two-hit kill scenario the timings were far more consistent with Stop and Attack Unit (Once) usually being the slowest and Hold Position generally matches idle and Attack Move for speed.
To sum up them as general guidelines: (Fast attacking are like stimmed marines or zerglings, slow attacking are like dragoons or mutalisks.) - Avoid using Stop to attack the enemy immediately, there are usually better alternatives. - Commanding units to Attack Unit is only better if there is one unit(e.g., high templar or defiler) that needs to die before other units or you are a bot that can issue perfectly timed and distributed commands to each of your units. For fast attacking units it is a bit slower than other commands and for slow attacking units it is either the same speed or slightly slower than other commands. - For fast attacking units avoid using Hold Position when there can be a lot of one-hit kills. In normal games this will rarely be relevant except when low health enemies approaches in a single file line, which will often not be much of a threat anyways. - Otherwise, the choice should be made according to whether the battle is moving and what sort of targeting is preferred.
|
|
|
|