Files
jakub 6a667d8deb Capture current mission, AI, map and administration development
Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
2026-10-13 22:52:53 +02:00

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());