Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
37 lines
2.8 KiB
Diff
37 lines
2.8 KiB
Diff
--- a/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoTransfer.c
|
|
+++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoTransfer.c
|
|
@@ -300,8 +300,8 @@
|
|
if (!m_Accepted) return Fail("native magazine move rejected; exact item will not be retried");
|
|
}
|
|
// Native callbacks may synchronously cancel this leaf or revoke ownership.
|
|
- if (m_LauncherMagazine && m_State != ERR_InfantryAmmoTransferState.PENDING) return m_State;
|
|
- if (m_LauncherMagazine && !Context()) return Fail("launcher custody authority changed during native submission");
|
|
+ if (m_State != ERR_InfantryAmmoTransferState.PENDING) return m_State;
|
|
+ if (!Context()) return Fail("magazine custody authority changed during native submission");
|
|
if (PhysicalProof())
|
|
{
|
|
m_State = ERR_InfantryAmmoTransferState.SUCCEEDED;
|
|
--- a/tests/test_infantry_ammo_transfer.py
|
|
+++ b/tests/test_infantry_ammo_transfer.py
|
|
@@ -150,6 +150,20 @@
|
|
rifle.parent=&recipient;loaded.parent=&rifle;loaded.magazine=∅empty.owner=&loaded;empty.well=&well;empty.rounds=0;muzzle.loaded=∅loaded.item=&loadedItem;loadedItem.slot=&loadedSlot;loadedSlot.container=&muzzle;loadedSlot.attached=&loaded;}
|
|
};
|
|
int main(){
|
|
+ // Rifle moves must obey the same irreversible cancellation boundary as launchers.
|
|
+ // Native inventory processing may synchronously invoke mission/ownership events.
|
|
+ for(int loss=0;loss<4;loss++){Fixture f;auto t=f.Job();
|
|
+ f.source.effect=[&](){if(loss==0)t.Stop();if(loss==1)f.truck.captured=true;if(loss==2)f.mode.active=false;if(loss==3)f.recipient.group=&f.otherGroup;f.Move();};
|
|
+ f.source.callback=1;assert(t.Tick(0)==FAILED&&t.Submitted()&&!t.Unresolved()&&f.source.calls==1);
|
|
+ assert(t.Tick(1)==FAILED&&f.source.calls==1);}
|
|
+ // Callback without custody after cancellation retains uncertainty until the
|
|
+ // original physical identity arrives, without resurrecting success or retry.
|
|
+ {Fixture f;auto t=f.Job();f.source.effect=[&](){t.Stop();};f.source.callback=1;
|
|
+ assert(t.Tick(0)==FAILED&&t.Submitted()&&t.Unresolved());f.Move();assert(!t.Unresolved());assert(t.Tick(1)==FAILED&&f.source.calls==1);}
|
|
+ // Coordinator must never book a cancelled native rifle transfer as delivery.
|
|
+ {SupplyFixture f;f.source.effect=[&](){f.c.m_Move->Stop();f.Move();};f.source.callback=1;
|
|
+ f.c.Transfer(0);assert(f.c.m_Spent.Count()==1&&f.c.m_Delivered==0);f.c.Transfer(1000);
|
|
+ assert(f.c.finishes==1&&f.c.m_Delivered==0&&f.c.m_Spent.Count()==1&&f.source.calls==1);}
|
|
// Failed callback settles only exact original unchanged custody; unknown never does.
|
|
{LauncherFixture f;f.source.callback=2;f.c.Transfer(0);assert(f.c.m_Move->Submitted()&&!f.c.m_Move->Unresolved()&&f.c.m_Spent.Count()==1);f.c.Transfer(1000);assert(f.source.calls==1&&f.c.m_Spent.Count()==1);}
|
|
for(int bad=0;bad<7;bad++){LauncherFixture f;f.c.Transfer(0);assert(f.c.m_Move->Unresolved());
|