bugfix(ai): Fix isSupplySourceAttacked SCAN_RATE using frames instead of seconds - #3380
WebbontheWeb wants to merge 5 commits into
Conversation
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (2)
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review. WalkthroughBoth game variants set the supply-attack scan interval to 10 frames in ChangesSupply attack scan interval
Priority: ➖ Normal Estimated code review effort: 2 (Simple) | ~8 minutes Change: Bug fix · Severity of issue fixed: Medium Suggested reviewers: Merge Risk: ⚪ Minimal · up to Non-CRC builds now retain supply attacks for 10 seconds, while CRC-compatible builds preserve their prior behavior. No actionable merge-blocking risk remains; the change is ready for normal checks. Architecture SummaryArchitecture risk: 🔵 Low · up to The change affects 2 systems. Changed systems: Architecture concerns Review detailsSystems and components
Before / after behavior
🚥 Pre-merge checks | ✅ 3 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (3 passed)
Full details: Linked Issues checkExplanation Issue Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
7d340d2 to
63f40b9
Compare
Skyaero42
left a comment
There was a problem hiding this comment.
This change is fine pending a few nits.
63f40b9 to
9558198
Compare
xezon
left a comment
There was a problem hiding this comment.
Comments can be restyled, otherwise makes sense.
9558198 to
3e53105
Compare
3e53105 to
c288acb
Compare
c288acb to
e1e9c0e
Compare
|
Greptile still has an open review with a concern that looks valid. |
|
Considering the original code had a comment indicating that 10 seconds was intended for SCAN_RATE, I don't believe that's an issue. If we think it is, I could update to separate the "refresh rate" from SCAN_RATE. m_supplySourceAttackCheckFrame could be incremented using the previous 10 frame value, while the rest could use the corrected SCAN_RATE. |
|
I sent an inquiry to kabuse about this. |
|
-TanSo-
|
|
Thanks for the feedback, it's been updated. I split SCAN_RATE into REFRESH_RATE (how often isSupplySourceAttacked can be checked) and SCAN_WINDOW (how far back it's checking). I wasn't sure how to keep the EA comment, since it doesn't accurately describe either of the variables, so I moved it above with a disclaimer. I also updated my map script to verify that the refresh is tracked separately from the scan. Before the tank attacks it now checks whether the supply truck has been attacked. It checks again 4 seconds after the attack. The previous version doesn't register that it has been attacked (defeat): previoussupplyfix.mp4While the updated version does (victory): newsupplyfix.mp4Map: |
6ec4e6a to
9f1a75a
Compare
| if (body->getLastDamageTimestamp() + SCAN_RATE > curFrame) { | ||
| #if !RETAIL_COMPATIBLE_CRC | ||
| // Ignore undamaged units. | ||
| if (body->getLastDamageTimestamp() == 0xffffffff) { |
There was a problem hiding this comment.
This is not good, because it compares against a magic value. Better add a new function to the interface that tells whether this has damage. Judging by other code, it looks like the common way to check for damage is to test the DamageInfo.in.m_sourceID, but needs verifying whether this is really reliable.
There was a problem hiding this comment.
I don't think I could use DamageInfo.in.m_sourceId, since it can be invalid even after damage has been taken.
For example, ScriptActions::doNamedDamage sets damageInfo.in.m_sourceID = INVALID_ID;. It also looks like it can be set to healers, so I'd have to filter those out as well.
Is having the magic value within the interface function alright, with something like this in ActiveBody.h?
virtual Bool hasLastDamageTimestamp() const override { return m_lastDamageTimestamp != 0xffffffff; }
If not, I could also create a constant for the value within ActiveBody.h:
constexpr const UnsignedInt InvalidBodyTimestamp = ~0u;
Additionally, while investigating I noticed that StealthUpdate::allowedToStealth has basically the same check as the one I added. Would it be a good idea to update that as well?
if( self->getBodyModule()->getLastDamageTimestamp() != 0xffffffff )
Sorry for all the questions
There was a problem hiding this comment.
Yes the virtual Bool hasLastDamageTimestamp() makes sense and internally you can have named constant for it as well. You can update the other place(s) as well.
|
|
||
| virtual const DamageInfo *getLastDamageInfo() const override { return &m_lastDamageInfo; } ///< return info on last damage dealt to this object | ||
| virtual UnsignedInt getLastDamageTimestamp() const override { return m_lastDamageTimestamp; } ///< return frame of last damage dealt | ||
| virtual Bool hasLastDamageTimestamp() const override { return m_lastDamageTimestamp != InvalidBodyTimestamp; } ///< return whether a frame of last damage has been recorded |
There was a problem hiding this comment.
Or is there any reliable marker inside DamageInfo that we can use to determine that there was a damage event?
DamageInfoInput()
{
m_sourceID = INVALID_ID;
m_sourceTemplate = nullptr;
m_sourcePlayerMask = 0;
m_damageType = DAMAGE_EXPLOSION;
m_damageStatusType = OBJECT_STATUS_NONE;
m_damageFXOverride = DAMAGE_UNRESISTABLE;
m_deathType = DEATH_NORMAL;
m_amount = 0;
m_kill = FALSE;For example, m_amount > 0 or m_damageStatusType != OBJECT_STATUS_NONE or m_sourcePlayerMask != 0 ?
We would just need to find one bit that is always reliably different.
There was a problem hiding this comment.
I did my best to find something, I also sent AI to see if it could find anything.
Healing seems to overwrite the entire DamageInfo record, making it unreliable. A unit that has only been healed can have an identical DamageInfo to one that was just attacked and then healed.
There doesn't really seem to be a great solution that's not the timestamp.
…amage is recorded
Updates AIPlayer::isSupplySourceAttacked() to check within the last 10 seconds, instead of the last 10 frames, by multiplying the SCAN_RATE by LOGICFRAMES_PER_SECOND.
This changes AI behavior, so it may break retail compatibility. It's removed with RETAIL_COMPATIBLE_CRC enabled.
Verified using a custom map where a tank attacks a supply truck. After the first hit, the tank is deleted to prevent any more attacks.
After 4 seconds, a script checks whether the supply source is under attack. If true, victory. If false, defeat.
With change:
withsupplyfix.mp4
Without change:
withoutsupplyfix.mp4
SupplyAttack2386.zip
Included replays ran successfully.
This is a small commit, but I'm trying to get the hang of working with this codebase and the testing process