Capture current mission, AI, map and administration development
Include the current addon, terrain integrations, tools, regression tests and recorded development evidence.
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
# Configuration and supply recovery — 3 October 2026
|
||||
|
||||
Malformed recognized configuration sections now prevent unrelated saves from replacing the only valid backup. Ordinary rifle resupply retains exact claims while its existing native transfer remains unresolved.
|
||||
|
||||
305 registered regression programs passed with unchanged captured inputs. Focused baseline failures and corrected-method controls are retained under config/ and supply/. Read review.json for exact source, input and preservation bindings.
|
||||
|
||||
The initial suite failure is retained under root/first-suite-failure/. Shared scanners now distinguish one unchanged, hash-pinned optional prefab identity comparison from hard resource references; the actual vanilla Character_Base load has an ordinary audited resource entry. Optional runtime dependency closure is unchanged. The proposal and scanner baseline failures are retained under optional-identity/.
|
||||
|
||||
Native checks were deferred because an existing game was running. No new native compilation, physical transfer, manual escape, multiplayer or FPS qualification is claimed. Original missions and four previous sealed packages remain unchanged.
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"reason": "Archive copies and directory rename completed, but local candidate-manifest variable seal shadowed seal() and prevented the final artifact index. Error cleanup also referred to already-renamed staging directory. No archived payload was lost. Documentation updates subsequently completed; attempted finalize refused the absent artifact index.",
|
||||
"copied_payloads_verified": 78,
|
||||
"production_inputs_unchanged": true,
|
||||
"original_failed_helper_preserved": "archive.py",
|
||||
"correction": "Rename sealing function to seal_archive and check staging exists before error cleanup. Validate every copied payload before recovering initial seal; ordinary finalization independently verifies post-suite documentation delta and preservation.",
|
||||
"native_or_test_failure": false
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Preview by default; --apply creates only this turn's new evidence archive.
|
||||
Run after successful bound suite and before separate documentation edits.
|
||||
No native launch, test execution, package rewrite or third-party payload copy.
|
||||
"""
|
||||
from pathlib import Path
|
||||
import argparse,hashlib,json,subprocess,sys,shutil,tempfile
|
||||
ROOT=Path('/home/jakub/devel/escapistsrereintroduced')
|
||||
WORK=Path('/tmp/erri-gameplay-root-1509')
|
||||
DEST=ROOT/'docs/evidence/config-supply-recovery-2026-10-03'
|
||||
PROPOSALS={'config':Path('/tmp/erri-config-review-1509'),'supply':Path('/tmp/erri-ai-review-1509'),'optional-identity':Path('/tmp/erri-optional-identity-1509')}
|
||||
ORIGINAL=Path('/home/jakub/devel/escapists')
|
||||
REFERENCE=Path('/tmp/erri-heartbeat-20260930-1542-reference.json')
|
||||
def sha(p):
|
||||
return hashlib.file_digest(p.open('rb'),'sha256').hexdigest()
|
||||
def load(p):return json.loads(p.read_text())
|
||||
def require(ok,why):
|
||||
if not ok:raise RuntimeError(why)
|
||||
def capture_inputs():
|
||||
sys.path.insert(0,str(ROOT/'tools'))
|
||||
from source_manifest import addon_manifest
|
||||
result=addon_manifest(ROOT)
|
||||
for folder in ['tests','tools','terrain-profiles','terrain-adapters','terrain-integrations']:
|
||||
result.update({str(p.relative_to(ROOT)):sha(p) for p in (ROOT/folder).rglob('*') if p.is_file() and '__pycache__' not in p.parts and p.suffix!='.pyc'})
|
||||
result.update({str(p.relative_to(ROOT)):sha(p) for p in (ROOT/'docs').iterdir() if p.is_file()})
|
||||
for name in ['README.md','.gitignore']:result[name]=sha(ROOT/name)
|
||||
return result
|
||||
|
||||
def seal():
|
||||
inventory={str(p.relative_to(DEST)):sha(p) for p in DEST.rglob('*') if p.is_file() and p.name!='artifact-sha256.json'}
|
||||
(DEST/'artifact-sha256.json').write_text(json.dumps(inventory,indent=2)+'\n')
|
||||
def finalize():
|
||||
require(DEST.is_dir(),'Archive must exist before documentation finalization')
|
||||
seal_before=load(DEST/'artifact-sha256.json')
|
||||
require({str(p.relative_to(DEST)):sha(p) for p in DEST.rglob('*') if p.is_file() and p.name!='artifact-sha256.json'}==seal_before,'Archive changed before final seal')
|
||||
changes=load(WORK/'post-suite-docs.json');inputs=load(WORK/'suite-inputs.json')
|
||||
require(set(changes)=={'docs/current-status.md','docs/configuration.md','docs/infantry-resupply.md'},'Unexpected post-suite document scope')
|
||||
expected=dict(inputs)
|
||||
for name,values in changes.items():
|
||||
require(inputs[name]==values['before'] and sha(ROOT/name)==values['after'],'Post-suite document binding mismatch '+name)
|
||||
expected[name]=values['after']
|
||||
require(capture_inputs()==expected,'Unreviewed post-suite input changes')
|
||||
baseline=load(WORK/'baseline.json');integrated=load(WORK/'integration.json')
|
||||
for name,digest in baseline['files'].items():
|
||||
expected_hash=changes.get(name,{}).get('after',integrated.get(name,{}).get('after',digest))
|
||||
require((ROOT/name).is_file() and sha(ROOT/name)==expected_hash,'Inherited path changed after docs '+name)
|
||||
index=hashlib.sha256(subprocess.check_output(['git','diff','--cached','--binary'],cwd=ROOT)).hexdigest()
|
||||
require(index==baseline['index_sha256'],'Index changed after docs')
|
||||
original=load(REFERENCE);require(len(original)==533 and all(sha(ORIGINAL/n)==v for n,v in original.items()),'Original changed after docs')
|
||||
for label in ['mounted-pair','mine-safety','ground-supply','depot-mines']:
|
||||
candidate=ROOT/f'.build/playtest-2026-10-03-{label}'
|
||||
require({str(p.relative_to(candidate)):sha(p) for p in candidate.rglob('*') if p.is_file()}==load(DEST/f'preservation/{label}-candidate-sha256.json'),'Candidate changed after docs '+label)
|
||||
for name in ['post-suite-docs.json','update-docs.py']:
|
||||
require(not (DEST/'root'/name).exists(),'Already finalized '+name)
|
||||
shutil.copyfile(WORK/name,DEST/'root'/name)
|
||||
(DEST/'finalization.json').write_text(json.dumps({'complete':True,'post_suite_document_changes':changes,'source_tests_tools_unchanged':True,'fresh_suite_after_prose_changes_claimed':False,'index_unchanged':True,'original533_unchanged':True,'four_sealed_candidates_unchanged':True},indent=2)+'\n')
|
||||
seal();print('Final document delta archived and evidence resealed')
|
||||
def main():
|
||||
parser=argparse.ArgumentParser(description=__doc__);group=parser.add_mutually_exclusive_group();group.add_argument('--apply',action='store_true');group.add_argument('--finalize',action='store_true');args=parser.parse_args()
|
||||
if args.finalize:return finalize()
|
||||
require(not DEST.exists(),'Refusing existing evidence archive')
|
||||
baseline=load(WORK/'baseline.json');integrated=load(WORK/'integration.json');suite=load(WORK/'suite-result.json');inputs=load(WORK/'suite-inputs.json')
|
||||
require(suite['exit']==0 and suite['inputs_unchanged'] is True,'Full unchanged-input suite required')
|
||||
programs=suite['programs'];require(programs and len(programs)==suite['regression_programs'] and all(p['exit']==0 for p in programs),'Incomplete/failed registered test list')
|
||||
require(capture_inputs()==inputs,'Current suite inputs differ; do not archive as current pass')
|
||||
for name,item in integrated.items():
|
||||
require(sha(ROOT/name)==item['after']==inputs[name],'Integrated source/test binding differs: '+name)
|
||||
for name,digest in baseline['files'].items():
|
||||
expected=integrated.get(name,{}).get('after',digest)
|
||||
require((ROOT/name).is_file() and sha(ROOT/name)==expected,'Unreviewed inherited change: '+name)
|
||||
index=hashlib.sha256(subprocess.check_output(['git','diff','--cached','--binary'],cwd=ROOT)).hexdigest()
|
||||
require(index==baseline['index_sha256'],'Index changed')
|
||||
original=load(REFERENCE);require(len(original)==533,'Unexpected original reference scope')
|
||||
require(all((ORIGINAL/name).is_file() and sha(ORIGINAL/name)==digest for name,digest in original.items()),'Original reference changed')
|
||||
# Only manifests are archived; sealed source/ZIP/PAK/runtime payloads stay in place.
|
||||
candidates=[];copies={}
|
||||
for label in ['mounted-pair','mine-safety','ground-supply','depot-mines']:
|
||||
sealpath=ROOT/f'docs/evidence/playtest-refresh-2026-10-03-{label}/candidate-sha256.json'
|
||||
seal=load(sealpath);candidate=ROOT/f'.build/playtest-2026-10-03-{label}'
|
||||
actual={str(p.relative_to(candidate)):sha(p) for p in candidate.rglob('*') if p.is_file()}
|
||||
require(actual==seal,'Sealed candidate changed: '+label)
|
||||
copies[f'preservation/{label}-candidate-sha256.json']=sealpath
|
||||
candidates.append({'candidate':str(candidate),'files':len(seal),'manifest_sha256':sha(sealpath),'unchanged':True})
|
||||
copies['preservation/original-reference.json']=REFERENCE
|
||||
base_review=Path('/tmp/erri-base-review-1509/finding.json');require(base_review.is_file(),'Missing bounded base review');copies['base-gameplay-review.json']=base_review
|
||||
root_required=['baseline.json','integration.json','suite-inputs.json','suite-result.json','full-suite.log','run-suite.py','native-deferred.json','optional-identity-audit.json','vanilla-character-audit.json']
|
||||
for name in root_required:
|
||||
require((WORK/name).is_file(),'Missing root evidence '+name);copies['root/'+name]=WORK/name
|
||||
for name in ['integrate.py','host-idle-inspection.json','preflight.json','review.json','final-review.json']:
|
||||
if (WORK/name).is_file():copies['root/'+name]=WORK/name
|
||||
failed=load(WORK/'first-suite-failure/suite-result.json')
|
||||
require(failed['exit']!=0,'Retained initial suite failure must remain a failure')
|
||||
for name in ['full-suite.log','suite-inputs.json','suite-result.json']:
|
||||
path=WORK/'first-suite-failure'/name
|
||||
require(path.is_file() and not path.is_symlink(),'Missing original suite failure '+name)
|
||||
copies['root/first-suite-failure/'+name]=path
|
||||
proposal_bindings={}
|
||||
# Explicit owned artifacts only. No recursive scratch copy or installed resources.
|
||||
optional=['baseline.json','finding.json','report.json','result.json','test-results.json','independent-review.json','review.json','apply-check.log','baseline-red.log','proposal-green.log','previous-validation-red.log','red.log','green.log','mutation-red.log','baseline-test.log','proposed-test.log','prepare.py','build-test.py','prepare-test.py','optional-identity-audit.json','vanilla-character-audit.json','vanilla-identity-proof.json','test-source-inputs.json']
|
||||
for label,folder in PROPOSALS.items():
|
||||
manifest_path=folder/'source-manifest.json';manifest=load(manifest_path)
|
||||
copies[label+'/source-manifest.json']=manifest_path
|
||||
patch=folder/'fix.patch';require(patch.is_file(),'Missing patch '+label);copies[label+'/fix.patch']=patch
|
||||
if 'patch_sha256' in manifest:require(sha(patch)==manifest['patch_sha256'],'Patch changed '+label)
|
||||
files=manifest.get('files',manifest);selected={}
|
||||
for name,item in files.items():
|
||||
if not isinstance(item,dict):continue
|
||||
digest=item.get('proposal_sha256',item.get('proposed'))
|
||||
if not digest:continue
|
||||
allowed=name.startswith(('addons/core/Scripts/Game/ERR/','tests/'))
|
||||
if label=='optional-identity':allowed=name in {'tools/resource_references.py','tools/check.py','tools/source_bundle.py','tests/test_external_addons.py','docs/vanilla-resources.json'}
|
||||
require(allowed and '..' not in Path(name).parts,'Unexpected proposal scope '+name)
|
||||
require(name in integrated and integrated[name]['after']==digest and sha(folder/name)==digest,'Unbound proposal '+name)
|
||||
copies[label+'/proposed/'+name]=folder/name;selected[name]=digest
|
||||
base=folder/'baseline'/name
|
||||
if base.is_file():
|
||||
expected=item.get('baseline_sha256',item.get('before_working',item.get('before')))
|
||||
require(expected and sha(base)==expected,'Proposal baseline mismatch '+name);copies[label+'/baseline/'+name]=base
|
||||
require(selected,'Empty proposal '+label)
|
||||
require((folder/'independent-review.json').is_file(),'Independent review required '+label)
|
||||
independent=load(folder/'independent-review.json')
|
||||
require(independent.get('approved') is True and independent['patch_sha256']==sha(patch) and independent['source_manifest_sha256']==sha(manifest_path),'Independent review binding differs '+label)
|
||||
for name,digest in manifest.get('artifacts',{}).items():
|
||||
require(Path(name).name==name and sha(folder/name)==digest,'Manifest artifact differs '+label+'/'+name)
|
||||
if label=='optional-identity':
|
||||
for name in ['optional-identity-audit.json','vanilla-character-audit.json']:
|
||||
require(sha(folder/name)==manifest[name+'_sha256']==sha(WORK/name),'Audit evidence differs '+name)
|
||||
audited=manifest['audited_source']
|
||||
require(audited['modified'] is False and sha(ROOT/audited['path'])==audited['sha256'],'Optional audited source changed')
|
||||
if 'test_results_sha256' in manifest:require(sha(folder/'test-results.json')==manifest['test_results_sha256'],'Test result binding differs '+label)
|
||||
for name in optional:
|
||||
if (folder/name).is_file():copies[label+'/'+name]=folder/name
|
||||
for log in folder.glob('*.log'):
|
||||
require(log.is_file() and not log.is_symlink(),'Unexpected log link '+str(log))
|
||||
copies[label+'/'+log.name]=log
|
||||
proposal_bindings[label]={'manifest_sha256':sha(manifest_path),'patch_sha256':sha(patch),'files':selected}
|
||||
deferred=load(WORK/'native-deferred.json');require(deferred['native_check_started'] is False,'Unexpected native scope')
|
||||
report={'complete':True,'scope':'Configuration and finite supply recovery plus bounded resource audit correction; no new native qualification or package change','suite':{'exit':0,'inputs_unchanged':True,'regression_programs':len(programs),'suite_inputs_sha256':sha(WORK/'suite-inputs.json'),'suite_result_sha256':sha(WORK/'suite-result.json')},'integration_sha256':sha(WORK/'integration.json'),'proposals':proposal_bindings,'preservation':{'baseline_paths':len(baseline['files']),'inherited_unchanged_except_integrated':True,'index_sha256':index,'original_files':533,'original_manifest_sha256':sha(REFERENCE),'original_unchanged':True,'sealed_candidates':candidates},'native':deferred,'retained_initial_suite_failure':{'exit':failed['exit'],'regression_programs':failed['regression_programs'],'suite_result_sha256':sha(WORK/'first-suite-failure/suite-result.json')},'archive_files':{name:sha(path) for name,path in sorted(copies.items())}}
|
||||
print(json.dumps({'ready':True,'destination':str(DEST),'files':len(copies),'programs':len(programs),'apply':args.apply},indent=2))
|
||||
if not args.apply:return
|
||||
# All binding/preservation checks finish before the first destination mutation.
|
||||
DEST.parent.mkdir(parents=True,exist_ok=True)
|
||||
staging=Path(tempfile.mkdtemp(prefix='.config-supply-recovery-',dir=DEST.parent))
|
||||
try:
|
||||
for name,path in copies.items():
|
||||
out=staging/name;out.parent.mkdir(parents=True,exist_ok=True);shutil.copyfile(path,out)
|
||||
require(sha(out)==report['archive_files'][name],'Copy verification failed '+name)
|
||||
(staging/'review.json').write_text(json.dumps(report,indent=2)+'\n')
|
||||
shutil.copyfile(Path(__file__),staging/'archive.py')
|
||||
(staging/'README.md').write_text('# Configuration and supply recovery — 3 October 2026\n\n'
|
||||
'Malformed recognized configuration sections now prevent unrelated saves from replacing the only valid backup. Ordinary rifle resupply retains exact claims while its existing native transfer remains unresolved.\n\n'
|
||||
+str(len(programs))+' registered regression programs passed with unchanged captured inputs. Focused baseline failures and corrected-method controls are retained under config/ and supply/. Read review.json for exact source, input and preservation bindings.\n\n'
|
||||
'The initial suite failure is retained under root/first-suite-failure/. Shared scanners now distinguish one unchanged, hash-pinned optional prefab identity comparison from hard resource references; the actual vanilla Character_Base load has an ordinary audited resource entry. Optional runtime dependency closure is unchanged. The proposal and scanner baseline failures are retained under optional-identity/.\n\n'
|
||||
'Native checks were deferred because an existing game was running. No new native compilation, physical transfer, manual escape, multiplayer or FPS qualification is claimed. Original missions and four previous sealed packages remain unchanged.\n')
|
||||
require(not DEST.exists(),'Destination appeared during finalization')
|
||||
staging.rename(DEST)
|
||||
seal()
|
||||
except BaseException:
|
||||
shutil.rmtree(staging);raise
|
||||
if __name__=='__main__':main()
|
||||
@@ -0,0 +1,89 @@
|
||||
{
|
||||
"base-gameplay-review.json": "70d6efba95e2f5c15389cebf3c95b16b50e45e2e94d5260fe5ff7531c75cbdda",
|
||||
"review.json": "dff090481a3ac2436e0465ccce9beb8cd06b010a687682882ed274f37d63ab0a",
|
||||
"archive.py": "ab8e51ac288a529ead61c498d6286d0e19b408cefaeaf42a609c2634c4f5813a",
|
||||
"README.md": "d00107d95e4531d0749ee4096cb59bf27641e3a0883439d85103be7df1e0fd9a",
|
||||
"archive-recovery.json": "a60b86e1a180850d52a812445b61bc9fd59c15e8156c8e70faf228b34d60067d",
|
||||
"finalization.json": "c16ea94ac2f169f8a8996896787a6c859fe1db3287d74045a8626b611065e3b1",
|
||||
"preservation/mounted-pair-candidate-sha256.json": "9fee715f8c9c324c465387ba1f88744c9c3748cb49668ce65e9c9500a38b14d7",
|
||||
"preservation/mine-safety-candidate-sha256.json": "202fa0854cf60a6c08ace1f22b276d826abcb538c79b6e052b48e5e51f458a87",
|
||||
"preservation/ground-supply-candidate-sha256.json": "0b58fde4127486894917db58ce92b684f984233b341317418e336b1740cac107",
|
||||
"preservation/depot-mines-candidate-sha256.json": "c91acda173e2914fea59fd3e264a451158ee21d85918fe1ec5c8312dd46f7074",
|
||||
"preservation/original-reference.json": "661c5ddf080c4ba8d4463aa4907f739d4d96acaa8694ac8d6f3d85bb94231226",
|
||||
"root/baseline.json": "b754fa12b42d106b63831e900ccc2f6ad828406e364991112acb20094b439e09",
|
||||
"root/integration.json": "60e8910288a739e572c65e32cc32bbeab2f7de0b8e9ad484f0efa993f467f08c",
|
||||
"root/suite-inputs.json": "d4ddadb4624be964249ed736bb33bf03d7df796f9ff1493cb575cc6b8e92d77d",
|
||||
"root/suite-result.json": "0e65713b176ce28a334d8c4f860436205fe584f169752b4295526809d78a329f",
|
||||
"root/full-suite.log": "c304c3d5bba1b1664782d7bac90881c1859a75d263587fcc9182d1d746251a5c",
|
||||
"root/run-suite.py": "8ce92c56b5553d2a26fee220578e02d39a18a541bdc5f9d6dc19262ae4918fb5",
|
||||
"root/native-deferred.json": "5f755cf077e7d1c8ae4efad2e69048bc6ebef44399a3d7af7329f02343d75367",
|
||||
"root/optional-identity-audit.json": "87581b0c0c210e76dfdb9f5285417fed0fa164a58897a0012f964e795236275b",
|
||||
"root/vanilla-character-audit.json": "625379d9757e265e4947b822df0b64548b4b36613c55ada811663fba2ede871c",
|
||||
"root/integrate.py": "047c5994de86fc4babe4d9937c5facebc1e8b8312c7e0c9195e3a92010e3d1eb",
|
||||
"root/final-review.json": "92c25e3264133bc5d948c306bbe18fa465c441f97eb6996159433777cc1385bf",
|
||||
"root/archive-recovery.py": "91c6331ae7a721519cceec32a043affb76f2c564fdb7a0be008d8fab6402c403",
|
||||
"root/recover-archive.py": "337c8ef817837189ddcb56cb1b1cdab732711ec9ec3af537ea460ca6c25b7cf0",
|
||||
"root/post-suite-docs.json": "40d571b778323f38ac50ea9d5dcaf6f6a350ff9f6f20541c56f54d9f48a3b290",
|
||||
"root/update-docs.py": "331ed1d69cee0de7ee621697dc71b5f4617330d6a8f6407defb0c08c5591542b",
|
||||
"config/source-manifest.json": "2fd845ee6bd744e8c405f7e9dc40562df2a82cb2ff215cf0df7db481b85e735f",
|
||||
"config/fix.patch": "9ddefab1f87ef5d0924e096d51359482e43de9b250c7986c98360c97d432104d",
|
||||
"config/finding.json": "b06cf00382b3dd855cdf0c10c433932e9b1ad1d38d9ba296d0f91596b397c4b5",
|
||||
"config/test-results.json": "20af613fa5168dc7e93734b4ce1b0f5ef771946bc310e802b58e93dee09f89cd",
|
||||
"config/independent-review.json": "52e31b6e43dd37a2a797ecb980f7f8064d48de5231afa66d031f018fd7662371",
|
||||
"config/apply-check.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
"config/baseline-red.log": "a51853e6c0004c0c17b932fb4b2d201d7618648fe1ba6f802c31011228f3c404",
|
||||
"config/proposal-green.log": "1c414380eb465210146fed3d49b2108f593abd625b6ffb92f50e7f27131de6f0",
|
||||
"config/previous-validation-red.log": "0f8438d6a2ad9c46e8372fc1ad3f4e2c01d07179c3bc19d1279de1066ae42ae9",
|
||||
"config/build-test.py": "0e16f59444f0bd9b16a6f5a53fc36bfd6136e2060a4d7f96ad24be31813ee783",
|
||||
"supply/source-manifest.json": "7d98965a23809a0dc4999a762c6dd8240f37cfc68290035fb884ab07744e33ea",
|
||||
"supply/fix.patch": "ece65980fbe99627d6984e3d964a4aa30d6d80bcc44939245c49644e0225bb6a",
|
||||
"supply/baseline.json": "d053779f016057f2d89b18321a9a64159019885cb5eb21bf7e68309624cfcbd5",
|
||||
"supply/finding.json": "7a573f29c1c6c1d66ab9cce77263db84a6adae930153da3861354994f66d318d",
|
||||
"supply/test-results.json": "c68108d773de900e6d559fd8f63829b8bdb2084a3e885820a67aae89d3b7bed9",
|
||||
"supply/independent-review.json": "1fbfdfd38b6e9ba0591cfe9557e0dd4c72f74f6d6094253dd66323bf537223b0",
|
||||
"supply/apply-check.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
"supply/prepare.py": "14e636685a8b1ab125350e35eaa6417ceab9b3a60b002ba338ce25a9f5f61b96",
|
||||
"supply/proposal-test_infantry_ammo_transfer.log": "27d49fc10aa8a5f150cdae91a192788fe84cb01b5998760ad6aba83d3c44d469",
|
||||
"supply/proposal-test_infantry_resupply_coordinator.log": "956e431f178f472436c3abd25fcd34bfd6309ae1446335c9fbc23229428bc7cd",
|
||||
"supply/proposal-test_infantry_resupply_planning.log": "c12aa5ba9b2141830d3916c3ab0285c06cbb44f606a9f8fbe42787ade0e67b21",
|
||||
"supply/baseline-test_infantry_resupply_planning.log": "bf89459dc00b4db4c351933d382c400b1736f885a69443856fdd630175b742ff",
|
||||
"optional-identity/source-manifest.json": "fdb25d5b1bdefc114291475dc9b68a195a3aadc55e8c7b662fc2d5a913b2b2e3",
|
||||
"optional-identity/fix.patch": "d02ed79ad88f21138e66a77189bbaf7130cf1e36331f47f1c3b5db026a1953c1",
|
||||
"optional-identity/finding.json": "0db9e9ba31079f7fc7ea7bb199976c00570cc625ed048ad6ba2f76f6bed27efb",
|
||||
"optional-identity/test-results.json": "a3c9e916289b106bd0c3befbf7c675ea8f08579359b7d074538e787705aa063d",
|
||||
"optional-identity/independent-review.json": "6c3e08c39f1ab4b082e71d69d3420950879c97913595a61471ee32a0a7e5ebb7",
|
||||
"optional-identity/apply-check.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
"optional-identity/proposal-green.log": "dec02332cb628dd7b75eff0af6e7a6c0f2f5ccab482b8d20b76bf97dcdc62468",
|
||||
"optional-identity/prepare-test.py": "8d38dab2a814c952918d55e651d5ef1031123f85b017799e56aa94621ab14ef4",
|
||||
"optional-identity/optional-identity-audit.json": "87581b0c0c210e76dfdb9f5285417fed0fa164a58897a0012f964e795236275b",
|
||||
"optional-identity/vanilla-character-audit.json": "625379d9757e265e4947b822df0b64548b4b36613c55ada811663fba2ede871c",
|
||||
"optional-identity/vanilla-identity-proof.json": "ac34caa4dcdc2ef734d6013da57838526468340d684acce8c1ad7a0469282d02",
|
||||
"optional-identity/test-source-inputs.json": "1fcc9536c2fcbdd332cb62ba01a02bdc190f5fc6bbc8975f5abf2c94f6811c06",
|
||||
"optional-identity/baseline-bundle-red.log": "5a326f80f5671a5c56f5f5ba6880942fcd83821675a0f8454ee860541d4e8f52",
|
||||
"optional-identity/baseline-scanner-red.log": "e18a68ba778b467108eeba569dd0d924abfbdad365e7bc482708bb243b8a2943",
|
||||
"optional-identity/proposal-initial-missing-vanilla.log": "0950195851664e3296729d14adaa159459b95adf7905537b18be74ff52f4009e",
|
||||
"optional-identity/baseline/tools/check.py": "d60357b1c6b0d61dfeb80148d4a6684121e468bd3a044a9adc8f76752f60a41a",
|
||||
"optional-identity/baseline/tools/source_bundle.py": "e8b06f9340a8d67da992373f4642385a028acebe9aa1b3752f62cab95c8fce98",
|
||||
"optional-identity/baseline/tests/test_external_addons.py": "4e2c3fa2c92661c49ea0c492648b736bebd54f24cd244f3fe27710a0c7a487ab",
|
||||
"optional-identity/baseline/docs/vanilla-resources.json": "588192d151f382b612ca6ce9a564193b57d4a9e7ce9a3918bf8ad2f7e877d1f4",
|
||||
"optional-identity/proposed/tools/resource_references.py": "2e6080227bece7213fd67e58e7a4d27aba9847e610f8c000f6f2f65b623e567c",
|
||||
"optional-identity/proposed/tools/check.py": "fb6bf594dd6544abee60d4e172d1d28f34f223cae93678e2356156f34e653f00",
|
||||
"optional-identity/proposed/tools/source_bundle.py": "5d1d0150d8009f24a950ee85501d0da8b1f69d5fcbb5a7118b08957f14658f57",
|
||||
"optional-identity/proposed/tests/test_external_addons.py": "4b0eb867b3aec1bca906f68168948a4e42cdc0bced0bec2856a3ba68187a6e24",
|
||||
"optional-identity/proposed/docs/vanilla-resources.json": "e10f60ce74a743b4619b0c2f2cc7fefcf09a94ab3ca1cbb332f386d6fb0da387",
|
||||
"supply/baseline/tests/test_infantry_resupply_planning.py": "20747ffda8754f81f3b9e9912b9f60a300c439f2ea2c473bb900302f61dd691f",
|
||||
"supply/baseline/tests/test_infantry_resupply_coordinator.py": "f9cf7d583a25a12cec9f5f80539b2590449560331f4ef34e33ea2db283c5d54a",
|
||||
"supply/baseline/tests/test_infantry_ammo_transfer.py": "0d2ebe4d5c18a4187745784013d07df621b8495967d0c01f39bd5a68ae574d26",
|
||||
"supply/baseline/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c": "1bfc1079961eaecee0c1ebb434570aaeb359c008f9f309033b33582092557b35",
|
||||
"supply/proposed/tests/test_infantry_resupply_planning.py": "9879a27816dbc6b9c4da19c4714407614b4c6e20b2dd831b2701e5f3500ede6a",
|
||||
"supply/proposed/tests/test_infantry_resupply_coordinator.py": "a7eaa26e21f587fd8abde5dee6f7f8afc1e9f2f7ed0bcf40ed6a087a56908adc",
|
||||
"supply/proposed/tests/test_infantry_ammo_transfer.py": "18029a092262d0d1a309108a158597a174c1a05f58157eafd096c1c707fa0e29",
|
||||
"supply/proposed/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c": "ca8eee2704e7758172e33014404bb1307c683f19b561b840d4592f6312051e62",
|
||||
"config/baseline/tests/test_profile_config.py": "088ea06a32a59711d8e02c426d5fdd4a14657cded725b831af312bd8eb5f133f",
|
||||
"config/baseline/addons/core/Scripts/Game/ERR/00_Core/ERR_ProfileConfig.c": "ac28363fd5861523db278bb18aa5499f356fef69d35435d1f4ef547da704b67d",
|
||||
"config/proposed/tests/test_profile_config.py": "727dc330db23d744fca0c965474f834d0cb70432e58938f286fde28bd8415435",
|
||||
"config/proposed/addons/core/Scripts/Game/ERR/00_Core/ERR_ProfileConfig.c": "9df8ccf45fc2ed12f4b14d08270878696e8785760a3ae51fe032b6f3818fc0e6",
|
||||
"root/first-suite-failure/full-suite.log": "39ba40807787077d5ac76006ca565dad8a1bb681f9f115c3cc5dc8afa531f944",
|
||||
"root/first-suite-failure/suite-inputs.json": "6d7e74d97cd0955d700b9d09d7f14828da6c71dcc9d67febda4dd2a6be7d0c70",
|
||||
"root/first-suite-failure/suite-result.json": "47ba24ecb4524a253ff37aaab6273ec866d7f255cd158b0db9fd566f8c060b27"
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"complete": true,
|
||||
"verdict": "No new demonstrated production defect in this bounded review; no patch proposed.",
|
||||
"scope": "Ordinary radio occupancy/completion, extraction resolution versus incapacitation, canonical player identity/disconnect and terminal callback cleanup.",
|
||||
"findings": [
|
||||
{
|
||||
"source": "ERR_RadioDefenceService.c:CanBegin/CanDefend/Tick",
|
||||
"evidence": "Tuning/defence require current roster-controlled friendly actor and conscious capability. Each server sample resets the uninterrupted interval when no defender remains, including disconnect and empty-server samples; another remaining defender preserves progress. Completion latches before callbacks.",
|
||||
"coverage": "test_radio_defence_policy.py actual matrix, handover/interruption/clock/duration controls; test_progression_identity.py current canonical body checks."
|
||||
},
|
||||
{
|
||||
"source": "ERR_GameMode.c:ServerTick; ERR_ExtractionService.c:Tick/Resolve/ConnectedWinners",
|
||||
"evidence": "Extraction resolves before recovery/no-survivor defeat. Only living original participant accounts physically aboard assigned helicopter outside boundary in EXTRACTION enter result. Unconscious/reserved disconnected passengers deliberately qualify. Result is latched before event; current connection must still map to same escaped account for winner IDs.",
|
||||
"coverage": "Existing ERR_NativeExtractionProbe explicitly specifies12 occupants, prior-phase crossing, unconscious/dead/left-behind/recycled-connection cases; this review did not rerun or qualify that fixture."
|
||||
},
|
||||
{
|
||||
"source": "ERR_PlayerRoster.c; ERR_SpawnLogic.c:OnPlayerDisconnected_S",
|
||||
"evidence": "Disconnect cancels pending admission then removes connection mapping while retaining round account/body/used-life record. Recycled connection IDs cannot inherit the old account. CurrentActor additionally requires actual native controller-body reciprocity."
|
||||
},
|
||||
{
|
||||
"source": "ERR_RecoveryService.c:Tick; ERR_GameMode.c:OnGameModeEnd/StopServices",
|
||||
"evidence": "Disconnected conscious reserved body remains a potential rescuer; recovering casualties prevent stalled defeat; empty server resets stall. Native end latches inactive before cleanup; existing actual tests cover reentrant cleanup and stale preparation callback refusal.",
|
||||
"coverage": "test_recovery_policy.py and test_native_end_lifecycle.py inspected."
|
||||
}
|
||||
],
|
||||
"limits": [
|
||||
"Read-only source/test audit, no test or compiler execution and no native/GUI/process interaction.",
|
||||
"No multiplayer, manual escape or native physical proof inferred.",
|
||||
"Current status already explicitly preserves those qualification limits; no unsupported missing-feature claim or speculative refactor."
|
||||
],
|
||||
"hashes": {
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_GameMode.c": "89a29c03ba225acbbb9fa3c58a721aced91a77bc0c77046d697005a6d7c48bb9",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_RadioDefenceService.c": "f5f0bf1352141f933d0edb5630e30541e001dc07e1d2c8529b29cc159c126b13",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ExtractionService.c": "91357099b4e0401196b67d48963be54be30e56bdba57cdac67dc20b8ebb883e9",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerRoster.c": "c038dac0f749bd29ebc35a4e952904b41a34417ba738904d5efcd1833a263e0b",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnLogic.c": "47a39c951be71bfcf1cc50526d507d0f9d8ef2fc09408697b6fe6b0dc5a529e2",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_RecoveryService.c": "86f9a7769e3ccb19fc61127fe2fee2ad0dd825487a5cd59f334de8b9741c93cf",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeExtractionProbe.c": "4b09385f73206de004f4f3c38a6192fd658a0d2012482dc5a84dff1599ceb972",
|
||||
"tests/test_radio_defence_policy.py": "48c9c01dc6135a3f6d2187b0974645758040f041c3c2c2c26b14222fc572dfe1",
|
||||
"tests/test_progression_identity.py": "2fb3725aa735e00b20ba7a4ac45f8e087d4346c58a176bee091bab0a9755c1df",
|
||||
"tests/test_player_admission_policy.py": "745ec0a9e491ffcf5bec53ebf67ecee8333f4dcfa5d19bafbde31cbd1cad7f8b",
|
||||
"tests/test_native_end_lifecycle.py": "8b187723c9039e68e3e590c812c91dcffe1e5917d4e450ed798dc177888fda7a",
|
||||
"tests/test_recovery_policy.py": "adc4966ab92f0849d08636d93da5bd02b9162d1ad7369b325a1a357903abaa55",
|
||||
"docs/current-status.md": "5d4494b599f9379ef137222230ae0ea79d579e7a032772aa97de0138138b319c"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
check: /tmp/err-policy-r3sh7kea/check.cpp:93: int main(): Assertion `!Store::Save("mission",change)' failed.
|
||||
PASS: shared config transaction rejects client writes, preserves first-save/prior/fallback state across open, write, backup, partial-copy, readback and mismatch failures
|
||||
Traceback (most recent call last):
|
||||
File "/tmp/erri-config-review-1509/tests/test_profile_config.py", line 105, in <module>
|
||||
run(r"""
|
||||
~~~^^^^^
|
||||
#include <cassert>
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
...<64 lines>...
|
||||
}
|
||||
^
|
||||
""")
|
||||
^^^^
|
||||
File "/home/jakub/devel/escapistsrereintroduced/tests/policy_harness.py", line 14, in run
|
||||
subprocess.run([str(p/'check')],check=True)
|
||||
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/usr/lib/python3.14/subprocess.py", line 578, in run
|
||||
raise CalledProcessError(retcode, process.args,
|
||||
output=stdout, stderr=stderr)
|
||||
subprocess.CalledProcessError: Command '['/tmp/err-policy-r3sh7kea/check']' died with <Signals.SIGABRT: 6>.
|
||||
+231
@@ -0,0 +1,231 @@
|
||||
// One operator-owned document. Legacy names identify sections internally only;
|
||||
// custom paths used by isolated probes keep their original standalone behavior.
|
||||
class ERR_ProfileConfig
|
||||
{
|
||||
static const string PATH = "$profile:Escapists.json";
|
||||
static const string VOICE = "$profile:EscapistsWelcomeVoice.json";
|
||||
static array<string> LegacyPaths()
|
||||
{
|
||||
return {ERR_Settings.PATH, ERR_ContentSettings.PATH, ERR_FactionSelection.PATH, ERR_TerrainPreference.PATH, ERR_ItemPreferences.PATH, VOICE};
|
||||
}
|
||||
static string Section(string path)
|
||||
{
|
||||
if (path == ERR_Settings.PATH) return "mission";
|
||||
if (path == ERR_ContentSettings.PATH) return "mods";
|
||||
if (path == ERR_FactionSelection.PATH) return "factions";
|
||||
if (path == ERR_TerrainPreference.PATH) return "terrain";
|
||||
if (path == ERR_ItemPreferences.PATH) return "items";
|
||||
if (path == VOICE) return "voice";
|
||||
return "";
|
||||
}
|
||||
static bool Text(string path, out string text)
|
||||
{
|
||||
FileHandle file = FileIO.OpenFile(path, FileMode.READ);
|
||||
if (!file) return false;
|
||||
int length = file.GetLength();
|
||||
if (length < 2 || length > 8388608) { file.Close(); return false; }
|
||||
file.Read(text, length); file.Close();
|
||||
return text.Length() == length;
|
||||
}
|
||||
// The engine validates JSON syntax. This scan only separates root members,
|
||||
// retaining unknown fields and dormant addon entries without reinterpreting them.
|
||||
static bool Split(string text, map<string, string> members)
|
||||
{
|
||||
members.Clear(); text.TrimInPlace();
|
||||
JsonLoadContext valid = new JsonLoadContext();
|
||||
if (text.Length() < 2 || text.Substring(0, 1) != "{" || !valid.LoadFromString(text)) return false;
|
||||
int depth, start = 1, colon = -1;
|
||||
bool quoted, escaped;
|
||||
string block;
|
||||
for (int i = 0; i < text.Length(); i++)
|
||||
{
|
||||
if (i % 1024 == 0) block = text.Substring(i, Math.Min(1024, text.Length() - i));
|
||||
string ch = block.Substring(i % 1024, 1);
|
||||
if (quoted)
|
||||
{
|
||||
if (escaped) escaped = false;
|
||||
else if (ch == "\\") escaped = true;
|
||||
else if (ch == "\"") quoted = false;
|
||||
continue;
|
||||
}
|
||||
if (ch == "\"") { quoted = true; continue; }
|
||||
if (ch == "{" || ch == "[") depth++;
|
||||
if (ch == "}" || ch == "]") depth--;
|
||||
if (depth == 1 && ch == ":" && colon < 0) colon = i;
|
||||
if ((depth == 1 && ch == ",") || (depth == 0 && ch == "}"))
|
||||
{
|
||||
if (colon < start)
|
||||
{
|
||||
string empty = text.Substring(start, i - start); empty.TrimInPlace();
|
||||
return members.Count() == 0 && empty.IsEmpty() && i == text.Length() - 1;
|
||||
}
|
||||
JsonLoadContext keyJson = new JsonLoadContext();
|
||||
string key;
|
||||
if (!keyJson.LoadFromString("{\"key\":" + text.Substring(start, colon - start) + "}") || !keyJson.ReadValue("key", key) || members.Contains(key)) return false;
|
||||
string value = text.Substring(colon + 1, i - colon - 1); value.TrimInPlace();
|
||||
members.Set(key, value); start = i + 1; colon = -1;
|
||||
}
|
||||
}
|
||||
return depth == 0 && !quoted;
|
||||
}
|
||||
static bool Document(string path, out map<string, string> members)
|
||||
{
|
||||
string text; members = new map<string, string>();
|
||||
if (!Text(path, text) || !Split(text, members)) return false;
|
||||
// Never downgrade or rewrite a configuration created by an unknown version.
|
||||
return members.Contains("configVersion") && members.Get("configVersion") == "1";
|
||||
}
|
||||
static bool Valid(string section, string text)
|
||||
{
|
||||
JsonLoadContext json = new JsonLoadContext();
|
||||
map<string, string> fields = new map<string, string>();
|
||||
if (!Split(text, fields) || !json.LoadFromString(text)) return false;
|
||||
map<string, int> numbers; map<string, string> roles; ResourceName scenario; array<string> records;
|
||||
if (section == "mission") return ERR_Settings.Parse(json, numbers);
|
||||
if (section == "mods") return ERR_ContentSettings.Parse(json, numbers);
|
||||
if (section == "factions") return ERR_FactionSelection.Parse(json, roles);
|
||||
if (section == "terrain") return ERR_TerrainPreference.Parse(json, scenario);
|
||||
if (section == "items") return ERR_ItemPreferences.Parse(json, records);
|
||||
string url;
|
||||
return section == "voice" && json.ReadValue("welcomeUrl", url) && (url.IsEmpty() || ERR_WelcomeVoiceRules.URL(url));
|
||||
}
|
||||
static string Defaults(string section)
|
||||
{
|
||||
if (section == "mods") return "{}";
|
||||
if (section == "factions") return "{\"escapists\":\"us\",\"enemy\":\"ussr\",\"independent\":\"fia\"}";
|
||||
if (section == "terrain") return "{\"scenario\":\"\"}";
|
||||
if (section == "items") return "{\"version\":1,\"records\":[\"active\"]}";
|
||||
if (section == "voice") return "{\"welcomeUrl\":\"\"}";
|
||||
JsonSaveContext json = new JsonSaveContext(); json.EnableTypeDiscriminator(false);
|
||||
foreach (string key : ERR_Settings.Keys())
|
||||
{
|
||||
int value = ERR_Settings.AddedDefault(key);
|
||||
if (key == "reportIntervalSeconds") value = 10;
|
||||
if (key == "supportSquadLimit") value = 4;
|
||||
if (key == "responseRadiusMetres") value = 2000;
|
||||
if (key == "aiIntelChancePercent") value = 60;
|
||||
if (key == "intelRevealChancePercent") value = 15;
|
||||
if (key == "radioDefenceSeconds") value = 180;
|
||||
json.WriteValue(key, value);
|
||||
}
|
||||
return json.SaveToString();
|
||||
}
|
||||
static string Encode(map<string, string> members)
|
||||
{
|
||||
string result = "{\n";
|
||||
int index;
|
||||
foreach (string key, string raw : members)
|
||||
{
|
||||
// Quote arbitrary root keys through the engine, including escaped characters.
|
||||
JsonSaveContext name = new JsonSaveContext(); name.EnableTypeDiscriminator(false); name.WriteValue("key", key);
|
||||
string pair = name.SaveToString(); int colon = pair.IndexOf(":");
|
||||
string quotedKey = pair.Substring(colon + 1, pair.Length() - colon - 2); quotedKey.TrimInPlace();
|
||||
if (index > 0) result += ",\n";
|
||||
result += " " + quotedKey + ": " + raw; index++;
|
||||
}
|
||||
return result + "\n}\n";
|
||||
}
|
||||
static bool Same(map<string, string> a, map<string, string> b)
|
||||
{
|
||||
if (!a || !b || a.Count() != b.Count()) return false;
|
||||
foreach (string key, string value : a) if (!b.Contains(key) || b.Get(key) != value) return false;
|
||||
return true;
|
||||
}
|
||||
static bool Commit(map<string, string> members)
|
||||
{
|
||||
if (!Replication.IsServer()) return false;
|
||||
FileHandle file = FileIO.OpenFile(PATH + ".tmp", FileMode.WRITE);
|
||||
if (!file) return false;
|
||||
file.Write(Encode(members)); file.Close();
|
||||
map<string, string> checked, previous;
|
||||
if (!Document(PATH + ".tmp", checked) || !Same(members, checked)) return false;
|
||||
bool hadPrevious = Document(PATH, previous);
|
||||
if (hadPrevious)
|
||||
{
|
||||
if (!FileIO.CopyFile(PATH, PATH + ".bak") || !Document(PATH + ".bak", checked) || !Same(previous, checked)) return false;
|
||||
}
|
||||
if (!FileIO.CopyFile(PATH + ".tmp", PATH) || !Document(PATH, checked) || !Same(members, checked))
|
||||
{
|
||||
if (FileIO.FileExists(PATH + ".bak")) FileIO.CopyFile(PATH + ".bak", PATH);
|
||||
else if (!hadPrevious) FileIO.DeleteFile(PATH);
|
||||
return false;
|
||||
}
|
||||
FileIO.DeleteFile(PATH + ".tmp");
|
||||
return true;
|
||||
}
|
||||
static bool Ensure()
|
||||
{
|
||||
if (!Replication.IsServer()) return false;
|
||||
// Existing unified files are authoritative; never reimport stale legacy data.
|
||||
if (FileIO.FileExists(PATH) || FileIO.FileExists(PATH + ".bak"))
|
||||
{
|
||||
string existing; map<string, string> root = new map<string, string>();
|
||||
if (Text(PATH, existing) && Split(existing, root) && (!root.Contains("configVersion") || root.Get("configVersion") != "1"))
|
||||
{
|
||||
Print("Reintroduced [config]: unsupported Escapists.json configVersion; file preserved, writes disabled", LogLevel.ERROR);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
map<string, string> members = new map<string, string>(); members.Set("configVersion", "1");
|
||||
foreach (string path : LegacyPaths())
|
||||
{
|
||||
string section = Section(path), raw;
|
||||
if (!Text(path, raw) || !Valid(section, raw))
|
||||
{
|
||||
if (!Text(path + ".bak", raw) || !Valid(section, raw))
|
||||
{
|
||||
if (FileIO.FileExists(path) || FileIO.FileExists(path + ".bak"))
|
||||
{
|
||||
Print("Reintroduced [config]: cannot import " + path + "; repair it or its backup. Existing files preserved.", LogLevel.ERROR);
|
||||
return false;
|
||||
}
|
||||
raw = Defaults(section);
|
||||
}
|
||||
}
|
||||
raw.TrimInPlace(); members.Set(section, raw);
|
||||
}
|
||||
if (!Commit(members)) return false;
|
||||
Print("Reintroduced [config]: using $profile:Escapists.json; legacy files retained but no longer used.");
|
||||
return true;
|
||||
}
|
||||
static bool Load(string path, JsonLoadContext json)
|
||||
{
|
||||
string section = Section(path); bool backup;
|
||||
if (section.IsEmpty() && path.EndsWith(".bak")) { section = Section(path.Substring(0, path.Length() - 4)); backup = true; }
|
||||
if (section.IsEmpty()) return json.LoadFromFile(path);
|
||||
if (!Ensure()) return false;
|
||||
string source = PATH; if (backup) source += ".bak";
|
||||
map<string, string> members;
|
||||
if (!Document(source, members)) return false;
|
||||
if (!members.Contains(section)) return json.LoadFromString(Defaults(section));
|
||||
return json.LoadFromString(members.Get(section));
|
||||
}
|
||||
static bool Exists(string path)
|
||||
{
|
||||
string section = Section(path);
|
||||
if (section.IsEmpty() && path.EndsWith(".bak")) section = Section(path.Substring(0, path.Length() - 4));
|
||||
if (section.IsEmpty()) return FileIO.FileExists(path);
|
||||
// A failed migration must make all owners read-only, not just the bad section.
|
||||
if (!Ensure()) return true;
|
||||
return FileIO.FileExists(PATH) || FileIO.FileExists(PATH + ".bak");
|
||||
}
|
||||
static bool Save(string path, JsonSaveContext json)
|
||||
{
|
||||
if (!Replication.IsServer() || !Ensure()) return false;
|
||||
string section = Section(path), raw = json.SaveToString(); raw.TrimInPlace();
|
||||
if (section.IsEmpty() || !Valid(section, raw)) return false;
|
||||
map<string, string> members;
|
||||
if (!Document(PATH, members) && !Document(PATH + ".bak", members)) return false;
|
||||
// Keep unrecognized fields within the edited section too (for returning mods
|
||||
// and newer optional settings). Explicitly written values replace old values.
|
||||
map<string, string> fields = new map<string, string>();
|
||||
map<string, string> changed = new map<string, string>();
|
||||
if (members.Contains(section) && !Split(members.Get(section), fields)) return false;
|
||||
if (!Split(raw, changed)) return false;
|
||||
foreach (string key, string value : changed) fields.Set(key, value);
|
||||
raw = Encode(fields); raw.TrimInPlace();
|
||||
members.Set(section, raw);
|
||||
return Commit(members);
|
||||
}
|
||||
}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
"""Execute the actual shared-file transaction with injected disk failures.
|
||||
Engine JSON/migration/menu checks are recorded separately in native evidence.
|
||||
"""
|
||||
from policy_harness import ROOT, body, run
|
||||
p = ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_ProfileConfig.c'
|
||||
method = body(p, 'static bool Commit(')
|
||||
for before, after in [
|
||||
('map<string, string>', 'Map'), ('FileHandle file', 'FileHandle* file'),
|
||||
('file.', 'file->'), ('FileIO.', 'FileIO::'), ('FileMode.', 'FileMode::'),
|
||||
('Replication.', 'Replication::')]:
|
||||
method = method.replace(before, after)
|
||||
run(r'''
|
||||
#include <cassert>
|
||||
#include <map>
|
||||
#include <string>
|
||||
using string=std::string;
|
||||
using Map=std::map<string,string>;
|
||||
const string PATH="Escapists.json";
|
||||
std::map<string,string> files;
|
||||
std::map<string,Map> documents;
|
||||
int fault=0,serial=0;
|
||||
namespace Replication {bool server=true;bool IsServer(){return server;}}
|
||||
namespace FileMode {int WRITE=1;}
|
||||
struct FileHandle {
|
||||
string path;
|
||||
void Write(string data){files[path]=fault==2?"CORRUPT":data;}
|
||||
void Close(){}
|
||||
};
|
||||
namespace FileIO {
|
||||
FileHandle* OpenFile(string path,int){static FileHandle h;h.path=path;return fault==1?nullptr:&h;}
|
||||
bool FileExists(string path){return files.count(path);}
|
||||
bool DeleteFile(string path){return files.erase(path);}
|
||||
bool CopyFile(string from,string to){
|
||||
if(!files.count(from))return false;
|
||||
if(to==PATH+".bak"&&fault==3)return false;
|
||||
files[to]=files[from];
|
||||
if(to==PATH+".bak"&&fault==4)files[to]="CORRUPT";
|
||||
if(from==PATH+".tmp"){
|
||||
if(fault==5){files[to]="PARTIAL";return false;}
|
||||
if(fault==6)files[to]="CORRUPT";
|
||||
if(fault==7){files[to]="WRONG";documents["WRONG"]={{"mission","wrong"}};}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
struct Store {
|
||||
static string Encode(Map values){string id="doc"+std::to_string(++serial);documents[id]=values;return id;}
|
||||
static bool Document(string path,Map& values){
|
||||
if(!files.count(path)||!documents.count(files[path]))return false;
|
||||
values=documents[files[path]];return true;
|
||||
}
|
||||
static bool Same(Map a,Map b){return a==b;}
|
||||
''' + method + r'''
|
||||
};
|
||||
int main(){
|
||||
Map old={{"mission","old"},{"items","presets"},{"voice","url"}}, next=old,read;
|
||||
next["mission"]="new";
|
||||
for(int injected:{1,2,5,6,7}){
|
||||
files.clear();fault=injected;
|
||||
assert(!Store::Commit(next)&&!files.count(PATH)); // failed first save stays absent
|
||||
}
|
||||
for(int injected=1;injected<=7;injected++){
|
||||
files.clear();fault=0;assert(Store::Commit(old));
|
||||
fault=injected;assert(!Store::Commit(next));
|
||||
assert(Store::Document(PATH,read)&&read==old); // current valid config remains
|
||||
fault=0;assert(Store::Commit(next));
|
||||
assert(Store::Document(PATH,read)&&read==next);
|
||||
}
|
||||
for(int injected:{1,2,5,6,7}){
|
||||
files.clear();files[PATH]="CORRUPT";files[PATH+".bak"]=Store::Encode(old);
|
||||
fault=injected;assert(!Store::Commit(next));
|
||||
assert(Store::Document(PATH+".bak",read)&&read==old); // only good backup not replaced
|
||||
fault=0;assert(Store::Commit(next));
|
||||
assert(Store::Document(PATH,read)&&read==next);
|
||||
}
|
||||
files.clear();fault=0;assert(Store::Commit(old));assert(Store::Commit(next));
|
||||
assert(Store::Document(PATH+".bak",read)&&read==old);
|
||||
assert(!files.count(PATH+".tmp"));
|
||||
Replication::server=false;assert(!Store::Commit(old));
|
||||
assert(Store::Document(PATH,read)&&read==next);
|
||||
}
|
||||
''')
|
||||
print('PASS: shared config transaction rejects client writes, preserves first-save/prior/fallback state across open, write, backup, partial-copy, readback and mismatch failures')
|
||||
@@ -0,0 +1,87 @@
|
||||
from pathlib import Path
|
||||
p=Path('/tmp/erri-config-review-1509/tests/test_profile_config.py');s=p.read_text().replace('from policy_harness import ROOT, body, run','import os\nfrom pathlib import Path\nfrom policy_harness import ROOT, body, run').replace("p = ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_ProfileConfig.c'","p = Path(os.environ.get('ERR_PROFILE_CONFIG_SOURCE', ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_ProfileConfig.c'))")
|
||||
# Existing transaction cases model well-formed sections; specialized validation is below.
|
||||
s=s.replace(' static string Encode(Map values)', ' static bool ContentsValid(Map){return true;}\n static string Encode(Map values)')
|
||||
s += r'''
|
||||
# Execute actual shared Save and Commit, with a small token document store.
|
||||
# JSON lexing and section parsers are explicit doubles: malformed terrain is a
|
||||
# valid JSON object rejected by the real TerrainPreference.Parse predicate.
|
||||
# No native filesystem atomicity or full JsonLoadContext implementation claim.
|
||||
def translate(method):
|
||||
for before, after in [
|
||||
('map<string, string>', 'Map'), ('new Map()', 'Map()'),
|
||||
('FileHandle file','FileHandle* file'), ('file.','file->'),
|
||||
('FileIO.','FileIO::'), ('FileMode.','FileMode::'), ('Replication.','Replication::'),
|
||||
('JsonSaveContext json','JsonSaveContext& json')]:
|
||||
method=method.replace(before,after)
|
||||
method=method.replace('foreach (string key, string value : changed)', 'for (auto [key,value] : changed)')
|
||||
method=method.replace('foreach (string path : LegacyPaths())', 'for (string path : LegacyPaths())')
|
||||
return method
|
||||
helper='static bool ContentsValid(Map) {return true;}'
|
||||
if 'static bool ContentsValid(' in p.read_text(): helper=translate(body(p,'static bool ContentsValid('))
|
||||
run(r"""
|
||||
#include <cassert>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
struct string:std::string{using std::string::string;string(std::string s):std::string(s){}bool IsEmpty(){return empty();}void TrimInPlace(){}};
|
||||
struct Map:std::map<string,string>{using std::map<string,string>::map;bool Contains(string key){return count(key);}string Get(string key){return at(key);}void Set(string key,string value){(*this)[key]=value;}};
|
||||
const string PATH="Escapists.json";
|
||||
std::map<string,string> files;
|
||||
std::map<string,Map> documents;
|
||||
int serial=0,copies=0;
|
||||
namespace Replication{bool server=true;bool IsServer(){return server;}}
|
||||
namespace FileMode{int WRITE=1;}
|
||||
struct FileHandle{string path;void Write(string data){files[path]=data;}void Close(){}};
|
||||
namespace FileIO{
|
||||
FileHandle* OpenFile(string path,int){static FileHandle h;h.path=path;return &h;}
|
||||
bool FileExists(string path){return files.count(path);}
|
||||
bool DeleteFile(string path){return files.erase(path);}
|
||||
bool CopyFile(string from,string to){if(!files.count(from))return false;copies++;files[to]=files[from];return true;}
|
||||
}
|
||||
struct JsonSaveContext{string token;string SaveToString(){return token;}};
|
||||
struct Store{
|
||||
static std::vector<string> LegacyPaths(){return {"mission","mods","factions","terrain","items","voice"};}
|
||||
static string Section(string path){return path;}
|
||||
static bool Ensure(){return true;}
|
||||
static string Encode(Map values){string id="doc"+std::to_string(++serial);documents[id]=values;return id;}
|
||||
static bool Split(string text,Map& values){if(!documents.count(text))return false;values=documents[text];return true;}
|
||||
static bool Valid(string section,string text){Map fields;if(!Split(text,fields))return false;return section!="terrain"||(fields.Contains("scenario")&&fields.Get("scenario")!="malformed");}
|
||||
static bool Document(string path,Map& values){return files.count(path)&&Split(files[path],values)&&values.Contains("configVersion")&&values.Get("configVersion")=="1";}
|
||||
static bool Same(Map a,Map b){return a==b;}
|
||||
""" + helper + translate(body(p,'static bool Commit(')) + translate(body(p,'static bool Save(')) + r"""
|
||||
};
|
||||
int main(){
|
||||
auto validTerrain=Store::Encode({{"scenario","valid-saved-terrain"},{"futureTerrainKey","keep"}});
|
||||
auto invalidTerrain=Store::Encode({{"scenario","malformed"},{"futureTerrainKey","keep"}});
|
||||
auto mission=Store::Encode({{"timer","10"},{"unknownMissionKey","keep"}});
|
||||
auto changedMission=Store::Encode({{"timer","20"}});
|
||||
Map good={{"configVersion","1"},{"mission",mission},{"terrain",validTerrain},{"unknownRoot","keep"}},current=good,read;
|
||||
current.Set("terrain",invalidTerrain);string originalGood=Store::Encode(good),originalBad=Store::Encode(current);
|
||||
files[PATH]=originalBad;files[PATH+".bak"]=originalGood;
|
||||
// Owner would reject current terrain and accept backup. An unrelated save must
|
||||
// not destroy the only recovery document or report success with invalid data.
|
||||
assert(!Store::Valid("terrain",current.Get("terrain"))&&Store::Valid("terrain",good.Get("terrain")));
|
||||
JsonSaveContext change{changedMission};
|
||||
assert(!Store::Save("mission",change));
|
||||
assert(files[PATH]==originalBad&&files[PATH+".bak"]==originalGood&&copies==0);
|
||||
// Repair the section through its recovered menu value. Preserve the only good
|
||||
// backup; merge unknown fields and allow subsequent ordinary menu persistence.
|
||||
JsonSaveContext repair{validTerrain};assert(Store::Save("terrain",repair));
|
||||
assert(files[PATH+".bak"]==originalGood&&Store::Document(PATH,read));
|
||||
assert(read.Get("unknownRoot")=="keep");Map fields;assert(Store::Split(read.Get("terrain"),fields)&&fields.Get("futureTerrainKey")=="keep");
|
||||
string repaired=files[PATH];assert(Store::Save("mission",change));assert(files[PATH+".bak"]==repaired);
|
||||
assert(Store::Document(PATH,read)&&Store::Split(read.Get("mission"),fields));assert(fields.Get("timer")=="20"&&fields.Get("unknownMissionKey")=="keep");
|
||||
// Missing optional sections continue to use their owner defaults; unknown roots
|
||||
// are not subject to this version's validators.
|
||||
Map sparse={{"configVersion","1"},{"unrecognized","opaque"}};assert(Store::Commit(sparse));
|
||||
// Existing defaults and each known section are checked; no invalid first write.
|
||||
files.clear();copies=0;assert(!Store::Commit(current)&&files.empty()&&copies==0);
|
||||
// Updating an already healthy document retains ordinary last-valid backup.
|
||||
files[PATH]=originalGood;assert(Store::Save("mission",change));assert(files[PATH+".bak"]==originalGood);
|
||||
}
|
||||
""")
|
||||
print('PASS: actual Save/Commit preserves semantically valid backup across unrelated menu edits and repairs; unknown fields/default sections retained; parsers and disk doubled')
|
||||
'''
|
||||
p.write_text(s)
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"trigger": "Primary unified document has valid JSON/configVersion but malformed recognized terrain scenario, while .bak contains the last valid selection. Terrain owner accepts the backup; an ordinary mission menu change calls ProfileConfig.Save.",
|
||||
"before": "Save edits only mission; Commit accepts version-only Document(primary) and overwrites good backup with malformed primary. Terrain selection becomes unrecoverable on next load.",
|
||||
"after": "ContentsValid checks all present known sections before any temporary-file write. Unrelated edits return existing Save failure without touching files. Repairing the damaged section succeeds while prior invalid primary is not copied over the good backup. Unknown keys and missing/default sections are retained.",
|
||||
"scope": "Only ProfileConfig.c and existing test_profile_config.py. Document/Load fallback semantics and custom file owners unchanged.",
|
||||
"tests": "Actual Save, Commit, new ContentsValid and unchanged actual TerrainPreference.Parse executed. Existing disk-fault matrix retained. Baseline compiles/runtime fails, proposal passes, removing previous-document validation compiles/runtime fails. JSON codec, disk, catalog and non-terrain validators explicitly doubled; native not qualified.",
|
||||
"menu_failure": "ERR_Settings.Set returns false immediately when ProfileConfig.Save refuses; other owners similarly propagate false. No success response introduced.",
|
||||
"limits": [
|
||||
"An unrelated save is refused until the damaged recognized section is repaired; no automatic merge from backup or default overwrite.",
|
||||
"Unknown future root keys remain preserved without semantic validation.",
|
||||
"build-test.py is historical scratch construction, not an authoritative generator."
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
--- a/addons/core/Scripts/Game/ERR/00_Core/ERR_ProfileConfig.c
|
||||
+++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_ProfileConfig.c
|
||||
@@ -131,15 +131,26 @@
|
||||
foreach (string key, string value : a) if (!b.Contains(key) || b.Get(key) != value) return false;
|
||||
return true;
|
||||
}
|
||||
+ // A section may have loaded from the backup while the primary remains valid
|
||||
+ // JSON. Never promote that damaged document or overwrite its recovery copy.
|
||||
+ static bool ContentsValid(map<string, string> members)
|
||||
+ {
|
||||
+ foreach (string path : LegacyPaths())
|
||||
+ {
|
||||
+ string section = Section(path);
|
||||
+ if (members.Contains(section) && !Valid(section, members.Get(section))) return false;
|
||||
+ }
|
||||
+ return true;
|
||||
+ }
|
||||
static bool Commit(map<string, string> members)
|
||||
{
|
||||
- if (!Replication.IsServer()) return false;
|
||||
+ if (!Replication.IsServer() || !ContentsValid(members)) return false;
|
||||
FileHandle file = FileIO.OpenFile(PATH + ".tmp", FileMode.WRITE);
|
||||
if (!file) return false;
|
||||
file.Write(Encode(members)); file.Close();
|
||||
map<string, string> checked, previous;
|
||||
if (!Document(PATH + ".tmp", checked) || !Same(members, checked)) return false;
|
||||
- bool hadPrevious = Document(PATH, previous);
|
||||
+ bool hadPrevious = Document(PATH, previous) && ContentsValid(previous);
|
||||
if (hadPrevious)
|
||||
{
|
||||
if (!FileIO.CopyFile(PATH, PATH + ".bak") || !Document(PATH + ".bak", checked) || !Same(previous, checked)) return false;
|
||||
--- a/tests/test_profile_config.py
|
||||
+++ b/tests/test_profile_config.py
|
||||
@@ -1,8 +1,10 @@
|
||||
"""Execute the actual shared-file transaction with injected disk failures.
|
||||
Engine JSON/migration/menu checks are recorded separately in native evidence.
|
||||
"""
|
||||
+import os
|
||||
+from pathlib import Path
|
||||
from policy_harness import ROOT, body, run
|
||||
-p = ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_ProfileConfig.c'
|
||||
+p = Path(os.environ.get('ERR_PROFILE_CONFIG_SOURCE', ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_ProfileConfig.c'))
|
||||
method = body(p, 'static bool Commit(')
|
||||
for before, after in [
|
||||
('map<string, string>', 'Map'), ('FileHandle file', 'FileHandle* file'),
|
||||
@@ -44,6 +46,7 @@
|
||||
}
|
||||
}
|
||||
struct Store {
|
||||
+ static bool ContentsValid(Map){return true;}
|
||||
static string Encode(Map values){string id="doc"+std::to_string(++serial);documents[id]=values;return id;}
|
||||
static bool Document(string path,Map& values){
|
||||
if(!files.count(path)||!documents.count(files[path]))return false;
|
||||
@@ -81,3 +84,90 @@
|
||||
}
|
||||
''')
|
||||
print('PASS: shared config transaction rejects client writes, preserves first-save/prior/fallback state across open, write, backup, partial-copy, readback and mismatch failures')
|
||||
+
|
||||
+# Execute actual shared Save and Commit, with a small token document store.
|
||||
+# JSON lexing and non-terrain section parsers are explicit doubles. The terrain
|
||||
+# rejection runs the actual TerrainPreference.Parse method with a catalog double.
|
||||
+# No native filesystem atomicity or full JsonLoadContext implementation claim.
|
||||
+def translate(method):
|
||||
+ for before, after in [
|
||||
+ ('map<string, string>', 'Map'), ('new Map()', 'Map()'),
|
||||
+ ('FileHandle file','FileHandle* file'), ('file.','file->'),
|
||||
+ ('FileIO.','FileIO::'), ('FileMode.','FileMode::'), ('Replication.','Replication::'),
|
||||
+ ('JsonSaveContext json','JsonSaveContext& json')]:
|
||||
+ method=method.replace(before,after)
|
||||
+ method=method.replace('foreach (string key, string value : changed)', 'for (auto [key,value] : changed)')
|
||||
+ method=method.replace('foreach (string path : LegacyPaths())', 'for (string path : LegacyPaths())')
|
||||
+ return method
|
||||
+helper='static bool ContentsValid(Map) {return true;}'
|
||||
+if 'static bool ContentsValid(' in p.read_text(): helper=translate(body(p,'static bool ContentsValid('))
|
||||
+terrain = body(ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainPreference.c', 'static bool Parse(').replace('JsonLoadContext json', 'JsonLoadContext& json').replace('out ResourceName scenario', 'string& scenario').replace('ERR_TerrainCatalog.', 'ERR_TerrainCatalog::')
|
||||
+run(r"""
|
||||
+#include <cassert>
|
||||
+#include <map>
|
||||
+#include <string>
|
||||
+#include <vector>
|
||||
+#include <algorithm>
|
||||
+struct string:std::string{using std::string::string;string(std::string s):std::string(s){}bool IsEmpty(){return empty();}int Length(){return size();}void TrimInPlace(){}};
|
||||
+struct Map:std::map<string,string>{using std::map<string,string>::map;bool Contains(string key){return count(key);}string Get(string key){return at(key);}void Set(string key,string value){(*this)[key]=value;}};
|
||||
+const string PATH="Escapists.json";
|
||||
+std::map<string,string> files;
|
||||
+std::map<string,Map> documents;
|
||||
+int serial=0,copies=0,writes=0;
|
||||
+namespace Replication{bool server=true;bool IsServer(){return server;}}
|
||||
+namespace FileMode{int WRITE=1;}
|
||||
+struct FileHandle{string path;void Write(string data){writes++;files[path]=data;}void Close(){}};
|
||||
+namespace FileIO{
|
||||
+ FileHandle* OpenFile(string path,int){static FileHandle h;h.path=path;return &h;}
|
||||
+ bool FileExists(string path){return files.count(path);}
|
||||
+ bool DeleteFile(string path){return files.erase(path);}
|
||||
+ bool CopyFile(string from,string to){if(!files.count(from))return false;copies++;files[to]=files[from];return true;}
|
||||
+}
|
||||
+struct JsonSaveContext{string token;string SaveToString(){return token;}};
|
||||
+struct JsonLoadContext{Map fields;bool ReadValue(string key,string&value){if(!fields.Contains(key))return false;value=fields.Get(key);return true;}};
|
||||
+namespace ERR_TerrainCatalog{string Key(string scenario){return scenario=="valid-saved-terrain"?"known":"";}}
|
||||
+struct Terrain{
|
||||
+""" + terrain + r"""
|
||||
+};
|
||||
+struct Store{
|
||||
+ static std::vector<string> LegacyPaths(){return {"mission","mods","factions","terrain","items","voice"};}
|
||||
+ static string Section(string path){return path;}
|
||||
+ static bool Ensure(){return true;}
|
||||
+ static string Encode(Map values){string id="doc"+std::to_string(++serial);documents[id]=values;return id;}
|
||||
+ static bool Split(string text,Map& values){if(!documents.count(text))return false;values=documents[text];return true;}
|
||||
+ static bool Valid(string section,string text){Map fields;if(!Split(text,fields))return false;if(section!="terrain")return true;JsonLoadContext json{fields};string scenario;return Terrain::Parse(json,scenario);}
|
||||
+ static bool Document(string path,Map& values){return files.count(path)&&Split(files[path],values)&&values.Contains("configVersion")&&values.Get("configVersion")=="1";}
|
||||
+ static bool Same(Map a,Map b){return a==b;}
|
||||
+""" + helper + translate(body(p,'static bool Commit(')) + translate(body(p,'static bool Save(')) + r"""
|
||||
+};
|
||||
+int main(){
|
||||
+ auto validTerrain=Store::Encode({{"scenario","valid-saved-terrain"},{"futureTerrainKey","keep"}});
|
||||
+ auto invalidTerrain=Store::Encode({{"scenario","malformed"},{"futureTerrainKey","keep"}});
|
||||
+ auto mission=Store::Encode({{"timer","10"},{"unknownMissionKey","keep"}});
|
||||
+ auto changedMission=Store::Encode({{"timer","20"}});
|
||||
+ Map good={{"configVersion","1"},{"mission",mission},{"terrain",validTerrain},{"unknownRoot","keep"}},current=good,read;
|
||||
+ current.Set("terrain",invalidTerrain);string originalGood=Store::Encode(good),originalBad=Store::Encode(current);
|
||||
+ files[PATH]=originalBad;files[PATH+".bak"]=originalGood;
|
||||
+ // Owner would reject current terrain and accept backup. An unrelated save must
|
||||
+ // not destroy the only recovery document or report success with invalid data.
|
||||
+ assert(!Store::Valid("terrain",current.Get("terrain"))&&Store::Valid("terrain",good.Get("terrain")));
|
||||
+ JsonSaveContext change{changedMission};
|
||||
+ assert(!Store::Save("mission",change));
|
||||
+ assert(files[PATH]==originalBad&&files[PATH+".bak"]==originalGood&&copies==0&&writes==0&&files.size()==2);
|
||||
+ // Repair the section through its recovered menu value. Preserve the only good
|
||||
+ // backup; merge unknown fields and allow subsequent ordinary menu persistence.
|
||||
+ JsonSaveContext repair{validTerrain};assert(Store::Save("terrain",repair));
|
||||
+ assert(files[PATH+".bak"]==originalGood&&Store::Document(PATH,read));
|
||||
+ assert(read.Get("unknownRoot")=="keep");Map fields;assert(Store::Split(read.Get("terrain"),fields)&&fields.Get("futureTerrainKey")=="keep");
|
||||
+ string repaired=files[PATH];assert(Store::Save("mission",change));assert(files[PATH+".bak"]==repaired);
|
||||
+ assert(Store::Document(PATH,read)&&Store::Split(read.Get("mission"),fields));assert(fields.Get("timer")=="20"&&fields.Get("unknownMissionKey")=="keep");
|
||||
+ // Missing optional sections continue to use their owner defaults; unknown roots
|
||||
+ // are not subject to this version's validators.
|
||||
+ Map sparse={{"configVersion","1"},{"unrecognized","opaque"}};assert(Store::Commit(sparse));
|
||||
+ // Existing defaults and each known section are checked; no invalid first write.
|
||||
+ files.clear();copies=0;writes=0;assert(!Store::Commit(current)&&files.empty()&&copies==0&&writes==0);
|
||||
+ // Updating an already healthy document retains ordinary last-valid backup.
|
||||
+ files[PATH]=originalGood;assert(Store::Save("mission",change));assert(files[PATH+".bak"]==originalGood);
|
||||
+}
|
||||
+""")
|
||||
+print('PASS: actual Save/Commit preserves semantically valid backup across unrelated menu edits and repairs; unknown fields/default sections retained; actual terrain parser; other parsers, catalog and disk doubled')
|
||||
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"complete": true,
|
||||
"approved": true,
|
||||
"reviewer": "player_admission_review",
|
||||
"files": {
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ProfileConfig.c": {
|
||||
"baseline_sha256": "ac28363fd5861523db278bb18aa5499f356fef69d35435d1f4ef547da704b67d",
|
||||
"proposal_sha256": "9df8ccf45fc2ed12f4b14d08270878696e8785760a3ae51fe032b6f3818fc0e6",
|
||||
"index_sha256": null,
|
||||
"index_absent": true
|
||||
},
|
||||
"tests/test_profile_config.py": {
|
||||
"baseline_sha256": "088ea06a32a59711d8e02c426d5fdd4a14657cded725b831af312bd8eb5f133f",
|
||||
"proposal_sha256": "727dc330db23d744fca0c965474f834d0cb70432e58938f286fde28bd8415435",
|
||||
"index_sha256": null,
|
||||
"index_absent": true
|
||||
}
|
||||
},
|
||||
"patch_sha256": "9ddefab1f87ef5d0924e096d51359482e43de9b250c7986c98360c97d432104d",
|
||||
"source_manifest_sha256": "2fd845ee6bd744e8c405f7e9dc40562df2a82cb2ff215cf0df7db481b85e735f",
|
||||
"findings": [
|
||||
"Exact production delta is one present-section validator plus Commit pre-write guard and valid-previous-only backup promotion. No Document/Load/schema/default policy changes.",
|
||||
"Recognized sections invoke existing owner parsers; missing sections and unknown root/section members are retained. Successful candidate validation plus exact readback Same check prevents semantically invalid candidate promotion.",
|
||||
"Unrelated save cannot replace sole good backup with malformed recognized primary. Explicit section repair succeeds without overwriting good backup, then normal healthy saves retain last valid document.",
|
||||
"Existing first-save, client-write, backup-copy, partial-copy and readback fault assertions remain in the first harness. Added harness executes actual Save/Commit/ContentsValid and actual terrain parser; engine JSON, remaining parsers/catalog and disk are explicitly doubled.",
|
||||
"Baseline compiled runtime failure at unrelated Save acceptance and proposal green were inspected from owner logs; omission of previous-content validation fails repair-backup assertion."
|
||||
],
|
||||
"limits": [
|
||||
"Independent source/test/log review only; no compiler or native run by reviewer.",
|
||||
"No native JSON/filesystem or real profile mutation qualification inferred.",
|
||||
"Malformed untouched section intentionally blocks unrelated saves until that section is repaired; safe refusal is deliberate."
|
||||
],
|
||||
"logs": {
|
||||
"apply-check.log": {
|
||||
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
"tail": ""
|
||||
},
|
||||
"previous-validation-red.log": {
|
||||
"sha256": "0f8438d6a2ad9c46e8372fc1ad3f4e2c01d07179c3bc19d1279de1066ae42ae9",
|
||||
"tail": "^^^^^^^^^^^^^^^^^^^\n File \"/usr/lib/python3.14/subprocess.py\", line 578, in run\n raise CalledProcessError(retcode, process.args,\n output=stdout, stderr=stderr)\nsubprocess.CalledProcessError: Command '['/tmp/err-policy-ri3j68jc/check']' died with <Signals.SIGABRT: 6>.\n"
|
||||
},
|
||||
"proposal-green.log": {
|
||||
"sha256": "1c414380eb465210146fed3d49b2108f593abd625b6ffb92f50e7f27131de6f0",
|
||||
"tail": "rior/fallback state across open, write, backup, partial-copy, readback and mismatch failures\nPASS: actual Save/Commit preserves semantically valid backup across unrelated menu edits and repairs; unknown fields/default sections retained; actual terrain parser; other parsers, catalog and disk doubled\n"
|
||||
},
|
||||
"baseline-red.log": {
|
||||
"sha256": "a51853e6c0004c0c17b932fb4b2d201d7618648fe1ba6f802c31011228f3c404",
|
||||
"tail": "^^^^^^^^^^^^^^^^^^^\n File \"/usr/lib/python3.14/subprocess.py\", line 578, in run\n raise CalledProcessError(retcode, process.args,\n output=stdout, stderr=stderr)\nsubprocess.CalledProcessError: Command '['/tmp/err-policy-r3sh7kea/check']' died with <Signals.SIGABRT: 6>.\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
check: /tmp/err-policy-ri3j68jc/check.cpp:106: int main(): Assertion `files[PATH+".bak"]==originalGood&&Store::Document(PATH,read)' failed.
|
||||
PASS: shared config transaction rejects client writes, preserves first-save/prior/fallback state across open, write, backup, partial-copy, readback and mismatch failures
|
||||
Traceback (most recent call last):
|
||||
File "/tmp/erri-config-review-1509/tests/test_profile_config.py", line 105, in <module>
|
||||
run(r"""
|
||||
~~~^^^^^
|
||||
#include <cassert>
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
...<64 lines>...
|
||||
}
|
||||
^
|
||||
""")
|
||||
^^^^
|
||||
File "/home/jakub/devel/escapistsrereintroduced/tests/policy_harness.py", line 14, in run
|
||||
subprocess.run([str(p/'check')],check=True)
|
||||
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/usr/lib/python3.14/subprocess.py", line 578, in run
|
||||
raise CalledProcessError(retcode, process.args,
|
||||
output=stdout, stderr=stderr)
|
||||
subprocess.CalledProcessError: Command '['/tmp/err-policy-ri3j68jc/check']' died with <Signals.SIGABRT: 6>.
|
||||
@@ -0,0 +1,2 @@
|
||||
PASS: shared config transaction rejects client writes, preserves first-save/prior/fallback state across open, write, backup, partial-copy, readback and mismatch failures
|
||||
PASS: actual Save/Commit preserves semantically valid backup across unrelated menu edits and repairs; unknown fields/default sections retained; actual terrain parser; other parsers, catalog and disk doubled
|
||||
+242
@@ -0,0 +1,242 @@
|
||||
// One operator-owned document. Legacy names identify sections internally only;
|
||||
// custom paths used by isolated probes keep their original standalone behavior.
|
||||
class ERR_ProfileConfig
|
||||
{
|
||||
static const string PATH = "$profile:Escapists.json";
|
||||
static const string VOICE = "$profile:EscapistsWelcomeVoice.json";
|
||||
static array<string> LegacyPaths()
|
||||
{
|
||||
return {ERR_Settings.PATH, ERR_ContentSettings.PATH, ERR_FactionSelection.PATH, ERR_TerrainPreference.PATH, ERR_ItemPreferences.PATH, VOICE};
|
||||
}
|
||||
static string Section(string path)
|
||||
{
|
||||
if (path == ERR_Settings.PATH) return "mission";
|
||||
if (path == ERR_ContentSettings.PATH) return "mods";
|
||||
if (path == ERR_FactionSelection.PATH) return "factions";
|
||||
if (path == ERR_TerrainPreference.PATH) return "terrain";
|
||||
if (path == ERR_ItemPreferences.PATH) return "items";
|
||||
if (path == VOICE) return "voice";
|
||||
return "";
|
||||
}
|
||||
static bool Text(string path, out string text)
|
||||
{
|
||||
FileHandle file = FileIO.OpenFile(path, FileMode.READ);
|
||||
if (!file) return false;
|
||||
int length = file.GetLength();
|
||||
if (length < 2 || length > 8388608) { file.Close(); return false; }
|
||||
file.Read(text, length); file.Close();
|
||||
return text.Length() == length;
|
||||
}
|
||||
// The engine validates JSON syntax. This scan only separates root members,
|
||||
// retaining unknown fields and dormant addon entries without reinterpreting them.
|
||||
static bool Split(string text, map<string, string> members)
|
||||
{
|
||||
members.Clear(); text.TrimInPlace();
|
||||
JsonLoadContext valid = new JsonLoadContext();
|
||||
if (text.Length() < 2 || text.Substring(0, 1) != "{" || !valid.LoadFromString(text)) return false;
|
||||
int depth, start = 1, colon = -1;
|
||||
bool quoted, escaped;
|
||||
string block;
|
||||
for (int i = 0; i < text.Length(); i++)
|
||||
{
|
||||
if (i % 1024 == 0) block = text.Substring(i, Math.Min(1024, text.Length() - i));
|
||||
string ch = block.Substring(i % 1024, 1);
|
||||
if (quoted)
|
||||
{
|
||||
if (escaped) escaped = false;
|
||||
else if (ch == "\\") escaped = true;
|
||||
else if (ch == "\"") quoted = false;
|
||||
continue;
|
||||
}
|
||||
if (ch == "\"") { quoted = true; continue; }
|
||||
if (ch == "{" || ch == "[") depth++;
|
||||
if (ch == "}" || ch == "]") depth--;
|
||||
if (depth == 1 && ch == ":" && colon < 0) colon = i;
|
||||
if ((depth == 1 && ch == ",") || (depth == 0 && ch == "}"))
|
||||
{
|
||||
if (colon < start)
|
||||
{
|
||||
string empty = text.Substring(start, i - start); empty.TrimInPlace();
|
||||
return members.Count() == 0 && empty.IsEmpty() && i == text.Length() - 1;
|
||||
}
|
||||
JsonLoadContext keyJson = new JsonLoadContext();
|
||||
string key;
|
||||
if (!keyJson.LoadFromString("{\"key\":" + text.Substring(start, colon - start) + "}") || !keyJson.ReadValue("key", key) || members.Contains(key)) return false;
|
||||
string value = text.Substring(colon + 1, i - colon - 1); value.TrimInPlace();
|
||||
members.Set(key, value); start = i + 1; colon = -1;
|
||||
}
|
||||
}
|
||||
return depth == 0 && !quoted;
|
||||
}
|
||||
static bool Document(string path, out map<string, string> members)
|
||||
{
|
||||
string text; members = new map<string, string>();
|
||||
if (!Text(path, text) || !Split(text, members)) return false;
|
||||
// Never downgrade or rewrite a configuration created by an unknown version.
|
||||
return members.Contains("configVersion") && members.Get("configVersion") == "1";
|
||||
}
|
||||
static bool Valid(string section, string text)
|
||||
{
|
||||
JsonLoadContext json = new JsonLoadContext();
|
||||
map<string, string> fields = new map<string, string>();
|
||||
if (!Split(text, fields) || !json.LoadFromString(text)) return false;
|
||||
map<string, int> numbers; map<string, string> roles; ResourceName scenario; array<string> records;
|
||||
if (section == "mission") return ERR_Settings.Parse(json, numbers);
|
||||
if (section == "mods") return ERR_ContentSettings.Parse(json, numbers);
|
||||
if (section == "factions") return ERR_FactionSelection.Parse(json, roles);
|
||||
if (section == "terrain") return ERR_TerrainPreference.Parse(json, scenario);
|
||||
if (section == "items") return ERR_ItemPreferences.Parse(json, records);
|
||||
string url;
|
||||
return section == "voice" && json.ReadValue("welcomeUrl", url) && (url.IsEmpty() || ERR_WelcomeVoiceRules.URL(url));
|
||||
}
|
||||
static string Defaults(string section)
|
||||
{
|
||||
if (section == "mods") return "{}";
|
||||
if (section == "factions") return "{\"escapists\":\"us\",\"enemy\":\"ussr\",\"independent\":\"fia\"}";
|
||||
if (section == "terrain") return "{\"scenario\":\"\"}";
|
||||
if (section == "items") return "{\"version\":1,\"records\":[\"active\"]}";
|
||||
if (section == "voice") return "{\"welcomeUrl\":\"\"}";
|
||||
JsonSaveContext json = new JsonSaveContext(); json.EnableTypeDiscriminator(false);
|
||||
foreach (string key : ERR_Settings.Keys())
|
||||
{
|
||||
int value = ERR_Settings.AddedDefault(key);
|
||||
if (key == "reportIntervalSeconds") value = 10;
|
||||
if (key == "supportSquadLimit") value = 4;
|
||||
if (key == "responseRadiusMetres") value = 2000;
|
||||
if (key == "aiIntelChancePercent") value = 60;
|
||||
if (key == "intelRevealChancePercent") value = 15;
|
||||
if (key == "radioDefenceSeconds") value = 180;
|
||||
json.WriteValue(key, value);
|
||||
}
|
||||
return json.SaveToString();
|
||||
}
|
||||
static string Encode(map<string, string> members)
|
||||
{
|
||||
string result = "{\n";
|
||||
int index;
|
||||
foreach (string key, string raw : members)
|
||||
{
|
||||
// Quote arbitrary root keys through the engine, including escaped characters.
|
||||
JsonSaveContext name = new JsonSaveContext(); name.EnableTypeDiscriminator(false); name.WriteValue("key", key);
|
||||
string pair = name.SaveToString(); int colon = pair.IndexOf(":");
|
||||
string quotedKey = pair.Substring(colon + 1, pair.Length() - colon - 2); quotedKey.TrimInPlace();
|
||||
if (index > 0) result += ",\n";
|
||||
result += " " + quotedKey + ": " + raw; index++;
|
||||
}
|
||||
return result + "\n}\n";
|
||||
}
|
||||
static bool Same(map<string, string> a, map<string, string> b)
|
||||
{
|
||||
if (!a || !b || a.Count() != b.Count()) return false;
|
||||
foreach (string key, string value : a) if (!b.Contains(key) || b.Get(key) != value) return false;
|
||||
return true;
|
||||
}
|
||||
// A section may have loaded from the backup while the primary remains valid
|
||||
// JSON. Never promote that damaged document or overwrite its recovery copy.
|
||||
static bool ContentsValid(map<string, string> members)
|
||||
{
|
||||
foreach (string path : LegacyPaths())
|
||||
{
|
||||
string section = Section(path);
|
||||
if (members.Contains(section) && !Valid(section, members.Get(section))) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
static bool Commit(map<string, string> members)
|
||||
{
|
||||
if (!Replication.IsServer() || !ContentsValid(members)) return false;
|
||||
FileHandle file = FileIO.OpenFile(PATH + ".tmp", FileMode.WRITE);
|
||||
if (!file) return false;
|
||||
file.Write(Encode(members)); file.Close();
|
||||
map<string, string> checked, previous;
|
||||
if (!Document(PATH + ".tmp", checked) || !Same(members, checked)) return false;
|
||||
bool hadPrevious = Document(PATH, previous) && ContentsValid(previous);
|
||||
if (hadPrevious)
|
||||
{
|
||||
if (!FileIO.CopyFile(PATH, PATH + ".bak") || !Document(PATH + ".bak", checked) || !Same(previous, checked)) return false;
|
||||
}
|
||||
if (!FileIO.CopyFile(PATH + ".tmp", PATH) || !Document(PATH, checked) || !Same(members, checked))
|
||||
{
|
||||
if (FileIO.FileExists(PATH + ".bak")) FileIO.CopyFile(PATH + ".bak", PATH);
|
||||
else if (!hadPrevious) FileIO.DeleteFile(PATH);
|
||||
return false;
|
||||
}
|
||||
FileIO.DeleteFile(PATH + ".tmp");
|
||||
return true;
|
||||
}
|
||||
static bool Ensure()
|
||||
{
|
||||
if (!Replication.IsServer()) return false;
|
||||
// Existing unified files are authoritative; never reimport stale legacy data.
|
||||
if (FileIO.FileExists(PATH) || FileIO.FileExists(PATH + ".bak"))
|
||||
{
|
||||
string existing; map<string, string> root = new map<string, string>();
|
||||
if (Text(PATH, existing) && Split(existing, root) && (!root.Contains("configVersion") || root.Get("configVersion") != "1"))
|
||||
{
|
||||
Print("Reintroduced [config]: unsupported Escapists.json configVersion; file preserved, writes disabled", LogLevel.ERROR);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
map<string, string> members = new map<string, string>(); members.Set("configVersion", "1");
|
||||
foreach (string path : LegacyPaths())
|
||||
{
|
||||
string section = Section(path), raw;
|
||||
if (!Text(path, raw) || !Valid(section, raw))
|
||||
{
|
||||
if (!Text(path + ".bak", raw) || !Valid(section, raw))
|
||||
{
|
||||
if (FileIO.FileExists(path) || FileIO.FileExists(path + ".bak"))
|
||||
{
|
||||
Print("Reintroduced [config]: cannot import " + path + "; repair it or its backup. Existing files preserved.", LogLevel.ERROR);
|
||||
return false;
|
||||
}
|
||||
raw = Defaults(section);
|
||||
}
|
||||
}
|
||||
raw.TrimInPlace(); members.Set(section, raw);
|
||||
}
|
||||
if (!Commit(members)) return false;
|
||||
Print("Reintroduced [config]: using $profile:Escapists.json; legacy files retained but no longer used.");
|
||||
return true;
|
||||
}
|
||||
static bool Load(string path, JsonLoadContext json)
|
||||
{
|
||||
string section = Section(path); bool backup;
|
||||
if (section.IsEmpty() && path.EndsWith(".bak")) { section = Section(path.Substring(0, path.Length() - 4)); backup = true; }
|
||||
if (section.IsEmpty()) return json.LoadFromFile(path);
|
||||
if (!Ensure()) return false;
|
||||
string source = PATH; if (backup) source += ".bak";
|
||||
map<string, string> members;
|
||||
if (!Document(source, members)) return false;
|
||||
if (!members.Contains(section)) return json.LoadFromString(Defaults(section));
|
||||
return json.LoadFromString(members.Get(section));
|
||||
}
|
||||
static bool Exists(string path)
|
||||
{
|
||||
string section = Section(path);
|
||||
if (section.IsEmpty() && path.EndsWith(".bak")) section = Section(path.Substring(0, path.Length() - 4));
|
||||
if (section.IsEmpty()) return FileIO.FileExists(path);
|
||||
// A failed migration must make all owners read-only, not just the bad section.
|
||||
if (!Ensure()) return true;
|
||||
return FileIO.FileExists(PATH) || FileIO.FileExists(PATH + ".bak");
|
||||
}
|
||||
static bool Save(string path, JsonSaveContext json)
|
||||
{
|
||||
if (!Replication.IsServer() || !Ensure()) return false;
|
||||
string section = Section(path), raw = json.SaveToString(); raw.TrimInPlace();
|
||||
if (section.IsEmpty() || !Valid(section, raw)) return false;
|
||||
map<string, string> members;
|
||||
if (!Document(PATH, members) && !Document(PATH + ".bak", members)) return false;
|
||||
// Keep unrecognized fields within the edited section too (for returning mods
|
||||
// and newer optional settings). Explicitly written values replace old values.
|
||||
map<string, string> fields = new map<string, string>();
|
||||
map<string, string> changed = new map<string, string>();
|
||||
if (members.Contains(section) && !Split(members.Get(section), fields)) return false;
|
||||
if (!Split(raw, changed)) return false;
|
||||
foreach (string key, string value : changed) fields.Set(key, value);
|
||||
raw = Encode(fields); raw.TrimInPlace();
|
||||
members.Set(section, raw);
|
||||
return Commit(members);
|
||||
}
|
||||
}
|
||||
+173
@@ -0,0 +1,173 @@
|
||||
"""Execute the actual shared-file transaction with injected disk failures.
|
||||
Engine JSON/migration/menu checks are recorded separately in native evidence.
|
||||
"""
|
||||
import os
|
||||
from pathlib import Path
|
||||
from policy_harness import ROOT, body, run
|
||||
p = Path(os.environ.get('ERR_PROFILE_CONFIG_SOURCE', ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_ProfileConfig.c'))
|
||||
method = body(p, 'static bool Commit(')
|
||||
for before, after in [
|
||||
('map<string, string>', 'Map'), ('FileHandle file', 'FileHandle* file'),
|
||||
('file.', 'file->'), ('FileIO.', 'FileIO::'), ('FileMode.', 'FileMode::'),
|
||||
('Replication.', 'Replication::')]:
|
||||
method = method.replace(before, after)
|
||||
run(r'''
|
||||
#include <cassert>
|
||||
#include <map>
|
||||
#include <string>
|
||||
using string=std::string;
|
||||
using Map=std::map<string,string>;
|
||||
const string PATH="Escapists.json";
|
||||
std::map<string,string> files;
|
||||
std::map<string,Map> documents;
|
||||
int fault=0,serial=0;
|
||||
namespace Replication {bool server=true;bool IsServer(){return server;}}
|
||||
namespace FileMode {int WRITE=1;}
|
||||
struct FileHandle {
|
||||
string path;
|
||||
void Write(string data){files[path]=fault==2?"CORRUPT":data;}
|
||||
void Close(){}
|
||||
};
|
||||
namespace FileIO {
|
||||
FileHandle* OpenFile(string path,int){static FileHandle h;h.path=path;return fault==1?nullptr:&h;}
|
||||
bool FileExists(string path){return files.count(path);}
|
||||
bool DeleteFile(string path){return files.erase(path);}
|
||||
bool CopyFile(string from,string to){
|
||||
if(!files.count(from))return false;
|
||||
if(to==PATH+".bak"&&fault==3)return false;
|
||||
files[to]=files[from];
|
||||
if(to==PATH+".bak"&&fault==4)files[to]="CORRUPT";
|
||||
if(from==PATH+".tmp"){
|
||||
if(fault==5){files[to]="PARTIAL";return false;}
|
||||
if(fault==6)files[to]="CORRUPT";
|
||||
if(fault==7){files[to]="WRONG";documents["WRONG"]={{"mission","wrong"}};}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
struct Store {
|
||||
static bool ContentsValid(Map){return true;}
|
||||
static string Encode(Map values){string id="doc"+std::to_string(++serial);documents[id]=values;return id;}
|
||||
static bool Document(string path,Map& values){
|
||||
if(!files.count(path)||!documents.count(files[path]))return false;
|
||||
values=documents[files[path]];return true;
|
||||
}
|
||||
static bool Same(Map a,Map b){return a==b;}
|
||||
''' + method + r'''
|
||||
};
|
||||
int main(){
|
||||
Map old={{"mission","old"},{"items","presets"},{"voice","url"}}, next=old,read;
|
||||
next["mission"]="new";
|
||||
for(int injected:{1,2,5,6,7}){
|
||||
files.clear();fault=injected;
|
||||
assert(!Store::Commit(next)&&!files.count(PATH)); // failed first save stays absent
|
||||
}
|
||||
for(int injected=1;injected<=7;injected++){
|
||||
files.clear();fault=0;assert(Store::Commit(old));
|
||||
fault=injected;assert(!Store::Commit(next));
|
||||
assert(Store::Document(PATH,read)&&read==old); // current valid config remains
|
||||
fault=0;assert(Store::Commit(next));
|
||||
assert(Store::Document(PATH,read)&&read==next);
|
||||
}
|
||||
for(int injected:{1,2,5,6,7}){
|
||||
files.clear();files[PATH]="CORRUPT";files[PATH+".bak"]=Store::Encode(old);
|
||||
fault=injected;assert(!Store::Commit(next));
|
||||
assert(Store::Document(PATH+".bak",read)&&read==old); // only good backup not replaced
|
||||
fault=0;assert(Store::Commit(next));
|
||||
assert(Store::Document(PATH,read)&&read==next);
|
||||
}
|
||||
files.clear();fault=0;assert(Store::Commit(old));assert(Store::Commit(next));
|
||||
assert(Store::Document(PATH+".bak",read)&&read==old);
|
||||
assert(!files.count(PATH+".tmp"));
|
||||
Replication::server=false;assert(!Store::Commit(old));
|
||||
assert(Store::Document(PATH,read)&&read==next);
|
||||
}
|
||||
''')
|
||||
print('PASS: shared config transaction rejects client writes, preserves first-save/prior/fallback state across open, write, backup, partial-copy, readback and mismatch failures')
|
||||
|
||||
# Execute actual shared Save and Commit, with a small token document store.
|
||||
# JSON lexing and non-terrain section parsers are explicit doubles. The terrain
|
||||
# rejection runs the actual TerrainPreference.Parse method with a catalog double.
|
||||
# No native filesystem atomicity or full JsonLoadContext implementation claim.
|
||||
def translate(method):
|
||||
for before, after in [
|
||||
('map<string, string>', 'Map'), ('new Map()', 'Map()'),
|
||||
('FileHandle file','FileHandle* file'), ('file.','file->'),
|
||||
('FileIO.','FileIO::'), ('FileMode.','FileMode::'), ('Replication.','Replication::'),
|
||||
('JsonSaveContext json','JsonSaveContext& json')]:
|
||||
method=method.replace(before,after)
|
||||
method=method.replace('foreach (string key, string value : changed)', 'for (auto [key,value] : changed)')
|
||||
method=method.replace('foreach (string path : LegacyPaths())', 'for (string path : LegacyPaths())')
|
||||
return method
|
||||
helper='static bool ContentsValid(Map) {return true;}'
|
||||
if 'static bool ContentsValid(' in p.read_text(): helper=translate(body(p,'static bool ContentsValid('))
|
||||
terrain = body(ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainPreference.c', 'static bool Parse(').replace('JsonLoadContext json', 'JsonLoadContext& json').replace('out ResourceName scenario', 'string& scenario').replace('ERR_TerrainCatalog.', 'ERR_TerrainCatalog::')
|
||||
run(r"""
|
||||
#include <cassert>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
struct string:std::string{using std::string::string;string(std::string s):std::string(s){}bool IsEmpty(){return empty();}int Length(){return size();}void TrimInPlace(){}};
|
||||
struct Map:std::map<string,string>{using std::map<string,string>::map;bool Contains(string key){return count(key);}string Get(string key){return at(key);}void Set(string key,string value){(*this)[key]=value;}};
|
||||
const string PATH="Escapists.json";
|
||||
std::map<string,string> files;
|
||||
std::map<string,Map> documents;
|
||||
int serial=0,copies=0,writes=0;
|
||||
namespace Replication{bool server=true;bool IsServer(){return server;}}
|
||||
namespace FileMode{int WRITE=1;}
|
||||
struct FileHandle{string path;void Write(string data){writes++;files[path]=data;}void Close(){}};
|
||||
namespace FileIO{
|
||||
FileHandle* OpenFile(string path,int){static FileHandle h;h.path=path;return &h;}
|
||||
bool FileExists(string path){return files.count(path);}
|
||||
bool DeleteFile(string path){return files.erase(path);}
|
||||
bool CopyFile(string from,string to){if(!files.count(from))return false;copies++;files[to]=files[from];return true;}
|
||||
}
|
||||
struct JsonSaveContext{string token;string SaveToString(){return token;}};
|
||||
struct JsonLoadContext{Map fields;bool ReadValue(string key,string&value){if(!fields.Contains(key))return false;value=fields.Get(key);return true;}};
|
||||
namespace ERR_TerrainCatalog{string Key(string scenario){return scenario=="valid-saved-terrain"?"known":"";}}
|
||||
struct Terrain{
|
||||
""" + terrain + r"""
|
||||
};
|
||||
struct Store{
|
||||
static std::vector<string> LegacyPaths(){return {"mission","mods","factions","terrain","items","voice"};}
|
||||
static string Section(string path){return path;}
|
||||
static bool Ensure(){return true;}
|
||||
static string Encode(Map values){string id="doc"+std::to_string(++serial);documents[id]=values;return id;}
|
||||
static bool Split(string text,Map& values){if(!documents.count(text))return false;values=documents[text];return true;}
|
||||
static bool Valid(string section,string text){Map fields;if(!Split(text,fields))return false;if(section!="terrain")return true;JsonLoadContext json{fields};string scenario;return Terrain::Parse(json,scenario);}
|
||||
static bool Document(string path,Map& values){return files.count(path)&&Split(files[path],values)&&values.Contains("configVersion")&&values.Get("configVersion")=="1";}
|
||||
static bool Same(Map a,Map b){return a==b;}
|
||||
""" + helper + translate(body(p,'static bool Commit(')) + translate(body(p,'static bool Save(')) + r"""
|
||||
};
|
||||
int main(){
|
||||
auto validTerrain=Store::Encode({{"scenario","valid-saved-terrain"},{"futureTerrainKey","keep"}});
|
||||
auto invalidTerrain=Store::Encode({{"scenario","malformed"},{"futureTerrainKey","keep"}});
|
||||
auto mission=Store::Encode({{"timer","10"},{"unknownMissionKey","keep"}});
|
||||
auto changedMission=Store::Encode({{"timer","20"}});
|
||||
Map good={{"configVersion","1"},{"mission",mission},{"terrain",validTerrain},{"unknownRoot","keep"}},current=good,read;
|
||||
current.Set("terrain",invalidTerrain);string originalGood=Store::Encode(good),originalBad=Store::Encode(current);
|
||||
files[PATH]=originalBad;files[PATH+".bak"]=originalGood;
|
||||
// Owner would reject current terrain and accept backup. An unrelated save must
|
||||
// not destroy the only recovery document or report success with invalid data.
|
||||
assert(!Store::Valid("terrain",current.Get("terrain"))&&Store::Valid("terrain",good.Get("terrain")));
|
||||
JsonSaveContext change{changedMission};
|
||||
assert(!Store::Save("mission",change));
|
||||
assert(files[PATH]==originalBad&&files[PATH+".bak"]==originalGood&&copies==0&&writes==0&&files.size()==2);
|
||||
// Repair the section through its recovered menu value. Preserve the only good
|
||||
// backup; merge unknown fields and allow subsequent ordinary menu persistence.
|
||||
JsonSaveContext repair{validTerrain};assert(Store::Save("terrain",repair));
|
||||
assert(files[PATH+".bak"]==originalGood&&Store::Document(PATH,read));
|
||||
assert(read.Get("unknownRoot")=="keep");Map fields;assert(Store::Split(read.Get("terrain"),fields)&&fields.Get("futureTerrainKey")=="keep");
|
||||
string repaired=files[PATH];assert(Store::Save("mission",change));assert(files[PATH+".bak"]==repaired);
|
||||
assert(Store::Document(PATH,read)&&Store::Split(read.Get("mission"),fields));assert(fields.Get("timer")=="20"&&fields.Get("unknownMissionKey")=="keep");
|
||||
// Missing optional sections continue to use their owner defaults; unknown roots
|
||||
// are not subject to this version's validators.
|
||||
Map sparse={{"configVersion","1"},{"unrecognized","opaque"}};assert(Store::Commit(sparse));
|
||||
// Existing defaults and each known section are checked; no invalid first write.
|
||||
files.clear();copies=0;writes=0;assert(!Store::Commit(current)&&files.empty()&&copies==0&&writes==0);
|
||||
// Updating an already healthy document retains ordinary last-valid backup.
|
||||
files[PATH]=originalGood;assert(Store::Save("mission",change));assert(files[PATH+".bak"]==originalGood);
|
||||
}
|
||||
""")
|
||||
print('PASS: actual Save/Commit preserves semantically valid backup across unrelated menu edits and repairs; unknown fields/default sections retained; actual terrain parser; other parsers, catalog and disk doubled')
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"target": "/home/jakub/devel/escapistsrereintroduced",
|
||||
"files": {
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ProfileConfig.c": {
|
||||
"baseline_sha256": "ac28363fd5861523db278bb18aa5499f356fef69d35435d1f4ef547da704b67d",
|
||||
"proposal_sha256": "9df8ccf45fc2ed12f4b14d08270878696e8785760a3ae51fe032b6f3818fc0e6",
|
||||
"index_sha256": null,
|
||||
"index_absent": true
|
||||
},
|
||||
"tests/test_profile_config.py": {
|
||||
"baseline_sha256": "088ea06a32a59711d8e02c426d5fdd4a14657cded725b831af312bd8eb5f133f",
|
||||
"proposal_sha256": "727dc330db23d744fca0c965474f834d0cb70432e58938f286fde28bd8415435",
|
||||
"index_sha256": null,
|
||||
"index_absent": true
|
||||
}
|
||||
},
|
||||
"native": "Not run; user game remains untouched.",
|
||||
"patch_sha256": "9ddefab1f87ef5d0924e096d51359482e43de9b250c7986c98360c97d432104d",
|
||||
"test_results_sha256": "20af613fa5168dc7e93734b4ce1b0f5ef771946bc310e802b58e93dee09f89cd",
|
||||
"unchanged_actual_parser": {
|
||||
"path": "addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainPreference.c",
|
||||
"sha256": "93fc55f2c33e95adbcf2bead3430aa14bdb55154315760bcc9647f89dc8286ff"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
[
|
||||
{
|
||||
"name": "baseline-red",
|
||||
"exit": 1,
|
||||
"expected_observed": true,
|
||||
"log_sha256": "a51853e6c0004c0c17b932fb4b2d201d7618648fe1ba6f802c31011228f3c404",
|
||||
"source_sha256": "ac28363fd5861523db278bb18aa5499f356fef69d35435d1f4ef547da704b67d"
|
||||
},
|
||||
{
|
||||
"name": "proposal-green",
|
||||
"exit": 0,
|
||||
"expected_observed": true,
|
||||
"log_sha256": "1c414380eb465210146fed3d49b2108f593abd625b6ffb92f50e7f27131de6f0",
|
||||
"source_sha256": "9df8ccf45fc2ed12f4b14d08270878696e8785760a3ae51fe032b6f3818fc0e6"
|
||||
},
|
||||
{
|
||||
"name": "previous-validation-red",
|
||||
"exit": 1,
|
||||
"expected_observed": true,
|
||||
"log_sha256": "0f8438d6a2ad9c46e8372fc1ad3f4e2c01d07179c3bc19d1279de1066ae42ae9",
|
||||
"source_sha256": "0098c3e33fb160a04a89c3ef9635bfcc75a4db1ee42b1412257492e0f9e7728b"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"complete": true,
|
||||
"post_suite_document_changes": {
|
||||
"docs/configuration.md": {
|
||||
"before": "3f6612dcb7366e2279b81a8b7b4b0e5f80bafeb94199633f55470ebde6acd253",
|
||||
"after": "5b94830326f8cfee366b131fd3a1fa7b5a74ebda808c2839929125e183417551"
|
||||
},
|
||||
"docs/infantry-resupply.md": {
|
||||
"before": "269d00c4397a04018c4366bf1c4be52bd290561b4484210442713ff641dfc74e",
|
||||
"after": "bb9c68e634ceb27c9501be1b8ed43e35229269d0889a5152360ebeb213004e7b"
|
||||
},
|
||||
"docs/current-status.md": {
|
||||
"before": "5d4494b599f9379ef137222230ae0ea79d579e7a032772aa97de0138138b319c",
|
||||
"after": "a1c648325198a83030b83b3684f94500548b289513e8f034266aa03432a5da91"
|
||||
}
|
||||
},
|
||||
"source_tests_tools_unchanged": true,
|
||||
"fresh_suite_after_prose_changes_claimed": false,
|
||||
"index_unchanged": true,
|
||||
"original533_unchanged": true,
|
||||
"four_sealed_candidates_unchanged": true
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
E
|
||||
======================================================================
|
||||
ERROR: test_actual_bundle_validator (__main__.OptionalIdentityTests.test_actual_bundle_validator)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "/tmp/erri-optional-identity-1509/tests/test_external_addons.py", line 135, in test_actual_bundle_validator
|
||||
bundle.validate(payload,ROOT)
|
||||
~~~~~~~~~~~~~~~^^^^^^^^^^^^^^
|
||||
File "/tmp/erri-optional-identity-1509/baseline/tools/source_bundle.py", line 160, in validate
|
||||
raise ValueError(f'unresolved or nonvanilla resource: {name}')
|
||||
ValueError: unresolved or nonvanilla resource: addons/core/Scripts/Game/ERR/00_Core/ERR_ReaperRHSCompat.c
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 1 test in 0.085s
|
||||
|
||||
FAILED (errors=1)
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
F
|
||||
======================================================================
|
||||
FAIL: test_actual_repository_resource_loop (__main__.OptionalIdentityTests.test_actual_repository_resource_loop)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "/tmp/erri-optional-identity-1509/tests/test_external_addons.py", line 123, in test_actual_repository_resource_loop
|
||||
self.repository_resource_loop(self.name,self.text)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/tmp/erri-optional-identity-1509/tests/test_external_addons.py", line 121, in repository_resource_loop
|
||||
exec(code,env)
|
||||
~~~~^^^^^^^^^^
|
||||
File "actual_repository_resource_loop", line 69, in <module>
|
||||
AssertionError: Unresolved/mismatched resource in /tmp/erri-optional-identity-1509/test-root/addons/core/Scripts/Game/ERR/00_Core/ERR_ReaperRHSCompat.c: 574AA64002B8E308 Prefabs/Characters/REAPER_SpectatorCameraHelper.et
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 1 test in 0.006s
|
||||
|
||||
FAILED (failures=1)
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
{
|
||||
"Assets/Items/Equipment/Maps/Map_Paper_01/Map_Paper_01_folded.xob": "E443663E5241622A",
|
||||
"Assets/Items/Equipment/Radios/Radio_R107M/Radio_R107M_01_item.xob": "77C9FCF3FB1246E9",
|
||||
"Assets/Items/Equipment/workspaces/paper_map.agr": "83675D0B0AB1B2C3",
|
||||
"Assets/Items/Equipment/workspaces/player_map.asi": "56794534F6B8C3D7",
|
||||
"Assets/Props/Fabric/Flags/Data/Flag_1_2_SovietArmy.emat": "B47B52D9DA68905D",
|
||||
"Assets/Props/Fabric/Flags/Data/Flag_1_2_USA.emat": "610803CC3F3D6649",
|
||||
"Assets/Props/Military/AmmoBox/EquipmentBoxWooden_01/Data/EquipmentBoxWooden_Weapon_01_USSR.emat": "7D2E831AFA5CF50D",
|
||||
"Assets/Props/Military/AmmoBox/EquipmentBoxWooden_01/EquipmentBoxWooden_Weapon_01.xob": "819ED3266EE5113B",
|
||||
"Assets/Props/Military/Sandbags/Data/Sandbags_01_Burlap_MLOD.emat": "2169E8EB73E1C127",
|
||||
"Assets/Props/Military/Sandbags/Data/Sandbags_01_short_Burlap.emat": "31529E064AA7C917",
|
||||
"Assets/Props/Military/Sandbags/Sandbag_01_short.xob": "268DBDABB3C94AD7",
|
||||
"Assets/Structures/BuildingsParts/Doors/DoorFrame_door_metal_A_RIGHT_EXT_B.xob": "E3BC73BFBC7AA497",
|
||||
"Assets/Structures/Walls/Concrete/ConcreteWall_01_3m.xob": "0B96D139FEBCA006",
|
||||
"Configs/Callsigns/Callsigns_US.conf": "CB7824D572DD0D5C",
|
||||
"Configs/Callsigns/Callsigns_USSR.conf": "958043CE1648EC43",
|
||||
"Configs/EntityCatalog/US/Characters_EntityCatalog_US.conf": "B56E8B4D4B195559",
|
||||
"Configs/EntityCatalog/US/Groups_EntityCatalog_US.conf": "4E70E7C4C2C17D4A",
|
||||
"Configs/EntityCatalog/US/InventoryItems_EntityCatalog_US.conf": "5F7EC52FC40A03E2",
|
||||
"Configs/EntityCatalog/US/SupplyContainerItems_EntityCatalog_US.conf": "0BF36EFF9FFAF92B",
|
||||
"Configs/EntityCatalog/US/WeaponTripod_EntityCatalog_US.conf": "0E4B62F186F97C43",
|
||||
"Configs/EntityCatalog/USSR/Characters_EntityCatalog_USSR.conf": "3B679F1799D55F6F",
|
||||
"Configs/EntityCatalog/USSR/Groups_EntityCatalog_USSR.conf": "37D5B75AAC3E72EA",
|
||||
"Configs/EntityCatalog/USSR/InventoryItems_EntityCatalog_USSR.conf": "C53421647C3D0D2E",
|
||||
"Configs/EntityCatalog/USSR/SupplyContainerItems_EntityCatalog_USSR.conf": "B4CA6761AC935808",
|
||||
"Configs/EntityCatalog/USSR/WeaponTripod_EntityCatalog_USSR.conf": "DDF17C8C140BD1F2",
|
||||
"Configs/Factions/BLUFOR.conf": "E7B7EA4823DD81F0",
|
||||
"Configs/Factions/FIA.conf": "8053DB656DD18B14",
|
||||
"Configs/Factions/OPFOR.conf": "B122E3B10BB3404B",
|
||||
"Configs/GameOverScreen/BaseGameOverScreensConfig.conf": "651583FFFB7FC765",
|
||||
"Configs/Identities/FactionIdentity_US.conf": "B600946E9ACC17C2",
|
||||
"Configs/Identities/FactionIdentity_USSR.conf": "FBBCD73926989580",
|
||||
"Configs/Identities/Territories/FactionHomeTerritory_US.conf": "B548A5B264939A98",
|
||||
"Configs/Identities/Territories/FactionHomeTerritory_USSR.conf": "31FC78AF00523A99",
|
||||
"Configs/Map/MapPlain.conf": "A786DD4868598F15",
|
||||
"Configs/Navmesh/Navmesh_GM_Eden_Soldier.conf": "8BBC73472092902E",
|
||||
"Configs/Navmesh/Navmesh_GM_Eden_Vehicle.conf": "0228A79846FD8A97",
|
||||
"Configs/System/ActionContext/ManualCameraContext.conf": "C538807EEE48BED8",
|
||||
"Configs/System/chimeraInputCommon.conf": "795184CF9AD764DB",
|
||||
"Configs/System/chimeraMenus.conf": "C747AFB6B750CE9A",
|
||||
"Configs/Systems/MissionSystems.conf": "C50579A2EC48E8EF",
|
||||
"Prefabs/AI/Groups/Group_Base.et": "000CD338713F2B5A",
|
||||
"Prefabs/AI/SCR_AIWorld.et": "E0A05C76552E7F58",
|
||||
"Prefabs/AI/Waypoints/AIWaypoint_Cycle.et": "35BD6541CBB8AC08",
|
||||
"Prefabs/AI/Waypoints/AIWaypoint_Defend.et": "93291E72AC23930F",
|
||||
"Prefabs/AI/Waypoints/AIWaypoint_GetIn.et": "712F4795CF8B91C7",
|
||||
"Prefabs/AI/Waypoints/AIWaypoint_GetOut.et": "C40316EE26846CAB",
|
||||
"Prefabs/AI/Waypoints/AIWaypoint_Move.et": "750A8D1695BD6998",
|
||||
"Prefabs/AI/Waypoints/AIWaypoint_SearchAndDestroy.et": "B3E7B8DC2BAB8ACC",
|
||||
"Prefabs/Characters/Campaign/Final/OPFOR/USSR_Army/Regular/Campaign_USSR_Player_MortarCrew.et": "86E565387A634103",
|
||||
"Prefabs/Characters/Factions/BLUFOR/US_Army/Character_US_Base.et": "836E7E39AAC5888B",
|
||||
"Prefabs/Characters/Factions/BLUFOR/US_Army/Character_US_HeliPilot.et": "42A502E3BB727CEB",
|
||||
"Prefabs/Characters/Factions/BLUFOR/US_Army/Character_US_Sniper.et": "0F6689B491641155",
|
||||
"Prefabs/Characters/Factions/BLUFOR/US_Army/Character_US_Unarmed.et": "2F912ED6E399FF47",
|
||||
"Prefabs/Characters/Factions/BLUFOR/US_Army/GreenBerets/Character_US_SF.et": "36E28C628A2F83CB",
|
||||
"Prefabs/Characters/Factions/BLUFOR/US_Army/GreenBerets/Character_US_SF_Medic.et": "9A234C5857D92187",
|
||||
"Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_AR.et": "23ADBBC31B6A3DC6",
|
||||
"Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_AT.et": "1C78331E156A3D65",
|
||||
"Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_HeliPilot.et": "A62FA97C4EC64F14",
|
||||
"Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_LAT.et": "BF643BE4ADBDFDD3",
|
||||
"Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_RTO.et": "612F43A4D5AE765F",
|
||||
"Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_Rifleman.et": "DCB41B3746FDD1BE",
|
||||
"Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_SL.et": "5436629450D8387A",
|
||||
"Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_SR.et": "333DA6244C7DA34C",
|
||||
"Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_Sharpshooter.et": "976AC400219898FA",
|
||||
"Prefabs/Characters/Factions/OPFOR/USSR_Army/Spetsnaz/Character_USSR_SF.et": "2DB452B3EC386B92",
|
||||
"Prefabs/Characters/Factions/OPFOR/USSR_Army/Spetsnaz/Character_USSR_SF_Medic.et": "8CA70597606992EC",
|
||||
"Prefabs/Characters/Footwear/CombatBoots_US_01.et": "DAAFD15478BDE1C3",
|
||||
"Prefabs/Characters/HeadGear/Hat_Patrol_US_01/Hat_Patrol_US_01.et": "F545C1BE7C99954A",
|
||||
"Prefabs/Characters/HeadGear/Helmet_PASGT_01/Helmet_PASGT_01_base.et": "8A2B2A544F3ED831",
|
||||
"Prefabs/Characters/Uniforms/Jacket_US_BDU_rolledup.et": "3CCA7A9BB4FD3197",
|
||||
"Prefabs/Characters/Uniforms/Pants_US_BDU.et": "604BB72BE8E023C2",
|
||||
"Prefabs/Decals/Dirt/Decal_Dirt_Patch_03.et": "4AD6EB80A8B1FA3A",
|
||||
"Prefabs/Groups/BLUFOR/Group_US_FireTeam.et": "84E5BBAB25EA23E5",
|
||||
"Prefabs/Groups/INDFOR/Group_FIA_FireTeam.et": "5BEA04939D148B1D",
|
||||
"Prefabs/Groups/OPFOR/Group_USSR_Base.et": "8DE0C0830FE0C33D",
|
||||
"Prefabs/Groups/OPFOR/Group_USSR_RifleSquad.et": "E552DABF3636C2AD",
|
||||
"Prefabs/Items/Core/Item_Base.et": "C95E11C60810F432",
|
||||
"Prefabs/Items/Equipment/Backpacks/Backpack_Kolobok.et": "41A9C55B61F375F0",
|
||||
"Prefabs/Items/Equipment/Binoculars/Binoculars_B8/Binoculars_B8.et": "243948B23D90BECB",
|
||||
"Prefabs/Items/Equipment/Kits/MedicalKit_01/MedicalKit_01_US.et": "AE578EEA4244D41F",
|
||||
"Prefabs/Items/Equipment/Kits/MedicalKit_01/MedicalKit_01_USSR.et": "21EF98BFC1EB3793",
|
||||
"Prefabs/Items/Equipment/Kits/RepairKit_01/RepairKit_01_wrench.et": "33B2DFDCD0EBA3DB",
|
||||
"Prefabs/Items/Equipment/Maps/Map_Paper_01/PaperMap_01_folded.et": "13772C903CB5E4F7",
|
||||
"Prefabs/Items/Equipment/Radios/Radio_ANPRC77.et": "9B6B61BB3FE3DFB0",
|
||||
"Prefabs/Items/Equipment/Radios/Radio_R107M.et": "54C68E438DD34265",
|
||||
"Prefabs/Items/Equipment/Radios/Radio_R148.et": "E1A5D4B878AA8980",
|
||||
"Prefabs/Items/Equipment/Watches/Watch_SandY184A.et": "78ED4FEF62BBA728",
|
||||
"Prefabs/Items/Fuel/Jerrycan_01/Jerrycan_01_item.et": "12D5AD21E383B768",
|
||||
"Prefabs/Items/Medicine/FieldDressing_01/FieldDressing_USSR_01.et": "C3F1FA1E2EC2B345",
|
||||
"Prefabs/Items/Medicine/FieldDressing_01/FieldDressing_US_01.et": "A81F501D3EF6F38E",
|
||||
"Prefabs/Items/Medicine/MorphineInjection_01/MorphineInjection_01.et": "0D9A5DCF89AE7AA9",
|
||||
"Prefabs/Items/Medicine/SalineBag_01/SalineBag_USSR_01.et": "527D7C5D2E476BDC",
|
||||
"Prefabs/Items/Medicine/SalineBag_01/SalineBag_US_01.et": "00E36F41CA310E2A",
|
||||
"Prefabs/Items/Medicine/Tourniquet_01/Tourniquet_US_01.et": "D70216B1B2889129",
|
||||
"Prefabs/Items/Misc/IntelligenceFolder_E_01/IntelligenceFolder_E_01.et": "6D56FED1E55A8F84",
|
||||
"Prefabs/MP/Managers/Factions/FactionManager_Base.et": "A242612865F2A48E",
|
||||
"Prefabs/MP/Managers/Factions/FactionManager_USxUSSR.et": "589540B35EBA8CDC",
|
||||
"Prefabs/MP/Managers/Loadouts/LoadoutManager_USxUSSR.et": "97EF4C1A41F63DDB",
|
||||
"Prefabs/MP/Modes/GameMode_Base.et": "0F307326459A1395",
|
||||
"Prefabs/MP/ScriptedChatEntity.et": "F69BC912AC8236F9",
|
||||
"Prefabs/Props/EmptyStorages/USSR_AmmoBox_empty.et": "EBBC859CCD94D96D",
|
||||
"Prefabs/Props/Furniture/Table_01.et": "53506DCB398C7EBE",
|
||||
"Prefabs/Props/Military/Antennas/Antenna_FIA_02/Antenna_FIA_02_base.et": "B3949F6D215A9F78",
|
||||
"Prefabs/Props/Military/Sandbags/Sandbag_01_short_burlap.et": "CFFEB23FBEA00322",
|
||||
"Prefabs/Structures/BuildingParts/Doors/DoorSet_Base.et": "87CADB5ADC989993",
|
||||
"Prefabs/Structures/BuildingParts/Doors/Door_MetalGate_01_Short_LEFT_EXT_ST_B.et": "34B08027DBDE322A",
|
||||
"Prefabs/Structures/BuildingParts/Doors/Door_Metal_A_RIGHT_EXT_COV_B.et": "67F17696FF278AE0",
|
||||
"Prefabs/Structures/Military/Camps/TentSmallUS_01/TentSmallUS_01.et": "01AE5FD77A9A4C21",
|
||||
"Prefabs/Structures/Military/Camps/TentUSSR_01/TentUSSR_01_base.et": "BE5D5CFA90224646",
|
||||
"Prefabs/Structures/Military/Camps/TentUS_01/TentUSMedical_01.et": "F8427C3EFC52644E",
|
||||
"Prefabs/Structures/Walls/BarbedWire/BarbedTape_01/BarbedTape_01_Long_noStake.et": "46904AF5D473FB75",
|
||||
"Prefabs/Structures/Walls/BarbedWire/BarbedTape_01/BarbedTape_01_Short_noStake.et": "CAE1588B6265A2AB",
|
||||
"Prefabs/Structures/Walls/Concrete/ConcreteWall_01/ConcreteWall_01_3m.et": "60E5729BEA18F875",
|
||||
"Prefabs/Systems/Radio/RadioManager.et": "B8E09FAB91C4ECCD",
|
||||
"Prefabs/Tasks/BaseTask.et": "1D0F815858EE24AD",
|
||||
"Prefabs/Vehicles/Helicopters/Mi8MT/Mi8MT_armed.et": "7BD282AF716ED639",
|
||||
"Prefabs/Vehicles/Helicopters/Mi8MT/Mi8MT_unarmed_transport.et": "DF5CCB7C0FF049F4",
|
||||
"Prefabs/Vehicles/Wheeled/UAZ469/UAZ469.et": "259EE7B78C51B624",
|
||||
"Prefabs/Vehicles/Wheeled/UAZ469/UAZ469_PKM.et": "0B4DEA8078B78A9B",
|
||||
"Prefabs/Vehicles/Wheeled/UAZ469/VehParts/Seats/UAZ469_seats_rear.et": "780AAF0A51AEE61A",
|
||||
"Prefabs/Vehicles/Wheeled/Ural4320/Ural4320_ammo.et": "3336BE330C4F355B",
|
||||
"Prefabs/Vehicles/Wheeled/Ural4320/Ural4320_transport.et": "16C1F16C9B053801",
|
||||
"Prefabs/Weapons/Ammo/Ammo_Shell_82mm_HE_O832DU.et": "98EC9C526AFBA282",
|
||||
"Prefabs/Weapons/Attachments/Optics/Optic_4x20/Optic_4x20.et": "BD496EE1B40DC510",
|
||||
"Prefabs/Weapons/Attachments/Optics/Optic_ARTII/Optic_ARTII.et": "D2018EDB1BBF4C88",
|
||||
"Prefabs/Weapons/Attachments/Optics/Optic_PSO1/Optic_PSO1.et": "C850A33226B8F9C1",
|
||||
"Prefabs/Weapons/Core/VehiclePeriscope_DummyWeapon_Base.et": "7E1DD1CE4D6A23F4",
|
||||
"Prefabs/Weapons/Explosives/Mine_PMN4/Mine_PMN4.et": "B05A816C0BF50802",
|
||||
"Prefabs/Weapons/Handguns/PM/Handgun_PM.et": "C0F7DD85A86B2900",
|
||||
"Prefabs/Weapons/Magazines/Magazine_545x39_AK_30rnd_Ball.et": "BBB50A815A2F916B",
|
||||
"Prefabs/Weapons/Magazines/Magazine_762x51_M14_20rnd_SpecialBall.et": "627255315038152A",
|
||||
"Prefabs/Weapons/Magazines/Magazine_762x54_SVD_10rnd_Sniper.et": "9CCB46C6EE632C1A",
|
||||
"Prefabs/Weapons/Magazines/Magazine_9x18_PM_8rnd_Ball.et": "8B853CDD11BA916E",
|
||||
"Prefabs/Weapons/Mortars/2B14/Mortar_2B14.et": "D1FFE458E8AC4BDB",
|
||||
"Prefabs/Weapons/Rifles/AK74/Rifle_AK74.et": "FA5C25BF66A53DCF",
|
||||
"Prefabs/World/Game/PerceptionManager.et": "028DAEAD63E056BE",
|
||||
"Sounds/Items/_SharedData/PickUp/Items_PickUp_Map.acp": "13F8D0DE67678118",
|
||||
"Sounds/Vehicles/Wheeled/UAZ469/Vehicles_UAZ469_Horn.acp": "7E64D37BE3E1F3FA",
|
||||
"UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt": "3E7733BAC8C831F6",
|
||||
"UI/Textures/DeployMenu/Loadout-BG/Loadout_BG_USSR.imageset": "21533F2089005056",
|
||||
"UI/Textures/DeployMenu/Loadout-BG/Loadout_US_BG.imageset": "F8AC305446D5D480",
|
||||
"UI/Textures/Editor/EditableEntities/Factions/EditableEntity_Faction_USA.edds": "EB7F65DBC9392557",
|
||||
"UI/Textures/Editor/EditableEntities/Factions/EditableEntity_Faction_USSR.edds": "40B12B0DF911B856",
|
||||
"UI/Textures/Flags/US-flag-base-3it.edds": "46FB2FB2C2125A3C",
|
||||
"UI/Textures/Flags/USSR-flag-base-3it.edds": "50824EB9F2C215AB",
|
||||
"UI/Textures/Icons/icons_mapMarkersUI-glow.imageset": "67B3A6DC2D712B52",
|
||||
"UI/Textures/Icons/icons_mapMarkersUI.imageset": "E23427CAC80DA8B7",
|
||||
"UI/Textures/Icons/icons_wrapperUI-glow.imageset": "00FE3DBDFD15227B",
|
||||
"UI/Textures/Icons/icons_wrapperUI.imageset": "3262679C50EF4F01",
|
||||
"UI/layouts/HUD/GameOver/EndScreen/EndScreenContent_NoImage.layout": "C4507D07F3C54831",
|
||||
"UI/layouts/Menus/PauseMenu/PauseMenuButton.layout": "9ECCD201BCF07E95",
|
||||
"UI/layouts/Task/TaskListEntry.layout": "B71975032150BAFB",
|
||||
"UI/layouts/Task/TaskListEntryDescription.layout": "552EB1921B5C548C",
|
||||
"UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout": "75C912A1C89BE6C2",
|
||||
"UI/layouts/WidgetLibrary/ComboBox/WLib_ComboBox.layout": "4B5AE6E64037FFB4",
|
||||
"UI/layouts/WidgetLibrary/EditBox/WLib_EditBox.layout": "0022F0B45ADBC5AC",
|
||||
"system/textures/defWhite.edds": "A64A8C63E0FBAE87",
|
||||
"worlds/Eden/Eden.ent": "853E92315D1D9EFE",
|
||||
"worlds/MP/Navmeshes/LowResEden.nmn": "5E19E60F26327356"
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Exercise exact dependency closure, resource ownership and isolated profile inputs."""
|
||||
import copy
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
sys.path.insert(0,str(Path(__file__).resolve().parents[1]/'tools'))
|
||||
import external_addons as ext
|
||||
ROOT=Path(__file__).resolve().parents[1]
|
||||
|
||||
class ExternalAddonsTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.temp=tempfile.TemporaryDirectory();self.addCleanup(self.temp.cleanup)
|
||||
self.home=Path(self.temp.name);self.source=self.home/'installed';self.source.mkdir()
|
||||
self.addons=self.home/'profile'/'addons';self.addons.mkdir(parents=True)
|
||||
self.cache=self.home/'profile'/'cache.json';self.value=ext.policy(ROOT)
|
||||
for guid,deps in ext.ALLOWED.items():
|
||||
folder=self.source/guid;folder.mkdir()
|
||||
manifest='GameProject { GUID "'+guid+'" Dependencies { '+' '.join('"'+d+'"' for d in sorted(deps))+' } }\n'
|
||||
(folder/'addon.gproj').write_text(manifest)
|
||||
self.value['addons'][guid]['project_sha256']=hashlib.sha256(manifest.encode()).hexdigest()
|
||||
data=b'RDB synthetic fixture\0'
|
||||
for path,entry in self.value['resources'].items():
|
||||
if entry['addon']==guid:data+=path.encode()+b'\0\x06\0\0\0\0\0'+bytes.fromhex(entry['guid'])[::-1]
|
||||
(folder/'resourceDatabase.rdb').write_bytes(data);(folder/'data.pak').write_bytes(b'fixture '+guid.encode())
|
||||
def test_resource_identity_requires_visible_owner(self):
|
||||
for path,item in self.value['resources'].items():
|
||||
self.assertTrue(ext.resource_allowed(self.value,{item['addon']},item['guid'],path))
|
||||
self.assertFalse(ext.resource_allowed(self.value,{'core'},item['guid'],path))
|
||||
self.assertFalse(ext.resource_allowed(self.value,{item['addon']},'0000000000000000',path))
|
||||
self.assertEqual(ext.direct_for('core'),set(ext.DIRECT));self.assertEqual(ext.direct_for('chat'),set())
|
||||
def test_policy_rejects_original_transitive_dependency(self):
|
||||
root=self.home/'root';(root/'docs').mkdir(parents=True)
|
||||
value=copy.deepcopy(self.value);value['addons'][ext.DIRECT[0]]['dependencies'].append('5F16D7E4A1CBE075')
|
||||
(root/'docs/external-addons.json').write_text(json.dumps(value))
|
||||
with self.assertRaisesRegex(ValueError,'transitive'):ext.policy(root)
|
||||
def test_only_exact_authorized_closure_is_exposed_and_hashed(self):
|
||||
unrelated=self.source/'original';unrelated.mkdir();(unrelated/'addon.gproj').write_text('GameProject { GUID "5F16D7E4A1CBE075" }')
|
||||
records=ext.prepare_profile(self.addons,self.source,self.value,self.cache)
|
||||
self.assertEqual(set(records),set(ext.ALLOWED))
|
||||
self.assertEqual({p.name for p in self.addons.iterdir()},{'ERRI_'+g for g in ext.ALLOWED})
|
||||
self.assertTrue(all(p.is_symlink() for p in self.addons.iterdir()))
|
||||
self.assertTrue(ext.verify_profile(records,self.source,self.value,self.cache,self.addons))
|
||||
self.assertEqual(ext.prepare_profile(self.addons,self.source,self.value,self.cache),records)
|
||||
(self.source/ext.DIRECT[0]/'data.pak').write_bytes(b'mutated runtime')
|
||||
self.assertFalse(ext.verify_profile(records,self.source,self.value,self.cache,self.addons))
|
||||
def test_missing_and_duplicate_identity_fail(self):
|
||||
guid=ext.DIRECT[0];shutil.copytree(self.source/guid,self.source/'duplicate')
|
||||
with self.assertRaisesRegex(ValueError,'Duplicate'):ext.installed(self.source,self.value)
|
||||
shutil.rmtree(self.source/'duplicate');shutil.rmtree(self.source/guid)
|
||||
with self.assertRaisesRegex(ValueError,'Missing installed'):ext.installed(self.source,self.value)
|
||||
def test_manifest_and_database_mutations_fail(self):
|
||||
guid=ext.DIRECT[0];manifest=self.source/guid/'addon.gproj';old=manifest.read_text();manifest.write_text(old+'// changed')
|
||||
with self.assertRaisesRegex(ValueError,'manifest changed'):ext.installed(self.source,self.value)
|
||||
manifest.write_text(old)
|
||||
resource=next(iter(self.value['resources'].values()));(self.source/resource['addon']/'resourceDatabase.rdb').write_bytes(b'wrong GUID')
|
||||
with self.assertRaisesRegex(ValueError,'resource identity'):ext.installed(self.source,self.value)
|
||||
def test_unrelated_profile_addon_and_wrong_link_fail(self):
|
||||
(self.addons/'original').mkdir()
|
||||
with self.assertRaisesRegex(ValueError,'Unrelated'):ext.prepare_profile(self.addons,self.source,self.value,self.cache)
|
||||
(self.addons/'original').rmdir();guid=ext.DIRECT[0]
|
||||
(self.addons/('ERRI_'+guid)).symlink_to(self.source/ext.DIRECT[1],target_is_directory=True)
|
||||
with self.assertRaisesRegex(ValueError,'Unexpected private'):ext.prepare_profile(self.addons,self.source,self.value,self.cache)
|
||||
def test_symlinked_runtime_file_fails(self):
|
||||
pak=self.source/ext.DIRECT[0]/'data.pak';pak.unlink();pak.symlink_to(self.source/ext.DIRECT[1]/'data.pak')
|
||||
with self.assertRaisesRegex(ValueError,'regular file'):ext.installed(self.source,self.value)
|
||||
|
||||
if __name__=='__main__':unittest.main()
|
||||
+93
File diff suppressed because one or more lines are too long
+243
@@ -0,0 +1,243 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Preview or write a deterministic DEVELOPMENT SOURCE BUNDLE; never build/publish."""
|
||||
import argparse
|
||||
import hashlib
|
||||
import io
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path, PurePosixPath
|
||||
import re
|
||||
import stat
|
||||
import tempfile
|
||||
import zipfile
|
||||
import sys
|
||||
|
||||
sys.dont_write_bytecode = True
|
||||
|
||||
from source_manifest import addon_manifest
|
||||
from project_schema import parse_project
|
||||
from external_addons import policy as external_policy, direct_for, resource_allowed, ALLOWED
|
||||
from release_check import audit, read_json, evidence_path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
BASE = '58D0FB3206B6F859'
|
||||
PROJECTS = {'core': ('ERR_Core', '2528466DE220D91C', ())}
|
||||
|
||||
DIRECTORIES = {'Scripts', 'Prefabs', 'Configs', 'Missions', 'Worlds', 'UI', 'Materials', 'AI'}
|
||||
SUFFIXES = {'.c', '.et', '.conf', '.ent', '.layer', '.layout', '.emat', '.bt', '.meta', '.gproj'}
|
||||
EXCLUDED = {'.git', '.build', '.local', '__pycache__', 'profiles', 'profile', 'cache',
|
||||
'runtime', 'evidence', 'vendor', 'vanilla', 'original', 'node_modules', '.agents', '.codex'}
|
||||
README = '''# DEVELOPMENT SOURCE BUNDLE — Co10 Escape Reintroduced
|
||||
|
||||
Author: Jakub Jim Žáček.
|
||||
|
||||
This ZIP contains the single Co10 Escape Reintroduced addon, with Core, AI,
|
||||
Intel, Map and Chat script folders. It is NOT a native .pak or a published mod.
|
||||
Third-party assets are not redistributed.
|
||||
|
||||
Extract into a NEW development folder and register addons/core/addon.gproj in
|
||||
Workbench. Install and register the RHS/WCS dependencies in EXTERNAL-ADDONS.json.
|
||||
Open addons/core/addon.gproj and use Missions/ERR_Everon.conf.
|
||||
|
||||
Scenario: {C1E20667DCE324ED}Missions/ERR_Everon.conf
|
||||
Use the installed engine's normal project/scenario workflow. This archive has not
|
||||
been compiled by its bundler; no native caches or binaries are included.
|
||||
|
||||
Target: Everon, up to 12 players. The mod requires the listed external addons. This remains development source.
|
||||
Manual prison/scavenging/radio/extraction play, remote joins/reconnects and
|
||||
ownership, twelve connected players, aircraft support, repeated companion cleanup,
|
||||
matched-workload FPS improvement and release qualification require separate
|
||||
source-bound validation. Existing scripted fixtures are not those acceptances.
|
||||
WORKBENCH-only probes are source, not proof of a test run or normal gameplay.
|
||||
|
||||
BUNDLE-MANIFEST.json lists each payload file's SHA-256 and project dependencies.
|
||||
Verify extracted bytes against it before editing. The manifest excludes its own
|
||||
hash to avoid self-reference. These hashes identify bytes, not authenticity,
|
||||
license grants or provenance proof. Source review remains required before sharing.
|
||||
Evidence, acceptance records, runtime profiles and test tools are intentionally
|
||||
absent; consult the maintained repository for current status and retained logs.
|
||||
Even --mode release only adds the existing repository qualification audit before
|
||||
this same development-source handoff; it does not build/publish a game release.
|
||||
'''
|
||||
|
||||
|
||||
def canonical(name):
|
||||
p = PurePosixPath(name)
|
||||
if (not name or p.is_absolute() or p.as_posix() != name or '\\' in name
|
||||
or ':' in name or any(ord(c) < 32 for c in name)
|
||||
or any(part in {'.', '..'} or part.endswith((' ', '.')) for part in p.parts)):
|
||||
raise ValueError(f'unsafe bundle path: {name!r}')
|
||||
return p
|
||||
|
||||
|
||||
def inventory(root):
|
||||
"""Reuse the evidence inventory; impose a narrower reviewed handoff schema."""
|
||||
# Preflight directories without following links, including otherwise excluded
|
||||
# entries themselves. Excluded trees are pruned from this preflight and
|
||||
# excluded from the payload; the shared source manifest may still hash them.
|
||||
addons = root / 'addons'
|
||||
if addons.is_symlink() or not addons.is_dir():
|
||||
raise ValueError('addons must be a real directory')
|
||||
for base, dirs, files in os.walk(addons, followlinks=False):
|
||||
for name in list(dirs) + files:
|
||||
path = Path(base) / name
|
||||
if path.is_symlink():
|
||||
raise ValueError(f'symlink refused: {path.relative_to(root)}')
|
||||
if not path.is_dir() and not stat.S_ISREG(path.lstat().st_mode):
|
||||
raise ValueError(f'nonregular addon entry: {path.relative_to(root)}')
|
||||
dirs[:] = [d for d in dirs if d.lower() not in EXCLUDED]
|
||||
original = addon_manifest(root)
|
||||
result = {}
|
||||
folded = set()
|
||||
for name, digest in original.items():
|
||||
parts = canonical(name).parts
|
||||
if any(part.lower() in EXCLUDED for part in parts):
|
||||
continue
|
||||
if any(part.startswith('.') for part in parts):
|
||||
raise ValueError(f'unreviewed hidden addon content: {name}')
|
||||
if len(parts) < 3 or parts[1] not in PROJECTS:
|
||||
raise ValueError(f'unknown addon project: {name}')
|
||||
path = root / name
|
||||
if not stat.S_ISREG(path.lstat().st_mode):
|
||||
raise ValueError(f'nonregular addon file: {name}')
|
||||
if name.casefold() in folded:
|
||||
raise ValueError(f'case-insensitive path collision: {name}')
|
||||
folded.add(name.casefold())
|
||||
if parts[2] == 'addon.gproj' and len(parts) == 3:
|
||||
pass
|
||||
elif len(parts) < 4 or parts[2] not in DIRECTORIES or path.suffix not in SUFFIXES - {'.gproj'}:
|
||||
raise ValueError(f'unreviewed addon source/resource format: {name}')
|
||||
result[name] = digest
|
||||
return result
|
||||
|
||||
|
||||
def validate(payload, root):
|
||||
projects = {}
|
||||
external = external_policy(root)
|
||||
own_ids = read_json(evidence_path(root, 'docs/addons.json'))
|
||||
if own_ids != {name: item[1] for name, item in PROJECTS.items()}:
|
||||
raise ValueError('successor identity catalog differs from the single owned project')
|
||||
for name, (identity, guid, deps) in PROJECTS.items():
|
||||
text = payload.get(f'addons/{name}/addon.gproj', b'').decode('utf-8')
|
||||
match = parse_project(text, allow_core_menu=name == 'core')
|
||||
expected = {BASE, *(PROJECTS[d][1] for d in deps), *direct_for(name)}
|
||||
found = re.findall(r'"([A-F0-9]{16})"', match[4]) if match else []
|
||||
if not match or match[1] != identity or match[2] != guid or set(found) != expected or len(found) != len(expected):
|
||||
raise ValueError(f'identity/dependency closure mismatch: {name}')
|
||||
projects[name] = {'id': identity, 'guid': guid, 'dependencies': sorted(found)}
|
||||
resources = {}
|
||||
for name, data in payload.items():
|
||||
if not name.endswith('.meta'):
|
||||
continue
|
||||
m = re.search(r'Name "\{([A-F0-9]{16})\}([^"\n]+)"', data.decode('utf-8'))
|
||||
owner = name.split('/')[1]
|
||||
if not m or f'addons/{owner}/{m[2]}.meta' != name or name[:-5] not in payload:
|
||||
raise ValueError(f'mismatched/missing resource metadata: {name}')
|
||||
if m[1] in resources or m[1] in own_ids.values() or m[1] == BASE:
|
||||
raise ValueError(f'duplicate resource identity: {name}')
|
||||
resources[m[1]] = (m[2], owner)
|
||||
vanilla = read_json(evidence_path(root, 'docs/vanilla-resources.json'))
|
||||
if set(resources) & set(vanilla.values()):
|
||||
raise ValueError('successor resource reuses a vanilla identity')
|
||||
for name, data in payload.items():
|
||||
suffix = PurePosixPath(name).suffix
|
||||
if suffix == '.meta':
|
||||
continue
|
||||
text = data.decode('utf-8') # Current reviewed handoff contains text assets only.
|
||||
if re.search(r'\b(?:ESCT\w*|SCRTC_\w+|SCRT_\w+|EAI_\w+)\b', text):
|
||||
raise ValueError(f'original ecosystem dependency: {name}')
|
||||
if suffix not in {'.c', '.layer', '.gproj'} and name + '.meta' not in payload:
|
||||
raise ValueError(f'resource lacks successor metadata: {name}')
|
||||
owner = name.split('/')[1]
|
||||
visible = {owner, *PROJECTS[owner][2]}
|
||||
if 'core' in visible: visible.update(ALLOWED)
|
||||
for guid, resource in re.findall(r'\{([A-F0-9]{16})\}([^"\n]+)', text):
|
||||
if guid in resources:
|
||||
path, target = resources[guid]
|
||||
if path != resource or target not in visible:
|
||||
raise ValueError(f'resource outside project dependency closure: {name}')
|
||||
elif vanilla.get(resource) != guid and not resource_allowed(external,visible,guid,resource):
|
||||
raise ValueError(f'unresolved or nonvanilla resource: {name}')
|
||||
return projects
|
||||
|
||||
|
||||
def build(root=ROOT, mode='development'):
|
||||
root = Path(root).resolve()
|
||||
if mode not in {'development', 'release'}:
|
||||
raise ValueError('unknown bundle mode')
|
||||
if mode == 'release':
|
||||
blockers = audit(root)
|
||||
if blockers:
|
||||
raise ValueError('Not release-qualified:\n - ' + '\n - '.join(blockers))
|
||||
before = inventory(root)
|
||||
payload = {name: (root / name).read_bytes() for name in before}
|
||||
if {name: hashlib.sha256(data).hexdigest() for name, data in payload.items()} != before:
|
||||
raise ValueError('addon bytes changed during collection')
|
||||
projects = validate(payload, root)
|
||||
if mode == 'release':
|
||||
blockers = audit(root)
|
||||
if blockers:
|
||||
raise ValueError('Not release-qualified after collection:\n - ' + '\n - '.join(blockers))
|
||||
if inventory(root) != before:
|
||||
raise ValueError('addon tree changed during collection')
|
||||
payload['BUNDLE-README.md'] = (README + '\nThe combined scenario requires the separately installed authorized addons listed in EXTERNAL-ADDONS.json. Their assets are not bundled.\n').encode('utf-8')
|
||||
payload['EXTERNAL-ADDONS.json'] = json.dumps(external_policy(root),indent=2,sort_keys=True).encode('utf-8')
|
||||
manifest = {'schema_version': 1, 'kind': 'DEVELOPMENT SOURCE BUNDLE',
|
||||
'native_build': False, 'release_package': False, 'projects': projects,
|
||||
'files': {name: hashlib.sha256(data).hexdigest() for name, data in sorted(payload.items())}}
|
||||
payload['BUNDLE-MANIFEST.json'] = (json.dumps(manifest, indent=2, sort_keys=True) + '\n').encode()
|
||||
stream = io.BytesIO()
|
||||
with zipfile.ZipFile(stream, 'w', compression=zipfile.ZIP_STORED) as archive:
|
||||
for name, data in sorted(payload.items()):
|
||||
entry = zipfile.ZipInfo(name, date_time=(1980, 1, 1, 0, 0, 0))
|
||||
entry.create_system = 3
|
||||
entry.external_attr = (stat.S_IFREG | 0o644) << 16
|
||||
archive.writestr(entry, data)
|
||||
return stream.getvalue(), manifest
|
||||
|
||||
|
||||
def write_new(output, content, root=ROOT):
|
||||
path = Path(output).absolute()
|
||||
canonical(path.as_posix().lstrip('/'))
|
||||
if path.suffix != '.zip' or path.resolve().is_relative_to(Path(root).resolve()):
|
||||
raise ValueError('output must be a new .zip outside the source checkout')
|
||||
for part in (path, *path.parents):
|
||||
if part.is_symlink():
|
||||
raise ValueError('output symlinks are refused')
|
||||
if path.exists() or not path.parent.is_dir():
|
||||
raise ValueError('output exists or parent directory is missing')
|
||||
temporary = None
|
||||
try:
|
||||
with tempfile.NamedTemporaryFile(prefix='.erri-bundle-', dir=path.parent, delete=False) as file:
|
||||
temporary = Path(file.name)
|
||||
file.write(content)
|
||||
file.flush()
|
||||
os.fsync(file.fileno())
|
||||
# Same-filesystem atomic publication; link refuses an existing destination.
|
||||
os.link(temporary, path, follow_symlinks=False)
|
||||
finally:
|
||||
if temporary is not None:
|
||||
temporary.unlink()
|
||||
|
||||
|
||||
def main(argv=None):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--mode', choices=('development', 'release'), default='development')
|
||||
parser.add_argument('--output', type=Path, help='explicit new .zip outside checkout; omitted means read-only preview')
|
||||
args = parser.parse_args(argv)
|
||||
try:
|
||||
content, manifest = build(mode=args.mode)
|
||||
if args.output:
|
||||
write_new(args.output, content)
|
||||
print(json.dumps({'kind': manifest['kind'], 'preview': args.output is None,
|
||||
'payload_files': len(manifest['files']), 'archive_bytes': len(content),
|
||||
'archive_sha256': hashlib.sha256(content).hexdigest(),
|
||||
'projects': manifest['projects']}, indent=2, sort_keys=True))
|
||||
return 0
|
||||
except (OSError, ValueError, UnicodeError) as error:
|
||||
print(f'Bundle refused: {error}')
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
raise SystemExit(main())
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"problem": "Every GUID/path literal was treated as a hard dependency, including CameraSlot equality against metadata already read from a loaded optional addon. Both repository and source-bundle checks refused existing compatibility code.",
|
||||
"fix": "One shared scanner excludes only one audited occurrence, pinned to exact full source SHA256, relative filename, complete method and unique literal. All source edits fail closed until reviewed. Existing reference/dependency validation otherwise unchanged.",
|
||||
"ordinary_loaded_resource": "Character_Base.et37578B1666981FCE remains a real load; normal vanilla metadata entry added after exact installed RDB verification. REAPER is not added to direct, transitive or runtime dependency closure.",
|
||||
"tests": "Ten existing/extended ExternalAddons tests pass, including actual repository resource loop and full actual bundle.validate against exact authored snapshot plus proposed vanilla JSON. Baseline scanner and bundler fail on same optional identity. Load/spawn/assignment/duplicate/comment/different-file/different-method/removed-mod-gate/source edits refuse exemption.",
|
||||
"scope": "Five tool/test/metadata files only; no production changes, no asset copying, no native/fullsuite run. Full-source hash intentionally requires fresh audit even for harmless compatibility source whitespace edits.",
|
||||
"first_failure": "proposal-initial-missing-vanilla.log preserves legitimate hard-load audit refusal before metadata addition.",
|
||||
"limits": "Python source validator proof only. Does not qualify native compatibility behavior, private runtime with REAPER, or release readiness."
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
--- /dev/null
|
||||
+++ b/tools/resource_references.py
|
||||
@@ -0,0 +1,31 @@
|
||||
+"""Hard resource references, with one fail-closed audited optional identity test.
|
||||
+
|
||||
+This is not a general Enforce parser or a new external dependency allowlist.
|
||||
+Changing any byte of the audited source requires reviewing this exception again.
|
||||
+"""
|
||||
+import hashlib
|
||||
+import re
|
||||
+
|
||||
+OPTIONAL_FILE = 'addons/core/Scripts/Game/ERR/00_Core/ERR_ReaperRHSCompat.c'
|
||||
+OPTIONAL_SHA256 = 'bcdf98c05ac6cdf0c7eaa854531b02e9ee4f53fbb346ae01d58114e572e7dd4f'
|
||||
+OPTIONAL_RESOURCE = '{574AA64002B8E308}Prefabs/Characters/REAPER_SpectatorCameraHelper.et'
|
||||
+OPTIONAL_METHOD = ''' protected static bool CameraSlot(BaseContainer slot)
|
||||
+ {
|
||||
+ if (!slot || slot.GetName() != "SpectatorCameraHelper") return false;
|
||||
+ ResourceName prefab;
|
||||
+ if (!slot.Get("Prefab", prefab)) return false;
|
||||
+ return prefab == "{574AA64002B8E308}Prefabs/Characters/REAPER_SpectatorCameraHelper.et";
|
||||
+ }'''
|
||||
+
|
||||
+
|
||||
+def hard_resource_references(relative_path, text):
|
||||
+ """Exclude only the pinned comparison occurrence; keep all other checks."""
|
||||
+ identity_offset = -1
|
||||
+ if (str(relative_path) == OPTIONAL_FILE
|
||||
+ and hashlib.sha256(text.encode('utf-8')).hexdigest() == OPTIONAL_SHA256
|
||||
+ and text.count(OPTIONAL_METHOD) == 1
|
||||
+ and text.count(OPTIONAL_RESOURCE) == 1):
|
||||
+ identity_offset = text.index(OPTIONAL_METHOD) + OPTIONAL_METHOD.index(OPTIONAL_RESOURCE)
|
||||
+ for match in re.finditer(r'\{([A-F0-9]{16})\}([^"\n]+)', text):
|
||||
+ if match.start() != identity_offset:
|
||||
+ yield match.groups()
|
||||
--- a/tools/check.py
|
||||
+++ b/tools/check.py
|
||||
@@ -2,6 +2,7 @@
|
||||
"""Validate addon/resource isolation and execute policy regressions. Not an engine compiler."""
|
||||
from pathlib import Path
|
||||
import json,re,subprocess,sys
|
||||
+from resource_references import hard_resource_references
|
||||
from external_addons import policy, ALLOWED, direct_for, resource_allowed
|
||||
from prefab_identity import check_prefabs
|
||||
ROOT=Path(__file__).resolve().parents[1]
|
||||
@@ -65,7 +66,7 @@
|
||||
if not p.is_file() or p.suffix not in ['.c','.et','.conf','.ent','.layer','.layout','.emat','.bt']:continue
|
||||
s=p.read_text()
|
||||
assert not re.search(r'\b(?:ESCT\w*|SCRTC_\w+|SCRT_\w+|EAI_\w+)\b',s),f'Original ecosystem dependency: {p}'
|
||||
- for g,path in re.findall(r'\{([A-F0-9]{16})\}([^"\n]+)',s):
|
||||
+ for g,path in hard_resource_references(p.relative_to(ROOT).as_posix(),s):
|
||||
assert resources.get(g)==path or vanilla.get(path)==g or resource_allowed(external,visibility[p.relative_to(ROOT/'addons').parts[0]],g,path),f'Unresolved/mismatched resource in {p}: {g} {path}'
|
||||
if g in owners:
|
||||
addon=p.relative_to(ROOT/'addons').parts[0]
|
||||
--- a/tools/source_bundle.py
|
||||
+++ b/tools/source_bundle.py
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
from source_manifest import addon_manifest
|
||||
from project_schema import parse_project
|
||||
+from resource_references import hard_resource_references
|
||||
from external_addons import policy as external_policy, direct_for, resource_allowed, ALLOWED
|
||||
from release_check import audit, read_json, evidence_path
|
||||
|
||||
@@ -151,7 +152,7 @@
|
||||
owner = name.split('/')[1]
|
||||
visible = {owner, *PROJECTS[owner][2]}
|
||||
if 'core' in visible: visible.update(ALLOWED)
|
||||
- for guid, resource in re.findall(r'\{([A-F0-9]{16})\}([^"\n]+)', text):
|
||||
+ for guid, resource in hard_resource_references(name, text):
|
||||
if guid in resources:
|
||||
path, target = resources[guid]
|
||||
if path != resource or target not in visible:
|
||||
--- a/tests/test_external_addons.py
|
||||
+++ b/tests/test_external_addons.py
|
||||
@@ -1,5 +1,9 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Exercise exact dependency closure, resource ownership and isolated profile inputs."""
|
||||
+import ast
|
||||
+import importlib.util
|
||||
+import os
|
||||
+import re
|
||||
import copy
|
||||
import hashlib
|
||||
import json
|
||||
@@ -9,8 +13,11 @@
|
||||
import tempfile
|
||||
import unittest
|
||||
sys.path.insert(0,str(Path(__file__).resolve().parents[1]/'tools'))
|
||||
+TOOLS=Path(os.environ.get('ERR_OPTIONAL_IDENTITY_TOOLS',Path(__file__).resolve().parents[1]/'tools'))
|
||||
+sys.path.insert(0,str(TOOLS))
|
||||
+import resource_references as refs
|
||||
import external_addons as ext
|
||||
-ROOT=Path(__file__).resolve().parents[1]
|
||||
+ROOT=Path(os.environ.get('ERR_REPO',Path(__file__).resolve().parents[1]))
|
||||
|
||||
class ExternalAddonsTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
@@ -69,4 +76,68 @@
|
||||
pak=self.source/ext.DIRECT[0]/'data.pak';pak.unlink();pak.symlink_to(self.source/ext.DIRECT[1]/'data.pak')
|
||||
with self.assertRaisesRegex(ValueError,'regular file'):ext.installed(self.source,self.value)
|
||||
|
||||
+
|
||||
+class OptionalIdentityTests(unittest.TestCase):
|
||||
+ def setUp(self):
|
||||
+ self.name=refs.OPTIONAL_FILE
|
||||
+ self.text=(ROOT/self.name).read_text()
|
||||
+ self.guid='574AA64002B8E308';self.resource='Prefabs/Characters/REAPER_SpectatorCameraHelper.et'
|
||||
+ def rejected_reference(self,name,text):
|
||||
+ self.assertIn((self.guid,self.resource),list(refs.hard_resource_references(name,text)))
|
||||
+ def test_exact_comparison_only_and_every_other_reference_retained(self):
|
||||
+ all_refs=re.findall(r'\{([A-F0-9]{16})\}([^"\n]+)',self.text)
|
||||
+ expected=[pair for pair in all_refs if pair!=(self.guid,self.resource)]
|
||||
+ self.assertEqual(list(refs.hard_resource_references(self.name,self.text)),expected)
|
||||
+ self.assertIn(('37578B1666981FCE','Prefabs/Characters/Core/Character_Base.et'),expected)
|
||||
+ self.rejected_reference('addons/core/Scripts/Game/Other.c',self.text)
|
||||
+ for changed in [
|
||||
+ self.text+'\n', # even a benign source edit needs renewed audit
|
||||
+ self.text.replace('return prefab ==', 'Resource.Load(prefab); return prefab =='),
|
||||
+ self.text.replace('return prefab ==', 'return Resource.Load(').replace(refs.OPTIONAL_RESOURCE+'";',refs.OPTIONAL_RESOURCE+'");'),
|
||||
+ self.text+'\nResource.Load("'+refs.OPTIONAL_RESOURCE+'");',
|
||||
+ self.text+'\nSpawn("'+refs.OPTIONAL_RESOURCE+'");',
|
||||
+ self.text+'\nResourceName extra = "'+refs.OPTIONAL_RESOURCE+'";',
|
||||
+ self.text.replace(refs.OPTIONAL_METHOD,'/*'+refs.OPTIONAL_METHOD+'*/'),
|
||||
+ self.text.replace('CameraSlot(BaseContainer slot)','DifferentMethod(BaseContainer slot)'),
|
||||
+ self.text.replace('if (!ModsPresent()) return false;',''),
|
||||
+ ]: self.rejected_reference(self.name,changed)
|
||||
+ unknown=self.text.replace(self.guid,'574AA64002B8E309')
|
||||
+ self.assertIn(('574AA64002B8E309',self.resource),list(refs.hard_resource_references(self.name,unknown)))
|
||||
+ # The optional addon never enters either resource policy or dependency closure.
|
||||
+ value=ext.policy(ROOT)
|
||||
+ self.assertNotIn('5EB139459EBF5C16',ext.ALLOWED)
|
||||
+ self.assertFalse(ext.resource_allowed(value,set(ext.ALLOWED),self.guid,self.resource))
|
||||
+ def repository_resource_loop(self,name,text):
|
||||
+ # Execute the actual dependency-scanner loop without running the full suite.
|
||||
+ source=Path(os.environ.get('ERR_OPTIONAL_CHECK_SOURCE',TOOLS/'check.py')).read_text()
|
||||
+ tree=ast.parse(source)
|
||||
+ loops=[node for node in ast.walk(tree) if isinstance(node,ast.For) and isinstance(node.target,ast.Tuple)
|
||||
+ and [getattr(n,'id',None) for n in node.target.elts]==['g','path']]
|
||||
+ self.assertEqual(len(loops),1)
|
||||
+ code=compile(ast.fix_missing_locations(ast.Module(body=loops,type_ignores=[])),'actual_repository_resource_loop','exec')
|
||||
+ env=dict(re=re,hard_resource_references=refs.hard_resource_references,p=ROOT/name,ROOT=ROOT,s=text,
|
||||
+ resources={},owners={},vanilla=json.loads((ROOT/'docs/vanilla-resources.json').read_text()),
|
||||
+ external=ext.policy(ROOT),visibility={'core':{'core',*ext.ALLOWED}},resource_allowed=ext.resource_allowed)
|
||||
+ exec(code,env)
|
||||
+ def test_actual_repository_resource_loop(self):
|
||||
+ self.repository_resource_loop(self.name,self.text)
|
||||
+ for name,text in [(self.name,self.text+'\nResource.Load("'+refs.OPTIONAL_RESOURCE+'");'),
|
||||
+ ('addons/core/Scripts/Game/Other.c',self.text),
|
||||
+ (self.name,self.text.replace('return prefab ==','return Resource.Load(').replace(refs.OPTIONAL_RESOURCE+'";',refs.OPTIONAL_RESOURCE+'");'))]:
|
||||
+ with self.assertRaisesRegex(AssertionError,'Unresolved/mismatched'):
|
||||
+ self.repository_resource_loop(name,text)
|
||||
+ def test_actual_bundle_validator(self):
|
||||
+ path=Path(os.environ.get('ERR_OPTIONAL_BUNDLE_SOURCE',TOOLS/'source_bundle.py'))
|
||||
+ spec=importlib.util.spec_from_file_location('optional_test_source_bundle',path)
|
||||
+ bundle=importlib.util.module_from_spec(spec);spec.loader.exec_module(bundle)
|
||||
+ payload={name:(ROOT/name).read_bytes() for name in bundle.inventory(ROOT)}
|
||||
+ before=ext.policy(ROOT)
|
||||
+ bundle.validate(payload,ROOT)
|
||||
+ self.assertEqual(before,ext.policy(ROOT))
|
||||
+ for changed in [self.text+'\nResource.Load("'+refs.OPTIONAL_RESOURCE+'");',
|
||||
+ self.text+'\nSpawn("'+refs.OPTIONAL_RESOURCE+'");']:
|
||||
+ altered=dict(payload);altered[self.name]=changed.encode()
|
||||
+ with self.assertRaisesRegex(ValueError,'unresolved or nonvanilla'):
|
||||
+ bundle.validate(altered,ROOT)
|
||||
+
|
||||
if __name__=='__main__':unittest.main()
|
||||
--- a/docs/vanilla-resources.json
|
||||
+++ b/docs/vanilla-resources.json
|
||||
@@ -48,6 +48,7 @@
|
||||
"Prefabs/AI/Waypoints/AIWaypoint_Move.et": "750A8D1695BD6998",
|
||||
"Prefabs/AI/Waypoints/AIWaypoint_SearchAndDestroy.et": "B3E7B8DC2BAB8ACC",
|
||||
"Prefabs/Characters/Campaign/Final/OPFOR/USSR_Army/Regular/Campaign_USSR_Player_MortarCrew.et": "86E565387A634103",
|
||||
+ "Prefabs/Characters/Core/Character_Base.et": "37578B1666981FCE",
|
||||
"Prefabs/Characters/Factions/BLUFOR/US_Army/Character_US_Base.et": "836E7E39AAC5888B",
|
||||
"Prefabs/Characters/Factions/BLUFOR/US_Army/Character_US_HeliPilot.et": "42A502E3BB727CEB",
|
||||
"Prefabs/Characters/Factions/BLUFOR/US_Army/Character_US_Sniper.et": "0F6689B491641155",
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"approved": true,
|
||||
"complete": true,
|
||||
"review_type": "Independent read-only source/test/evidence review; no test or native execution",
|
||||
"files": {
|
||||
"tools/resource_references.py": {
|
||||
"baseline_sha256": null,
|
||||
"proposal_sha256": "2e6080227bece7213fd67e58e7a4d27aba9847e610f8c000f6f2f65b623e567c",
|
||||
"index_sha256": null,
|
||||
"index_absent": true
|
||||
},
|
||||
"tools/check.py": {
|
||||
"baseline_sha256": "d60357b1c6b0d61dfeb80148d4a6684121e468bd3a044a9adc8f76752f60a41a",
|
||||
"proposal_sha256": "fb6bf594dd6544abee60d4e172d1d28f34f223cae93678e2356156f34e653f00",
|
||||
"index_sha256": "57937780370c47833d07e9ba8b7ce61133358f339294f788a60a7ae4325ba496",
|
||||
"index_absent": false
|
||||
},
|
||||
"tools/source_bundle.py": {
|
||||
"baseline_sha256": "e8b06f9340a8d67da992373f4642385a028acebe9aa1b3752f62cab95c8fce98",
|
||||
"proposal_sha256": "5d1d0150d8009f24a950ee85501d0da8b1f69d5fcbb5a7118b08957f14658f57",
|
||||
"index_sha256": "e8b06f9340a8d67da992373f4642385a028acebe9aa1b3752f62cab95c8fce98",
|
||||
"index_absent": false
|
||||
},
|
||||
"tests/test_external_addons.py": {
|
||||
"baseline_sha256": "4e2c3fa2c92661c49ea0c492648b736bebd54f24cd244f3fe27710a0c7a487ab",
|
||||
"proposal_sha256": "4b0eb867b3aec1bca906f68168948a4e42cdc0bced0bec2856a3ba68187a6e24",
|
||||
"index_sha256": "4e2c3fa2c92661c49ea0c492648b736bebd54f24cd244f3fe27710a0c7a487ab",
|
||||
"index_absent": false
|
||||
},
|
||||
"docs/vanilla-resources.json": {
|
||||
"baseline_sha256": "588192d151f382b612ca6ce9a564193b57d4a9e7ce9a3918bf8ad2f7e877d1f4",
|
||||
"proposal_sha256": "e10f60ce74a743b4619b0c2f2cc7fefcf09a94ab3ca1cbb332f386d6fb0da387",
|
||||
"index_sha256": "30dccbe13f1737ab832bb287cdef7f5a46ae718eafb68aa13c1c13ebdd29923b",
|
||||
"index_absent": false
|
||||
}
|
||||
},
|
||||
"patch_sha256": "d02ed79ad88f21138e66a77189bbaf7130cf1e36331f47f1c3b5db026a1953c1",
|
||||
"source_manifest_sha256": "fdb25d5b1bdefc114291475dc9b68a195a3aadc55e8c7b662fc2d5a913b2b2e3",
|
||||
"test_results_sha256": "a3c9e916289b106bd0c3befbf7c675ea8f08579359b7d074538e787705aa063d",
|
||||
"findings": [
|
||||
"Exact optional file path, complete source-text SHA, exact CameraSlot method and one occurrence constrain the filtered equality literal. Every source drift fails closed and preserves all hard references.",
|
||||
"Both actual repository and source-bundle scanners consume the same helper; no dependency or external resource owner policy changed.",
|
||||
"Actual Resource.Load of vanilla Character_Base remains subject to ordinary resource checks; independently confirmed exact installed RDB path/type/little-endian GUID record, added one ordinary vanilla manifest entry.",
|
||||
"Original seven external-addon tests retained. Three new tests cover helper counterexamples, actual scanner loop and actual bundle.validate; added Load/spawn, wrong file, removed mod guard, changed method/literal all remain rejected.",
|
||||
"Owner logs show actual baseline scanners reject exact optional identity, proposal ten tests pass, initial correctly rejected unaudited Character_Base hard reference preserved."
|
||||
],
|
||||
"source_semantics": [
|
||||
"Native GameProject.GetLoadedAddons enumerates already-loaded GUIDs; optional compatibility Apply exits before resource inspection unless both selected mods are already loaded.",
|
||||
"CameraSlot reads a Prefab field and compares identity. The only actual Resource.Load uses vanilla Character_Base; optional prefab literal does not request a new load."
|
||||
],
|
||||
"limits": [
|
||||
"No native compiler or optional Reaper/RHS runtime compatibility proof.",
|
||||
"Source hash guard intentionally requires renewed review after any substantive edit; this is not a general Enforce parser or permissive optional addon allowlist."
|
||||
],
|
||||
"audited_source": {
|
||||
"path": "addons/core/Scripts/Game/ERR/00_Core/ERR_ReaperRHSCompat.c",
|
||||
"sha256": "bcdf98c05ac6cdf0c7eaa854531b02e9ee4f53fbb346ae01d58114e572e7dd4f",
|
||||
"modified": false
|
||||
},
|
||||
"runtime_dependency_closure_changed": false
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"project_path": "/tmp/erri-reaper-native/first/addons/REAPER_CORE_5EB139459EBF5C16/addon.gproj",
|
||||
"project_sha256": "9a50e425661956163ef2d74336df656a3c62ad696253a83b3f0b51b9b56d8ee3",
|
||||
"rdb_path": "/tmp/erri-reaper-native/first/addons/REAPER_CORE_5EB139459EBF5C16/resourceDatabase.rdb",
|
||||
"rdb_sha256": "ef07f7be363b3857ca217cd0520fb851ce980f34fc5f121b8350f4c84ee6c414",
|
||||
"resource_path": "Prefabs/Characters/REAPER_SpectatorCameraHelper.et",
|
||||
"resource_guid": "574AA64002B8E308",
|
||||
"matching_records": 1,
|
||||
"assets_copied": false
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
from pathlib import Path
|
||||
r=Path('/tmp/erri-optional-identity-1509');s=(r/'baseline/tests/test_external_addons.py').read_text();s=s.replace('import copy','import ast\nimport importlib.util\nimport os\nimport re\nimport copy',1);s=s.replace('import external_addons as ext',"TOOLS=Path(os.environ.get('ERR_OPTIONAL_IDENTITY_TOOLS',Path(__file__).resolve().parents[1]/'tools'))\nsys.path.insert(0,str(TOOLS))\nimport resource_references as refs\nimport external_addons as ext",1);s=s.replace("ROOT=Path(__file__).resolve().parents[1]","ROOT=Path(os.environ.get('ERR_REPO',Path(__file__).resolve().parents[1]))",1)
|
||||
new=r'''
|
||||
class OptionalIdentityTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.name=refs.OPTIONAL_FILE
|
||||
self.text=(ROOT/self.name).read_text()
|
||||
self.guid='574AA64002B8E308';self.resource='Prefabs/Characters/REAPER_SpectatorCameraHelper.et'
|
||||
def rejected_reference(self,name,text):
|
||||
self.assertIn((self.guid,self.resource),list(refs.hard_resource_references(name,text)))
|
||||
def test_exact_comparison_only_and_every_other_reference_retained(self):
|
||||
all_refs=re.findall(r'\{([A-F0-9]{16})\}([^"\n]+)',self.text)
|
||||
expected=[pair for pair in all_refs if pair!=(self.guid,self.resource)]
|
||||
self.assertEqual(list(refs.hard_resource_references(self.name,self.text)),expected)
|
||||
self.assertIn(('37578B1666981FCE','Prefabs/Characters/Core/Character_Base.et'),expected)
|
||||
self.rejected_reference('addons/core/Scripts/Game/Other.c',self.text)
|
||||
for changed in [
|
||||
self.text+'\n', # even a benign source edit needs renewed audit
|
||||
self.text.replace('return prefab ==', 'Resource.Load(prefab); return prefab =='),
|
||||
self.text.replace('return prefab ==', 'return Resource.Load(').replace(refs.OPTIONAL_RESOURCE+'";',refs.OPTIONAL_RESOURCE+'");'),
|
||||
self.text+'\nResource.Load("'+refs.OPTIONAL_RESOURCE+'");',
|
||||
self.text+'\nSpawn("'+refs.OPTIONAL_RESOURCE+'");',
|
||||
self.text+'\nResourceName extra = "'+refs.OPTIONAL_RESOURCE+'";',
|
||||
self.text.replace(refs.OPTIONAL_METHOD,'/*'+refs.OPTIONAL_METHOD+'*/'),
|
||||
self.text.replace('CameraSlot(BaseContainer slot)','DifferentMethod(BaseContainer slot)'),
|
||||
self.text.replace('if (!ModsPresent()) return false;',''),
|
||||
]: self.rejected_reference(self.name,changed)
|
||||
unknown=self.text.replace(self.guid,'574AA64002B8E309')
|
||||
self.assertIn(('574AA64002B8E309',self.resource),list(refs.hard_resource_references(self.name,unknown)))
|
||||
# The optional addon never enters either resource policy or dependency closure.
|
||||
value=ext.policy(ROOT)
|
||||
self.assertNotIn('5EB139459EBF5C16',ext.ALLOWED)
|
||||
self.assertFalse(ext.resource_allowed(value,set(ext.ALLOWED),self.guid,self.resource))
|
||||
def repository_resource_loop(self,name,text):
|
||||
# Execute the actual dependency-scanner loop without running the full suite.
|
||||
source=Path(os.environ.get('ERR_OPTIONAL_CHECK_SOURCE',TOOLS/'check.py')).read_text()
|
||||
tree=ast.parse(source)
|
||||
loops=[node for node in ast.walk(tree) if isinstance(node,ast.For) and isinstance(node.target,ast.Tuple)
|
||||
and [getattr(n,'id',None) for n in node.target.elts]==['g','path']]
|
||||
self.assertEqual(len(loops),1)
|
||||
code=compile(ast.fix_missing_locations(ast.Module(body=loops,type_ignores=[])),'actual_repository_resource_loop','exec')
|
||||
env=dict(re=re,hard_resource_references=refs.hard_resource_references,p=ROOT/name,ROOT=ROOT,s=text,
|
||||
resources={},owners={},vanilla=json.loads((ROOT/'docs/vanilla-resources.json').read_text()),
|
||||
external=ext.policy(ROOT),visibility={'core':{'core',*ext.ALLOWED}},resource_allowed=ext.resource_allowed)
|
||||
exec(code,env)
|
||||
def test_actual_repository_resource_loop(self):
|
||||
self.repository_resource_loop(self.name,self.text)
|
||||
for name,text in [(self.name,self.text+'\nResource.Load("'+refs.OPTIONAL_RESOURCE+'");'),
|
||||
('addons/core/Scripts/Game/Other.c',self.text),
|
||||
(self.name,self.text.replace('return prefab ==','return Resource.Load(').replace(refs.OPTIONAL_RESOURCE+'";',refs.OPTIONAL_RESOURCE+'");'))]:
|
||||
with self.assertRaisesRegex(AssertionError,'Unresolved/mismatched'):
|
||||
self.repository_resource_loop(name,text)
|
||||
def test_actual_bundle_validator(self):
|
||||
path=Path(os.environ.get('ERR_OPTIONAL_BUNDLE_SOURCE',TOOLS/'source_bundle.py'))
|
||||
spec=importlib.util.spec_from_file_location('optional_test_source_bundle',path)
|
||||
bundle=importlib.util.module_from_spec(spec);spec.loader.exec_module(bundle)
|
||||
payload={name:(ROOT/name).read_bytes() for name in bundle.inventory(ROOT)}
|
||||
before=ext.policy(ROOT)
|
||||
bundle.validate(payload,ROOT)
|
||||
self.assertEqual(before,ext.policy(ROOT))
|
||||
for changed in [self.text+'\nResource.Load("'+refs.OPTIONAL_RESOURCE+'");',
|
||||
self.text+'\nSpawn("'+refs.OPTIONAL_RESOURCE+'");']:
|
||||
altered=dict(payload);altered[self.name]=changed.encode()
|
||||
with self.assertRaisesRegex(ValueError,'unresolved or nonvanilla'):
|
||||
bundle.validate(altered,ROOT)
|
||||
|
||||
'''
|
||||
s=s.replace("if __name__=='__main__':unittest.main()",new+"if __name__=='__main__':unittest.main()")
|
||||
(r/'tests/test_external_addons.py').write_text(s)
|
||||
@@ -0,0 +1,5 @@
|
||||
..........
|
||||
----------------------------------------------------------------------
|
||||
Ran 10 tests in 0.235s
|
||||
|
||||
OK
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
.......EF.
|
||||
======================================================================
|
||||
ERROR: test_actual_bundle_validator (__main__.OptionalIdentityTests.test_actual_bundle_validator)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "/tmp/erri-optional-identity-1509/tests/test_external_addons.py", line 135, in test_actual_bundle_validator
|
||||
bundle.validate(payload,ROOT)
|
||||
~~~~~~~~~~~~~~~^^^^^^^^^^^^^^
|
||||
File "/tmp/erri-optional-identity-1509/tools/source_bundle.py", line 161, in validate
|
||||
raise ValueError(f'unresolved or nonvanilla resource: {name}')
|
||||
ValueError: unresolved or nonvanilla resource: addons/core/Scripts/Game/ERR/00_Core/ERR_ReaperRHSCompat.c
|
||||
|
||||
======================================================================
|
||||
FAIL: test_actual_repository_resource_loop (__main__.OptionalIdentityTests.test_actual_repository_resource_loop)
|
||||
----------------------------------------------------------------------
|
||||
Traceback (most recent call last):
|
||||
File "/tmp/erri-optional-identity-1509/tests/test_external_addons.py", line 123, in test_actual_repository_resource_loop
|
||||
self.repository_resource_loop(self.name,self.text)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/tmp/erri-optional-identity-1509/tests/test_external_addons.py", line 121, in repository_resource_loop
|
||||
exec(code,env)
|
||||
~~~~^^^^^^^^^^
|
||||
File "actual_repository_resource_loop", line 70, in <module>
|
||||
AssertionError: Unresolved/mismatched resource in /home/jakub/devel/escapistsrereintroduced/addons/core/Scripts/Game/ERR/00_Core/ERR_ReaperRHSCompat.c: 37578B1666981FCE Prefabs/Characters/Core/Character_Base.et
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 10 tests in 0.123s
|
||||
|
||||
FAILED (failures=1, errors=1)
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
{
|
||||
"Assets/Items/Equipment/Maps/Map_Paper_01/Map_Paper_01_folded.xob": "E443663E5241622A",
|
||||
"Assets/Items/Equipment/Radios/Radio_R107M/Radio_R107M_01_item.xob": "77C9FCF3FB1246E9",
|
||||
"Assets/Items/Equipment/workspaces/paper_map.agr": "83675D0B0AB1B2C3",
|
||||
"Assets/Items/Equipment/workspaces/player_map.asi": "56794534F6B8C3D7",
|
||||
"Assets/Props/Fabric/Flags/Data/Flag_1_2_SovietArmy.emat": "B47B52D9DA68905D",
|
||||
"Assets/Props/Fabric/Flags/Data/Flag_1_2_USA.emat": "610803CC3F3D6649",
|
||||
"Assets/Props/Military/AmmoBox/EquipmentBoxWooden_01/Data/EquipmentBoxWooden_Weapon_01_USSR.emat": "7D2E831AFA5CF50D",
|
||||
"Assets/Props/Military/AmmoBox/EquipmentBoxWooden_01/EquipmentBoxWooden_Weapon_01.xob": "819ED3266EE5113B",
|
||||
"Assets/Props/Military/Sandbags/Data/Sandbags_01_Burlap_MLOD.emat": "2169E8EB73E1C127",
|
||||
"Assets/Props/Military/Sandbags/Data/Sandbags_01_short_Burlap.emat": "31529E064AA7C917",
|
||||
"Assets/Props/Military/Sandbags/Sandbag_01_short.xob": "268DBDABB3C94AD7",
|
||||
"Assets/Structures/BuildingsParts/Doors/DoorFrame_door_metal_A_RIGHT_EXT_B.xob": "E3BC73BFBC7AA497",
|
||||
"Assets/Structures/Walls/Concrete/ConcreteWall_01_3m.xob": "0B96D139FEBCA006",
|
||||
"Configs/Callsigns/Callsigns_US.conf": "CB7824D572DD0D5C",
|
||||
"Configs/Callsigns/Callsigns_USSR.conf": "958043CE1648EC43",
|
||||
"Configs/EntityCatalog/US/Characters_EntityCatalog_US.conf": "B56E8B4D4B195559",
|
||||
"Configs/EntityCatalog/US/Groups_EntityCatalog_US.conf": "4E70E7C4C2C17D4A",
|
||||
"Configs/EntityCatalog/US/InventoryItems_EntityCatalog_US.conf": "5F7EC52FC40A03E2",
|
||||
"Configs/EntityCatalog/US/SupplyContainerItems_EntityCatalog_US.conf": "0BF36EFF9FFAF92B",
|
||||
"Configs/EntityCatalog/US/WeaponTripod_EntityCatalog_US.conf": "0E4B62F186F97C43",
|
||||
"Configs/EntityCatalog/USSR/Characters_EntityCatalog_USSR.conf": "3B679F1799D55F6F",
|
||||
"Configs/EntityCatalog/USSR/Groups_EntityCatalog_USSR.conf": "37D5B75AAC3E72EA",
|
||||
"Configs/EntityCatalog/USSR/InventoryItems_EntityCatalog_USSR.conf": "C53421647C3D0D2E",
|
||||
"Configs/EntityCatalog/USSR/SupplyContainerItems_EntityCatalog_USSR.conf": "B4CA6761AC935808",
|
||||
"Configs/EntityCatalog/USSR/WeaponTripod_EntityCatalog_USSR.conf": "DDF17C8C140BD1F2",
|
||||
"Configs/Factions/BLUFOR.conf": "E7B7EA4823DD81F0",
|
||||
"Configs/Factions/FIA.conf": "8053DB656DD18B14",
|
||||
"Configs/Factions/OPFOR.conf": "B122E3B10BB3404B",
|
||||
"Configs/GameOverScreen/BaseGameOverScreensConfig.conf": "651583FFFB7FC765",
|
||||
"Configs/Identities/FactionIdentity_US.conf": "B600946E9ACC17C2",
|
||||
"Configs/Identities/FactionIdentity_USSR.conf": "FBBCD73926989580",
|
||||
"Configs/Identities/Territories/FactionHomeTerritory_US.conf": "B548A5B264939A98",
|
||||
"Configs/Identities/Territories/FactionHomeTerritory_USSR.conf": "31FC78AF00523A99",
|
||||
"Configs/Map/MapPlain.conf": "A786DD4868598F15",
|
||||
"Configs/Navmesh/Navmesh_GM_Eden_Soldier.conf": "8BBC73472092902E",
|
||||
"Configs/Navmesh/Navmesh_GM_Eden_Vehicle.conf": "0228A79846FD8A97",
|
||||
"Configs/System/ActionContext/ManualCameraContext.conf": "C538807EEE48BED8",
|
||||
"Configs/System/chimeraInputCommon.conf": "795184CF9AD764DB",
|
||||
"Configs/System/chimeraMenus.conf": "C747AFB6B750CE9A",
|
||||
"Configs/Systems/MissionSystems.conf": "C50579A2EC48E8EF",
|
||||
"Prefabs/AI/Groups/Group_Base.et": "000CD338713F2B5A",
|
||||
"Prefabs/AI/SCR_AIWorld.et": "E0A05C76552E7F58",
|
||||
"Prefabs/AI/Waypoints/AIWaypoint_Cycle.et": "35BD6541CBB8AC08",
|
||||
"Prefabs/AI/Waypoints/AIWaypoint_Defend.et": "93291E72AC23930F",
|
||||
"Prefabs/AI/Waypoints/AIWaypoint_GetIn.et": "712F4795CF8B91C7",
|
||||
"Prefabs/AI/Waypoints/AIWaypoint_GetOut.et": "C40316EE26846CAB",
|
||||
"Prefabs/AI/Waypoints/AIWaypoint_Move.et": "750A8D1695BD6998",
|
||||
"Prefabs/AI/Waypoints/AIWaypoint_SearchAndDestroy.et": "B3E7B8DC2BAB8ACC",
|
||||
"Prefabs/Characters/Campaign/Final/OPFOR/USSR_Army/Regular/Campaign_USSR_Player_MortarCrew.et": "86E565387A634103",
|
||||
"Prefabs/Characters/Core/Character_Base.et": "37578B1666981FCE",
|
||||
"Prefabs/Characters/Factions/BLUFOR/US_Army/Character_US_Base.et": "836E7E39AAC5888B",
|
||||
"Prefabs/Characters/Factions/BLUFOR/US_Army/Character_US_HeliPilot.et": "42A502E3BB727CEB",
|
||||
"Prefabs/Characters/Factions/BLUFOR/US_Army/Character_US_Sniper.et": "0F6689B491641155",
|
||||
"Prefabs/Characters/Factions/BLUFOR/US_Army/Character_US_Unarmed.et": "2F912ED6E399FF47",
|
||||
"Prefabs/Characters/Factions/BLUFOR/US_Army/GreenBerets/Character_US_SF.et": "36E28C628A2F83CB",
|
||||
"Prefabs/Characters/Factions/BLUFOR/US_Army/GreenBerets/Character_US_SF_Medic.et": "9A234C5857D92187",
|
||||
"Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_AR.et": "23ADBBC31B6A3DC6",
|
||||
"Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_AT.et": "1C78331E156A3D65",
|
||||
"Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_HeliPilot.et": "A62FA97C4EC64F14",
|
||||
"Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_LAT.et": "BF643BE4ADBDFDD3",
|
||||
"Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_RTO.et": "612F43A4D5AE765F",
|
||||
"Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_Rifleman.et": "DCB41B3746FDD1BE",
|
||||
"Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_SL.et": "5436629450D8387A",
|
||||
"Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_SR.et": "333DA6244C7DA34C",
|
||||
"Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_Sharpshooter.et": "976AC400219898FA",
|
||||
"Prefabs/Characters/Factions/OPFOR/USSR_Army/Spetsnaz/Character_USSR_SF.et": "2DB452B3EC386B92",
|
||||
"Prefabs/Characters/Factions/OPFOR/USSR_Army/Spetsnaz/Character_USSR_SF_Medic.et": "8CA70597606992EC",
|
||||
"Prefabs/Characters/Footwear/CombatBoots_US_01.et": "DAAFD15478BDE1C3",
|
||||
"Prefabs/Characters/HeadGear/Hat_Patrol_US_01/Hat_Patrol_US_01.et": "F545C1BE7C99954A",
|
||||
"Prefabs/Characters/HeadGear/Helmet_PASGT_01/Helmet_PASGT_01_base.et": "8A2B2A544F3ED831",
|
||||
"Prefabs/Characters/Uniforms/Jacket_US_BDU_rolledup.et": "3CCA7A9BB4FD3197",
|
||||
"Prefabs/Characters/Uniforms/Pants_US_BDU.et": "604BB72BE8E023C2",
|
||||
"Prefabs/Decals/Dirt/Decal_Dirt_Patch_03.et": "4AD6EB80A8B1FA3A",
|
||||
"Prefabs/Groups/BLUFOR/Group_US_FireTeam.et": "84E5BBAB25EA23E5",
|
||||
"Prefabs/Groups/INDFOR/Group_FIA_FireTeam.et": "5BEA04939D148B1D",
|
||||
"Prefabs/Groups/OPFOR/Group_USSR_Base.et": "8DE0C0830FE0C33D",
|
||||
"Prefabs/Groups/OPFOR/Group_USSR_RifleSquad.et": "E552DABF3636C2AD",
|
||||
"Prefabs/Items/Core/Item_Base.et": "C95E11C60810F432",
|
||||
"Prefabs/Items/Equipment/Backpacks/Backpack_Kolobok.et": "41A9C55B61F375F0",
|
||||
"Prefabs/Items/Equipment/Binoculars/Binoculars_B8/Binoculars_B8.et": "243948B23D90BECB",
|
||||
"Prefabs/Items/Equipment/Kits/MedicalKit_01/MedicalKit_01_US.et": "AE578EEA4244D41F",
|
||||
"Prefabs/Items/Equipment/Kits/MedicalKit_01/MedicalKit_01_USSR.et": "21EF98BFC1EB3793",
|
||||
"Prefabs/Items/Equipment/Kits/RepairKit_01/RepairKit_01_wrench.et": "33B2DFDCD0EBA3DB",
|
||||
"Prefabs/Items/Equipment/Maps/Map_Paper_01/PaperMap_01_folded.et": "13772C903CB5E4F7",
|
||||
"Prefabs/Items/Equipment/Radios/Radio_ANPRC77.et": "9B6B61BB3FE3DFB0",
|
||||
"Prefabs/Items/Equipment/Radios/Radio_R107M.et": "54C68E438DD34265",
|
||||
"Prefabs/Items/Equipment/Radios/Radio_R148.et": "E1A5D4B878AA8980",
|
||||
"Prefabs/Items/Equipment/Watches/Watch_SandY184A.et": "78ED4FEF62BBA728",
|
||||
"Prefabs/Items/Fuel/Jerrycan_01/Jerrycan_01_item.et": "12D5AD21E383B768",
|
||||
"Prefabs/Items/Medicine/FieldDressing_01/FieldDressing_USSR_01.et": "C3F1FA1E2EC2B345",
|
||||
"Prefabs/Items/Medicine/FieldDressing_01/FieldDressing_US_01.et": "A81F501D3EF6F38E",
|
||||
"Prefabs/Items/Medicine/MorphineInjection_01/MorphineInjection_01.et": "0D9A5DCF89AE7AA9",
|
||||
"Prefabs/Items/Medicine/SalineBag_01/SalineBag_USSR_01.et": "527D7C5D2E476BDC",
|
||||
"Prefabs/Items/Medicine/SalineBag_01/SalineBag_US_01.et": "00E36F41CA310E2A",
|
||||
"Prefabs/Items/Medicine/Tourniquet_01/Tourniquet_US_01.et": "D70216B1B2889129",
|
||||
"Prefabs/Items/Misc/IntelligenceFolder_E_01/IntelligenceFolder_E_01.et": "6D56FED1E55A8F84",
|
||||
"Prefabs/MP/Managers/Factions/FactionManager_Base.et": "A242612865F2A48E",
|
||||
"Prefabs/MP/Managers/Factions/FactionManager_USxUSSR.et": "589540B35EBA8CDC",
|
||||
"Prefabs/MP/Managers/Loadouts/LoadoutManager_USxUSSR.et": "97EF4C1A41F63DDB",
|
||||
"Prefabs/MP/Modes/GameMode_Base.et": "0F307326459A1395",
|
||||
"Prefabs/MP/ScriptedChatEntity.et": "F69BC912AC8236F9",
|
||||
"Prefabs/Props/EmptyStorages/USSR_AmmoBox_empty.et": "EBBC859CCD94D96D",
|
||||
"Prefabs/Props/Furniture/Table_01.et": "53506DCB398C7EBE",
|
||||
"Prefabs/Props/Military/Antennas/Antenna_FIA_02/Antenna_FIA_02_base.et": "B3949F6D215A9F78",
|
||||
"Prefabs/Props/Military/Sandbags/Sandbag_01_short_burlap.et": "CFFEB23FBEA00322",
|
||||
"Prefabs/Structures/BuildingParts/Doors/DoorSet_Base.et": "87CADB5ADC989993",
|
||||
"Prefabs/Structures/BuildingParts/Doors/Door_MetalGate_01_Short_LEFT_EXT_ST_B.et": "34B08027DBDE322A",
|
||||
"Prefabs/Structures/BuildingParts/Doors/Door_Metal_A_RIGHT_EXT_COV_B.et": "67F17696FF278AE0",
|
||||
"Prefabs/Structures/Military/Camps/TentSmallUS_01/TentSmallUS_01.et": "01AE5FD77A9A4C21",
|
||||
"Prefabs/Structures/Military/Camps/TentUSSR_01/TentUSSR_01_base.et": "BE5D5CFA90224646",
|
||||
"Prefabs/Structures/Military/Camps/TentUS_01/TentUSMedical_01.et": "F8427C3EFC52644E",
|
||||
"Prefabs/Structures/Walls/BarbedWire/BarbedTape_01/BarbedTape_01_Long_noStake.et": "46904AF5D473FB75",
|
||||
"Prefabs/Structures/Walls/BarbedWire/BarbedTape_01/BarbedTape_01_Short_noStake.et": "CAE1588B6265A2AB",
|
||||
"Prefabs/Structures/Walls/Concrete/ConcreteWall_01/ConcreteWall_01_3m.et": "60E5729BEA18F875",
|
||||
"Prefabs/Systems/Radio/RadioManager.et": "B8E09FAB91C4ECCD",
|
||||
"Prefabs/Tasks/BaseTask.et": "1D0F815858EE24AD",
|
||||
"Prefabs/Vehicles/Helicopters/Mi8MT/Mi8MT_armed.et": "7BD282AF716ED639",
|
||||
"Prefabs/Vehicles/Helicopters/Mi8MT/Mi8MT_unarmed_transport.et": "DF5CCB7C0FF049F4",
|
||||
"Prefabs/Vehicles/Wheeled/UAZ469/UAZ469.et": "259EE7B78C51B624",
|
||||
"Prefabs/Vehicles/Wheeled/UAZ469/UAZ469_PKM.et": "0B4DEA8078B78A9B",
|
||||
"Prefabs/Vehicles/Wheeled/UAZ469/VehParts/Seats/UAZ469_seats_rear.et": "780AAF0A51AEE61A",
|
||||
"Prefabs/Vehicles/Wheeled/Ural4320/Ural4320_ammo.et": "3336BE330C4F355B",
|
||||
"Prefabs/Vehicles/Wheeled/Ural4320/Ural4320_transport.et": "16C1F16C9B053801",
|
||||
"Prefabs/Weapons/Ammo/Ammo_Shell_82mm_HE_O832DU.et": "98EC9C526AFBA282",
|
||||
"Prefabs/Weapons/Attachments/Optics/Optic_4x20/Optic_4x20.et": "BD496EE1B40DC510",
|
||||
"Prefabs/Weapons/Attachments/Optics/Optic_ARTII/Optic_ARTII.et": "D2018EDB1BBF4C88",
|
||||
"Prefabs/Weapons/Attachments/Optics/Optic_PSO1/Optic_PSO1.et": "C850A33226B8F9C1",
|
||||
"Prefabs/Weapons/Core/VehiclePeriscope_DummyWeapon_Base.et": "7E1DD1CE4D6A23F4",
|
||||
"Prefabs/Weapons/Explosives/Mine_PMN4/Mine_PMN4.et": "B05A816C0BF50802",
|
||||
"Prefabs/Weapons/Handguns/PM/Handgun_PM.et": "C0F7DD85A86B2900",
|
||||
"Prefabs/Weapons/Magazines/Magazine_545x39_AK_30rnd_Ball.et": "BBB50A815A2F916B",
|
||||
"Prefabs/Weapons/Magazines/Magazine_762x51_M14_20rnd_SpecialBall.et": "627255315038152A",
|
||||
"Prefabs/Weapons/Magazines/Magazine_762x54_SVD_10rnd_Sniper.et": "9CCB46C6EE632C1A",
|
||||
"Prefabs/Weapons/Magazines/Magazine_9x18_PM_8rnd_Ball.et": "8B853CDD11BA916E",
|
||||
"Prefabs/Weapons/Mortars/2B14/Mortar_2B14.et": "D1FFE458E8AC4BDB",
|
||||
"Prefabs/Weapons/Rifles/AK74/Rifle_AK74.et": "FA5C25BF66A53DCF",
|
||||
"Prefabs/World/Game/PerceptionManager.et": "028DAEAD63E056BE",
|
||||
"Sounds/Items/_SharedData/PickUp/Items_PickUp_Map.acp": "13F8D0DE67678118",
|
||||
"Sounds/Vehicles/Wheeled/UAZ469/Vehicles_UAZ469_Horn.acp": "7E64D37BE3E1F3FA",
|
||||
"UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt": "3E7733BAC8C831F6",
|
||||
"UI/Textures/DeployMenu/Loadout-BG/Loadout_BG_USSR.imageset": "21533F2089005056",
|
||||
"UI/Textures/DeployMenu/Loadout-BG/Loadout_US_BG.imageset": "F8AC305446D5D480",
|
||||
"UI/Textures/Editor/EditableEntities/Factions/EditableEntity_Faction_USA.edds": "EB7F65DBC9392557",
|
||||
"UI/Textures/Editor/EditableEntities/Factions/EditableEntity_Faction_USSR.edds": "40B12B0DF911B856",
|
||||
"UI/Textures/Flags/US-flag-base-3it.edds": "46FB2FB2C2125A3C",
|
||||
"UI/Textures/Flags/USSR-flag-base-3it.edds": "50824EB9F2C215AB",
|
||||
"UI/Textures/Icons/icons_mapMarkersUI-glow.imageset": "67B3A6DC2D712B52",
|
||||
"UI/Textures/Icons/icons_mapMarkersUI.imageset": "E23427CAC80DA8B7",
|
||||
"UI/Textures/Icons/icons_wrapperUI-glow.imageset": "00FE3DBDFD15227B",
|
||||
"UI/Textures/Icons/icons_wrapperUI.imageset": "3262679C50EF4F01",
|
||||
"UI/layouts/HUD/GameOver/EndScreen/EndScreenContent_NoImage.layout": "C4507D07F3C54831",
|
||||
"UI/layouts/Menus/PauseMenu/PauseMenuButton.layout": "9ECCD201BCF07E95",
|
||||
"UI/layouts/Task/TaskListEntry.layout": "B71975032150BAFB",
|
||||
"UI/layouts/Task/TaskListEntryDescription.layout": "552EB1921B5C548C",
|
||||
"UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout": "75C912A1C89BE6C2",
|
||||
"UI/layouts/WidgetLibrary/ComboBox/WLib_ComboBox.layout": "4B5AE6E64037FFB4",
|
||||
"UI/layouts/WidgetLibrary/EditBox/WLib_EditBox.layout": "0022F0B45ADBC5AC",
|
||||
"system/textures/defWhite.edds": "A64A8C63E0FBAE87",
|
||||
"worlds/Eden/Eden.ent": "853E92315D1D9EFE",
|
||||
"worlds/MP/Navmeshes/LowResEden.nmn": "5E19E60F26327356"
|
||||
}
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Exercise exact dependency closure, resource ownership and isolated profile inputs."""
|
||||
import ast
|
||||
import importlib.util
|
||||
import os
|
||||
import re
|
||||
import copy
|
||||
import hashlib
|
||||
import json
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
sys.path.insert(0,str(Path(__file__).resolve().parents[1]/'tools'))
|
||||
TOOLS=Path(os.environ.get('ERR_OPTIONAL_IDENTITY_TOOLS',Path(__file__).resolve().parents[1]/'tools'))
|
||||
sys.path.insert(0,str(TOOLS))
|
||||
import resource_references as refs
|
||||
import external_addons as ext
|
||||
ROOT=Path(os.environ.get('ERR_REPO',Path(__file__).resolve().parents[1]))
|
||||
|
||||
class ExternalAddonsTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.temp=tempfile.TemporaryDirectory();self.addCleanup(self.temp.cleanup)
|
||||
self.home=Path(self.temp.name);self.source=self.home/'installed';self.source.mkdir()
|
||||
self.addons=self.home/'profile'/'addons';self.addons.mkdir(parents=True)
|
||||
self.cache=self.home/'profile'/'cache.json';self.value=ext.policy(ROOT)
|
||||
for guid,deps in ext.ALLOWED.items():
|
||||
folder=self.source/guid;folder.mkdir()
|
||||
manifest='GameProject { GUID "'+guid+'" Dependencies { '+' '.join('"'+d+'"' for d in sorted(deps))+' } }\n'
|
||||
(folder/'addon.gproj').write_text(manifest)
|
||||
self.value['addons'][guid]['project_sha256']=hashlib.sha256(manifest.encode()).hexdigest()
|
||||
data=b'RDB synthetic fixture\0'
|
||||
for path,entry in self.value['resources'].items():
|
||||
if entry['addon']==guid:data+=path.encode()+b'\0\x06\0\0\0\0\0'+bytes.fromhex(entry['guid'])[::-1]
|
||||
(folder/'resourceDatabase.rdb').write_bytes(data);(folder/'data.pak').write_bytes(b'fixture '+guid.encode())
|
||||
def test_resource_identity_requires_visible_owner(self):
|
||||
for path,item in self.value['resources'].items():
|
||||
self.assertTrue(ext.resource_allowed(self.value,{item['addon']},item['guid'],path))
|
||||
self.assertFalse(ext.resource_allowed(self.value,{'core'},item['guid'],path))
|
||||
self.assertFalse(ext.resource_allowed(self.value,{item['addon']},'0000000000000000',path))
|
||||
self.assertEqual(ext.direct_for('core'),set(ext.DIRECT));self.assertEqual(ext.direct_for('chat'),set())
|
||||
def test_policy_rejects_original_transitive_dependency(self):
|
||||
root=self.home/'root';(root/'docs').mkdir(parents=True)
|
||||
value=copy.deepcopy(self.value);value['addons'][ext.DIRECT[0]]['dependencies'].append('5F16D7E4A1CBE075')
|
||||
(root/'docs/external-addons.json').write_text(json.dumps(value))
|
||||
with self.assertRaisesRegex(ValueError,'transitive'):ext.policy(root)
|
||||
def test_only_exact_authorized_closure_is_exposed_and_hashed(self):
|
||||
unrelated=self.source/'original';unrelated.mkdir();(unrelated/'addon.gproj').write_text('GameProject { GUID "5F16D7E4A1CBE075" }')
|
||||
records=ext.prepare_profile(self.addons,self.source,self.value,self.cache)
|
||||
self.assertEqual(set(records),set(ext.ALLOWED))
|
||||
self.assertEqual({p.name for p in self.addons.iterdir()},{'ERRI_'+g for g in ext.ALLOWED})
|
||||
self.assertTrue(all(p.is_symlink() for p in self.addons.iterdir()))
|
||||
self.assertTrue(ext.verify_profile(records,self.source,self.value,self.cache,self.addons))
|
||||
self.assertEqual(ext.prepare_profile(self.addons,self.source,self.value,self.cache),records)
|
||||
(self.source/ext.DIRECT[0]/'data.pak').write_bytes(b'mutated runtime')
|
||||
self.assertFalse(ext.verify_profile(records,self.source,self.value,self.cache,self.addons))
|
||||
def test_missing_and_duplicate_identity_fail(self):
|
||||
guid=ext.DIRECT[0];shutil.copytree(self.source/guid,self.source/'duplicate')
|
||||
with self.assertRaisesRegex(ValueError,'Duplicate'):ext.installed(self.source,self.value)
|
||||
shutil.rmtree(self.source/'duplicate');shutil.rmtree(self.source/guid)
|
||||
with self.assertRaisesRegex(ValueError,'Missing installed'):ext.installed(self.source,self.value)
|
||||
def test_manifest_and_database_mutations_fail(self):
|
||||
guid=ext.DIRECT[0];manifest=self.source/guid/'addon.gproj';old=manifest.read_text();manifest.write_text(old+'// changed')
|
||||
with self.assertRaisesRegex(ValueError,'manifest changed'):ext.installed(self.source,self.value)
|
||||
manifest.write_text(old)
|
||||
resource=next(iter(self.value['resources'].values()));(self.source/resource['addon']/'resourceDatabase.rdb').write_bytes(b'wrong GUID')
|
||||
with self.assertRaisesRegex(ValueError,'resource identity'):ext.installed(self.source,self.value)
|
||||
def test_unrelated_profile_addon_and_wrong_link_fail(self):
|
||||
(self.addons/'original').mkdir()
|
||||
with self.assertRaisesRegex(ValueError,'Unrelated'):ext.prepare_profile(self.addons,self.source,self.value,self.cache)
|
||||
(self.addons/'original').rmdir();guid=ext.DIRECT[0]
|
||||
(self.addons/('ERRI_'+guid)).symlink_to(self.source/ext.DIRECT[1],target_is_directory=True)
|
||||
with self.assertRaisesRegex(ValueError,'Unexpected private'):ext.prepare_profile(self.addons,self.source,self.value,self.cache)
|
||||
def test_symlinked_runtime_file_fails(self):
|
||||
pak=self.source/ext.DIRECT[0]/'data.pak';pak.unlink();pak.symlink_to(self.source/ext.DIRECT[1]/'data.pak')
|
||||
with self.assertRaisesRegex(ValueError,'regular file'):ext.installed(self.source,self.value)
|
||||
|
||||
|
||||
class OptionalIdentityTests(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.name=refs.OPTIONAL_FILE
|
||||
self.text=(ROOT/self.name).read_text()
|
||||
self.guid='574AA64002B8E308';self.resource='Prefabs/Characters/REAPER_SpectatorCameraHelper.et'
|
||||
def rejected_reference(self,name,text):
|
||||
self.assertIn((self.guid,self.resource),list(refs.hard_resource_references(name,text)))
|
||||
def test_exact_comparison_only_and_every_other_reference_retained(self):
|
||||
all_refs=re.findall(r'\{([A-F0-9]{16})\}([^"\n]+)',self.text)
|
||||
expected=[pair for pair in all_refs if pair!=(self.guid,self.resource)]
|
||||
self.assertEqual(list(refs.hard_resource_references(self.name,self.text)),expected)
|
||||
self.assertIn(('37578B1666981FCE','Prefabs/Characters/Core/Character_Base.et'),expected)
|
||||
self.rejected_reference('addons/core/Scripts/Game/Other.c',self.text)
|
||||
for changed in [
|
||||
self.text+'\n', # even a benign source edit needs renewed audit
|
||||
self.text.replace('return prefab ==', 'Resource.Load(prefab); return prefab =='),
|
||||
self.text.replace('return prefab ==', 'return Resource.Load(').replace(refs.OPTIONAL_RESOURCE+'";',refs.OPTIONAL_RESOURCE+'");'),
|
||||
self.text+'\nResource.Load("'+refs.OPTIONAL_RESOURCE+'");',
|
||||
self.text+'\nSpawn("'+refs.OPTIONAL_RESOURCE+'");',
|
||||
self.text+'\nResourceName extra = "'+refs.OPTIONAL_RESOURCE+'";',
|
||||
self.text.replace(refs.OPTIONAL_METHOD,'/*'+refs.OPTIONAL_METHOD+'*/'),
|
||||
self.text.replace('CameraSlot(BaseContainer slot)','DifferentMethod(BaseContainer slot)'),
|
||||
self.text.replace('if (!ModsPresent()) return false;',''),
|
||||
]: self.rejected_reference(self.name,changed)
|
||||
unknown=self.text.replace(self.guid,'574AA64002B8E309')
|
||||
self.assertIn(('574AA64002B8E309',self.resource),list(refs.hard_resource_references(self.name,unknown)))
|
||||
# The optional addon never enters either resource policy or dependency closure.
|
||||
value=ext.policy(ROOT)
|
||||
self.assertNotIn('5EB139459EBF5C16',ext.ALLOWED)
|
||||
self.assertFalse(ext.resource_allowed(value,set(ext.ALLOWED),self.guid,self.resource))
|
||||
def repository_resource_loop(self,name,text):
|
||||
# Execute the actual dependency-scanner loop without running the full suite.
|
||||
source=Path(os.environ.get('ERR_OPTIONAL_CHECK_SOURCE',TOOLS/'check.py')).read_text()
|
||||
tree=ast.parse(source)
|
||||
loops=[node for node in ast.walk(tree) if isinstance(node,ast.For) and isinstance(node.target,ast.Tuple)
|
||||
and [getattr(n,'id',None) for n in node.target.elts]==['g','path']]
|
||||
self.assertEqual(len(loops),1)
|
||||
code=compile(ast.fix_missing_locations(ast.Module(body=loops,type_ignores=[])),'actual_repository_resource_loop','exec')
|
||||
env=dict(re=re,hard_resource_references=refs.hard_resource_references,p=ROOT/name,ROOT=ROOT,s=text,
|
||||
resources={},owners={},vanilla=json.loads((ROOT/'docs/vanilla-resources.json').read_text()),
|
||||
external=ext.policy(ROOT),visibility={'core':{'core',*ext.ALLOWED}},resource_allowed=ext.resource_allowed)
|
||||
exec(code,env)
|
||||
def test_actual_repository_resource_loop(self):
|
||||
self.repository_resource_loop(self.name,self.text)
|
||||
for name,text in [(self.name,self.text+'\nResource.Load("'+refs.OPTIONAL_RESOURCE+'");'),
|
||||
('addons/core/Scripts/Game/Other.c',self.text),
|
||||
(self.name,self.text.replace('return prefab ==','return Resource.Load(').replace(refs.OPTIONAL_RESOURCE+'";',refs.OPTIONAL_RESOURCE+'");'))]:
|
||||
with self.assertRaisesRegex(AssertionError,'Unresolved/mismatched'):
|
||||
self.repository_resource_loop(name,text)
|
||||
def test_actual_bundle_validator(self):
|
||||
path=Path(os.environ.get('ERR_OPTIONAL_BUNDLE_SOURCE',TOOLS/'source_bundle.py'))
|
||||
spec=importlib.util.spec_from_file_location('optional_test_source_bundle',path)
|
||||
bundle=importlib.util.module_from_spec(spec);spec.loader.exec_module(bundle)
|
||||
payload={name:(ROOT/name).read_bytes() for name in bundle.inventory(ROOT)}
|
||||
before=ext.policy(ROOT)
|
||||
bundle.validate(payload,ROOT)
|
||||
self.assertEqual(before,ext.policy(ROOT))
|
||||
for changed in [self.text+'\nResource.Load("'+refs.OPTIONAL_RESOURCE+'");',
|
||||
self.text+'\nSpawn("'+refs.OPTIONAL_RESOURCE+'");']:
|
||||
altered=dict(payload);altered[self.name]=changed.encode()
|
||||
with self.assertRaisesRegex(ValueError,'unresolved or nonvanilla'):
|
||||
bundle.validate(altered,ROOT)
|
||||
|
||||
if __name__=='__main__':unittest.main()
|
||||
+94
File diff suppressed because one or more lines are too long
+31
@@ -0,0 +1,31 @@
|
||||
"""Hard resource references, with one fail-closed audited optional identity test.
|
||||
|
||||
This is not a general Enforce parser or a new external dependency allowlist.
|
||||
Changing any byte of the audited source requires reviewing this exception again.
|
||||
"""
|
||||
import hashlib
|
||||
import re
|
||||
|
||||
OPTIONAL_FILE = 'addons/core/Scripts/Game/ERR/00_Core/ERR_ReaperRHSCompat.c'
|
||||
OPTIONAL_SHA256 = 'bcdf98c05ac6cdf0c7eaa854531b02e9ee4f53fbb346ae01d58114e572e7dd4f'
|
||||
OPTIONAL_RESOURCE = '{574AA64002B8E308}Prefabs/Characters/REAPER_SpectatorCameraHelper.et'
|
||||
OPTIONAL_METHOD = ''' protected static bool CameraSlot(BaseContainer slot)
|
||||
{
|
||||
if (!slot || slot.GetName() != "SpectatorCameraHelper") return false;
|
||||
ResourceName prefab;
|
||||
if (!slot.Get("Prefab", prefab)) return false;
|
||||
return prefab == "{574AA64002B8E308}Prefabs/Characters/REAPER_SpectatorCameraHelper.et";
|
||||
}'''
|
||||
|
||||
|
||||
def hard_resource_references(relative_path, text):
|
||||
"""Exclude only the pinned comparison occurrence; keep all other checks."""
|
||||
identity_offset = -1
|
||||
if (str(relative_path) == OPTIONAL_FILE
|
||||
and hashlib.sha256(text.encode('utf-8')).hexdigest() == OPTIONAL_SHA256
|
||||
and text.count(OPTIONAL_METHOD) == 1
|
||||
and text.count(OPTIONAL_RESOURCE) == 1):
|
||||
identity_offset = text.index(OPTIONAL_METHOD) + OPTIONAL_METHOD.index(OPTIONAL_RESOURCE)
|
||||
for match in re.finditer(r'\{([A-F0-9]{16})\}([^"\n]+)', text):
|
||||
if match.start() != identity_offset:
|
||||
yield match.groups()
|
||||
+244
@@ -0,0 +1,244 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Preview or write a deterministic DEVELOPMENT SOURCE BUNDLE; never build/publish."""
|
||||
import argparse
|
||||
import hashlib
|
||||
import io
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path, PurePosixPath
|
||||
import re
|
||||
import stat
|
||||
import tempfile
|
||||
import zipfile
|
||||
import sys
|
||||
|
||||
sys.dont_write_bytecode = True
|
||||
|
||||
from source_manifest import addon_manifest
|
||||
from project_schema import parse_project
|
||||
from resource_references import hard_resource_references
|
||||
from external_addons import policy as external_policy, direct_for, resource_allowed, ALLOWED
|
||||
from release_check import audit, read_json, evidence_path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
BASE = '58D0FB3206B6F859'
|
||||
PROJECTS = {'core': ('ERR_Core', '2528466DE220D91C', ())}
|
||||
|
||||
DIRECTORIES = {'Scripts', 'Prefabs', 'Configs', 'Missions', 'Worlds', 'UI', 'Materials', 'AI'}
|
||||
SUFFIXES = {'.c', '.et', '.conf', '.ent', '.layer', '.layout', '.emat', '.bt', '.meta', '.gproj'}
|
||||
EXCLUDED = {'.git', '.build', '.local', '__pycache__', 'profiles', 'profile', 'cache',
|
||||
'runtime', 'evidence', 'vendor', 'vanilla', 'original', 'node_modules', '.agents', '.codex'}
|
||||
README = '''# DEVELOPMENT SOURCE BUNDLE — Co10 Escape Reintroduced
|
||||
|
||||
Author: Jakub Jim Žáček.
|
||||
|
||||
This ZIP contains the single Co10 Escape Reintroduced addon, with Core, AI,
|
||||
Intel, Map and Chat script folders. It is NOT a native .pak or a published mod.
|
||||
Third-party assets are not redistributed.
|
||||
|
||||
Extract into a NEW development folder and register addons/core/addon.gproj in
|
||||
Workbench. Install and register the RHS/WCS dependencies in EXTERNAL-ADDONS.json.
|
||||
Open addons/core/addon.gproj and use Missions/ERR_Everon.conf.
|
||||
|
||||
Scenario: {C1E20667DCE324ED}Missions/ERR_Everon.conf
|
||||
Use the installed engine's normal project/scenario workflow. This archive has not
|
||||
been compiled by its bundler; no native caches or binaries are included.
|
||||
|
||||
Target: Everon, up to 12 players. The mod requires the listed external addons. This remains development source.
|
||||
Manual prison/scavenging/radio/extraction play, remote joins/reconnects and
|
||||
ownership, twelve connected players, aircraft support, repeated companion cleanup,
|
||||
matched-workload FPS improvement and release qualification require separate
|
||||
source-bound validation. Existing scripted fixtures are not those acceptances.
|
||||
WORKBENCH-only probes are source, not proof of a test run or normal gameplay.
|
||||
|
||||
BUNDLE-MANIFEST.json lists each payload file's SHA-256 and project dependencies.
|
||||
Verify extracted bytes against it before editing. The manifest excludes its own
|
||||
hash to avoid self-reference. These hashes identify bytes, not authenticity,
|
||||
license grants or provenance proof. Source review remains required before sharing.
|
||||
Evidence, acceptance records, runtime profiles and test tools are intentionally
|
||||
absent; consult the maintained repository for current status and retained logs.
|
||||
Even --mode release only adds the existing repository qualification audit before
|
||||
this same development-source handoff; it does not build/publish a game release.
|
||||
'''
|
||||
|
||||
|
||||
def canonical(name):
|
||||
p = PurePosixPath(name)
|
||||
if (not name or p.is_absolute() or p.as_posix() != name or '\\' in name
|
||||
or ':' in name or any(ord(c) < 32 for c in name)
|
||||
or any(part in {'.', '..'} or part.endswith((' ', '.')) for part in p.parts)):
|
||||
raise ValueError(f'unsafe bundle path: {name!r}')
|
||||
return p
|
||||
|
||||
|
||||
def inventory(root):
|
||||
"""Reuse the evidence inventory; impose a narrower reviewed handoff schema."""
|
||||
# Preflight directories without following links, including otherwise excluded
|
||||
# entries themselves. Excluded trees are pruned from this preflight and
|
||||
# excluded from the payload; the shared source manifest may still hash them.
|
||||
addons = root / 'addons'
|
||||
if addons.is_symlink() or not addons.is_dir():
|
||||
raise ValueError('addons must be a real directory')
|
||||
for base, dirs, files in os.walk(addons, followlinks=False):
|
||||
for name in list(dirs) + files:
|
||||
path = Path(base) / name
|
||||
if path.is_symlink():
|
||||
raise ValueError(f'symlink refused: {path.relative_to(root)}')
|
||||
if not path.is_dir() and not stat.S_ISREG(path.lstat().st_mode):
|
||||
raise ValueError(f'nonregular addon entry: {path.relative_to(root)}')
|
||||
dirs[:] = [d for d in dirs if d.lower() not in EXCLUDED]
|
||||
original = addon_manifest(root)
|
||||
result = {}
|
||||
folded = set()
|
||||
for name, digest in original.items():
|
||||
parts = canonical(name).parts
|
||||
if any(part.lower() in EXCLUDED for part in parts):
|
||||
continue
|
||||
if any(part.startswith('.') for part in parts):
|
||||
raise ValueError(f'unreviewed hidden addon content: {name}')
|
||||
if len(parts) < 3 or parts[1] not in PROJECTS:
|
||||
raise ValueError(f'unknown addon project: {name}')
|
||||
path = root / name
|
||||
if not stat.S_ISREG(path.lstat().st_mode):
|
||||
raise ValueError(f'nonregular addon file: {name}')
|
||||
if name.casefold() in folded:
|
||||
raise ValueError(f'case-insensitive path collision: {name}')
|
||||
folded.add(name.casefold())
|
||||
if parts[2] == 'addon.gproj' and len(parts) == 3:
|
||||
pass
|
||||
elif len(parts) < 4 or parts[2] not in DIRECTORIES or path.suffix not in SUFFIXES - {'.gproj'}:
|
||||
raise ValueError(f'unreviewed addon source/resource format: {name}')
|
||||
result[name] = digest
|
||||
return result
|
||||
|
||||
|
||||
def validate(payload, root):
|
||||
projects = {}
|
||||
external = external_policy(root)
|
||||
own_ids = read_json(evidence_path(root, 'docs/addons.json'))
|
||||
if own_ids != {name: item[1] for name, item in PROJECTS.items()}:
|
||||
raise ValueError('successor identity catalog differs from the single owned project')
|
||||
for name, (identity, guid, deps) in PROJECTS.items():
|
||||
text = payload.get(f'addons/{name}/addon.gproj', b'').decode('utf-8')
|
||||
match = parse_project(text, allow_core_menu=name == 'core')
|
||||
expected = {BASE, *(PROJECTS[d][1] for d in deps), *direct_for(name)}
|
||||
found = re.findall(r'"([A-F0-9]{16})"', match[4]) if match else []
|
||||
if not match or match[1] != identity or match[2] != guid or set(found) != expected or len(found) != len(expected):
|
||||
raise ValueError(f'identity/dependency closure mismatch: {name}')
|
||||
projects[name] = {'id': identity, 'guid': guid, 'dependencies': sorted(found)}
|
||||
resources = {}
|
||||
for name, data in payload.items():
|
||||
if not name.endswith('.meta'):
|
||||
continue
|
||||
m = re.search(r'Name "\{([A-F0-9]{16})\}([^"\n]+)"', data.decode('utf-8'))
|
||||
owner = name.split('/')[1]
|
||||
if not m or f'addons/{owner}/{m[2]}.meta' != name or name[:-5] not in payload:
|
||||
raise ValueError(f'mismatched/missing resource metadata: {name}')
|
||||
if m[1] in resources or m[1] in own_ids.values() or m[1] == BASE:
|
||||
raise ValueError(f'duplicate resource identity: {name}')
|
||||
resources[m[1]] = (m[2], owner)
|
||||
vanilla = read_json(evidence_path(root, 'docs/vanilla-resources.json'))
|
||||
if set(resources) & set(vanilla.values()):
|
||||
raise ValueError('successor resource reuses a vanilla identity')
|
||||
for name, data in payload.items():
|
||||
suffix = PurePosixPath(name).suffix
|
||||
if suffix == '.meta':
|
||||
continue
|
||||
text = data.decode('utf-8') # Current reviewed handoff contains text assets only.
|
||||
if re.search(r'\b(?:ESCT\w*|SCRTC_\w+|SCRT_\w+|EAI_\w+)\b', text):
|
||||
raise ValueError(f'original ecosystem dependency: {name}')
|
||||
if suffix not in {'.c', '.layer', '.gproj'} and name + '.meta' not in payload:
|
||||
raise ValueError(f'resource lacks successor metadata: {name}')
|
||||
owner = name.split('/')[1]
|
||||
visible = {owner, *PROJECTS[owner][2]}
|
||||
if 'core' in visible: visible.update(ALLOWED)
|
||||
for guid, resource in hard_resource_references(name, text):
|
||||
if guid in resources:
|
||||
path, target = resources[guid]
|
||||
if path != resource or target not in visible:
|
||||
raise ValueError(f'resource outside project dependency closure: {name}')
|
||||
elif vanilla.get(resource) != guid and not resource_allowed(external,visible,guid,resource):
|
||||
raise ValueError(f'unresolved or nonvanilla resource: {name}')
|
||||
return projects
|
||||
|
||||
|
||||
def build(root=ROOT, mode='development'):
|
||||
root = Path(root).resolve()
|
||||
if mode not in {'development', 'release'}:
|
||||
raise ValueError('unknown bundle mode')
|
||||
if mode == 'release':
|
||||
blockers = audit(root)
|
||||
if blockers:
|
||||
raise ValueError('Not release-qualified:\n - ' + '\n - '.join(blockers))
|
||||
before = inventory(root)
|
||||
payload = {name: (root / name).read_bytes() for name in before}
|
||||
if {name: hashlib.sha256(data).hexdigest() for name, data in payload.items()} != before:
|
||||
raise ValueError('addon bytes changed during collection')
|
||||
projects = validate(payload, root)
|
||||
if mode == 'release':
|
||||
blockers = audit(root)
|
||||
if blockers:
|
||||
raise ValueError('Not release-qualified after collection:\n - ' + '\n - '.join(blockers))
|
||||
if inventory(root) != before:
|
||||
raise ValueError('addon tree changed during collection')
|
||||
payload['BUNDLE-README.md'] = (README + '\nThe combined scenario requires the separately installed authorized addons listed in EXTERNAL-ADDONS.json. Their assets are not bundled.\n').encode('utf-8')
|
||||
payload['EXTERNAL-ADDONS.json'] = json.dumps(external_policy(root),indent=2,sort_keys=True).encode('utf-8')
|
||||
manifest = {'schema_version': 1, 'kind': 'DEVELOPMENT SOURCE BUNDLE',
|
||||
'native_build': False, 'release_package': False, 'projects': projects,
|
||||
'files': {name: hashlib.sha256(data).hexdigest() for name, data in sorted(payload.items())}}
|
||||
payload['BUNDLE-MANIFEST.json'] = (json.dumps(manifest, indent=2, sort_keys=True) + '\n').encode()
|
||||
stream = io.BytesIO()
|
||||
with zipfile.ZipFile(stream, 'w', compression=zipfile.ZIP_STORED) as archive:
|
||||
for name, data in sorted(payload.items()):
|
||||
entry = zipfile.ZipInfo(name, date_time=(1980, 1, 1, 0, 0, 0))
|
||||
entry.create_system = 3
|
||||
entry.external_attr = (stat.S_IFREG | 0o644) << 16
|
||||
archive.writestr(entry, data)
|
||||
return stream.getvalue(), manifest
|
||||
|
||||
|
||||
def write_new(output, content, root=ROOT):
|
||||
path = Path(output).absolute()
|
||||
canonical(path.as_posix().lstrip('/'))
|
||||
if path.suffix != '.zip' or path.resolve().is_relative_to(Path(root).resolve()):
|
||||
raise ValueError('output must be a new .zip outside the source checkout')
|
||||
for part in (path, *path.parents):
|
||||
if part.is_symlink():
|
||||
raise ValueError('output symlinks are refused')
|
||||
if path.exists() or not path.parent.is_dir():
|
||||
raise ValueError('output exists or parent directory is missing')
|
||||
temporary = None
|
||||
try:
|
||||
with tempfile.NamedTemporaryFile(prefix='.erri-bundle-', dir=path.parent, delete=False) as file:
|
||||
temporary = Path(file.name)
|
||||
file.write(content)
|
||||
file.flush()
|
||||
os.fsync(file.fileno())
|
||||
# Same-filesystem atomic publication; link refuses an existing destination.
|
||||
os.link(temporary, path, follow_symlinks=False)
|
||||
finally:
|
||||
if temporary is not None:
|
||||
temporary.unlink()
|
||||
|
||||
|
||||
def main(argv=None):
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--mode', choices=('development', 'release'), default='development')
|
||||
parser.add_argument('--output', type=Path, help='explicit new .zip outside checkout; omitted means read-only preview')
|
||||
args = parser.parse_args(argv)
|
||||
try:
|
||||
content, manifest = build(mode=args.mode)
|
||||
if args.output:
|
||||
write_new(args.output, content)
|
||||
print(json.dumps({'kind': manifest['kind'], 'preview': args.output is None,
|
||||
'payload_files': len(manifest['files']), 'archive_bytes': len(content),
|
||||
'archive_sha256': hashlib.sha256(content).hexdigest(),
|
||||
'projects': manifest['projects']}, indent=2, sort_keys=True))
|
||||
return 0
|
||||
except (OSError, ValueError, UnicodeError) as error:
|
||||
print(f'Bundle refused: {error}')
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
raise SystemExit(main())
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"files": {
|
||||
"tools/resource_references.py": {
|
||||
"baseline_sha256": null,
|
||||
"proposal_sha256": "2e6080227bece7213fd67e58e7a4d27aba9847e610f8c000f6f2f65b623e567c",
|
||||
"index_sha256": null,
|
||||
"index_absent": true
|
||||
},
|
||||
"tools/check.py": {
|
||||
"baseline_sha256": "d60357b1c6b0d61dfeb80148d4a6684121e468bd3a044a9adc8f76752f60a41a",
|
||||
"proposal_sha256": "fb6bf594dd6544abee60d4e172d1d28f34f223cae93678e2356156f34e653f00",
|
||||
"index_sha256": "57937780370c47833d07e9ba8b7ce61133358f339294f788a60a7ae4325ba496",
|
||||
"index_absent": false
|
||||
},
|
||||
"tools/source_bundle.py": {
|
||||
"baseline_sha256": "e8b06f9340a8d67da992373f4642385a028acebe9aa1b3752f62cab95c8fce98",
|
||||
"proposal_sha256": "5d1d0150d8009f24a950ee85501d0da8b1f69d5fcbb5a7118b08957f14658f57",
|
||||
"index_sha256": "e8b06f9340a8d67da992373f4642385a028acebe9aa1b3752f62cab95c8fce98",
|
||||
"index_absent": false
|
||||
},
|
||||
"tests/test_external_addons.py": {
|
||||
"baseline_sha256": "4e2c3fa2c92661c49ea0c492648b736bebd54f24cd244f3fe27710a0c7a487ab",
|
||||
"proposal_sha256": "4b0eb867b3aec1bca906f68168948a4e42cdc0bced0bec2856a3ba68187a6e24",
|
||||
"index_sha256": "4e2c3fa2c92661c49ea0c492648b736bebd54f24cd244f3fe27710a0c7a487ab",
|
||||
"index_absent": false
|
||||
},
|
||||
"docs/vanilla-resources.json": {
|
||||
"baseline_sha256": "588192d151f382b612ca6ce9a564193b57d4a9e7ce9a3918bf8ad2f7e877d1f4",
|
||||
"proposal_sha256": "e10f60ce74a743b4619b0c2f2cc7fefcf09a94ab3ca1cbb332f386d6fb0da387",
|
||||
"index_sha256": "30dccbe13f1737ab832bb287cdef7f5a46ae718eafb68aa13c1c13ebdd29923b",
|
||||
"index_absent": false
|
||||
}
|
||||
},
|
||||
"runtime_dependency_closure_changed": false,
|
||||
"patch_sha256": "d02ed79ad88f21138e66a77189bbaf7130cf1e36331f47f1c3b5db026a1953c1",
|
||||
"test_results_sha256": "a3c9e916289b106bd0c3befbf7c675ea8f08579359b7d074538e787705aa063d",
|
||||
"audited_source": {
|
||||
"path": "addons/core/Scripts/Game/ERR/00_Core/ERR_ReaperRHSCompat.c",
|
||||
"sha256": "bcdf98c05ac6cdf0c7eaa854531b02e9ee4f53fbb346ae01d58114e572e7dd4f",
|
||||
"modified": false
|
||||
},
|
||||
"optional-identity-audit.json_sha256": "87581b0c0c210e76dfdb9f5285417fed0fa164a58897a0012f964e795236275b",
|
||||
"vanilla-character-audit.json_sha256": "625379d9757e265e4947b822df0b64548b4b36613c55ada811663fba2ede871c"
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
[
|
||||
{
|
||||
"name": "baseline-scanner-red",
|
||||
"exit": 1,
|
||||
"expected": true,
|
||||
"log_sha256": "e18a68ba778b467108eeba569dd0d924abfbdad365e7bc482708bb243b8a2943"
|
||||
},
|
||||
{
|
||||
"name": "baseline-bundle-red",
|
||||
"exit": 1,
|
||||
"expected": true,
|
||||
"log_sha256": "5a326f80f5671a5c56f5f5ba6880942fcd83821675a0f8454ee860541d4e8f52"
|
||||
},
|
||||
{
|
||||
"name": "proposal-green",
|
||||
"exit": 0,
|
||||
"expected": true,
|
||||
"log_sha256": "dec02332cb628dd7b75eff0af6e7a6c0f2f5ccab482b8d20b76bf97dcdc62468",
|
||||
"test_count": 10
|
||||
}
|
||||
]
|
||||
+430
@@ -0,0 +1,430 @@
|
||||
{
|
||||
"addons/core/AI/BehaviorTrees/ERR/MortarRapidFire.bt": "16b263bcb2fb3ae361367a600753a829425620d2e6b350a891c51fba47437ab6",
|
||||
"addons/core/AI/BehaviorTrees/ERR/MortarRapidFire.bt.meta": "f2a44ece28891240e6bfa1d01af29428adcadbe82c80e287eb33cd5e58f1f90a",
|
||||
"addons/core/Configs/ERR/AdminMenus.conf": "a7f889f260e43656136fc159342129e5f48748d28c426f65f9faac37b624cf94",
|
||||
"addons/core/Configs/ERR/AdminMenus.conf.meta": "5faf5ddc0a51c1d0f82d60af00d91edc22fe9c39aac50d8d04b772a2c9271be1",
|
||||
"addons/core/Configs/ERR/Content/Registry.conf": "546a5a407c9e6c25c9157ae4392898fa3f40c04c7956649e62201f9ac0ba187c",
|
||||
"addons/core/Configs/ERR/Content/Registry.conf.meta": "046aa988bf8e972afcf7a60b6f2312f605f016f98625dbbd9cd75ebf9ea88800",
|
||||
"addons/core/Configs/ERR/EveronSites.conf": "a66c30039c7141e5a0f22af21aa522728fe4aa5cde821158aea3b716d11457a1",
|
||||
"addons/core/Configs/ERR/EveronSites.conf.meta": "d5fe68025ef4e7c1e16082cf5873b7c7172eacbfaef4ab29b7e0e3c98f8dca56",
|
||||
"addons/core/Configs/ERR/Factions/MissionVehicles.conf": "5f74f4a7089c7e7b54ad62463159ce8f0bab25a6b85268dc3872ea6001e048fb",
|
||||
"addons/core/Configs/ERR/Factions/MissionVehicles.conf.meta": "00c368b6271d3440cc8bf627b03a384d247635723923fc5ad2104b8b4007b035",
|
||||
"addons/core/Configs/ERR/Factions/US.conf": "4c3da063abb6e3ee39a6e4e0c5a9ffd5eae9d209d58470ea18b45dba5528db1b",
|
||||
"addons/core/Configs/ERR/Factions/US.conf.meta": "a05469aef028e9e17eba545e81e2af2887b59f0fef17dac51a23c7b8155e381b",
|
||||
"addons/core/Configs/ERR/Factions/USSR.conf": "407ea27f80a64c5184c089d43cdd0bdabfc5974c84f1d2a245081fdf2afa3f30",
|
||||
"addons/core/Configs/ERR/Factions/USSR.conf.meta": "057397d97096346791b51b7b13fbe18af218bcf78e9984d9c01b49a2403de611",
|
||||
"addons/core/Configs/ERR/GameOverScreens.conf": "45231061911a1462d45fb6db0fecc2b0793f17b5ae71017174954ff4fbd20236",
|
||||
"addons/core/Configs/ERR/GameOverScreens.conf.meta": "eb654b745c0b97b41c991694569ef4877a3c2315e0826f9556337cd68690843e",
|
||||
"addons/core/Configs/ERR/ObserverInput.conf": "e898d645911e85b6ba902366cb23890d8bb14bbd2c485102e6d49ea728e9b054",
|
||||
"addons/core/Configs/ERR/ObserverInput.conf.meta": "9714dce6c38ee81bcc513c8ebef51d7af63fd15bcdda2e40946937c625dc3ba4",
|
||||
"addons/core/Configs/ERR/Tests/LegacySites.conf": "3864eb638d0ed4dd313013d2d787f975ae6ce4bbe238569919f76b73d5f7ca42",
|
||||
"addons/core/Configs/ERR/Tests/LegacySites.conf.meta": "097ac7daef4fc18344699a8471fdd77f9d158f8c70bab394068d7a08e4777ac0",
|
||||
"addons/core/Configs/ERR/VanillaFactions.conf": "db890b61b48ee15484041fd2245a862d9fa9e7ba21b1229c281ff37c448a35b1",
|
||||
"addons/core/Configs/ERR/VanillaFactions.conf.meta": "ac77725c0c21974991ef47a466b88122e939de8b46fd23e68889e7674cbb2bfd",
|
||||
"addons/core/Materials/ERRM_MapRenderTarget.emat": "9877c5b175c5f30dd80bea36c711b21ab38219aa7075adf9ae79932e1d4c76bc",
|
||||
"addons/core/Materials/ERRM_MapRenderTarget.emat.meta": "5ee1a705f8011a44020ca2691f5ccc17d44bf596fef9a36e98d1f267eb58fab0",
|
||||
"addons/core/Missions/ERR_Everon.conf": "936619df7789a6b4b80bd763f702526e1145ab4d5c300516c07e7e70dfe57d92",
|
||||
"addons/core/Missions/ERR_Everon.conf.meta": "0a23c98bf83873536c65fa17d38dea33a1d7b9e4ab210f90633ff688abcc551f",
|
||||
"addons/core/Missions/ERR_Everon_Base.conf": "b46e1f4aeef383a8dbe7ef2b5c12a55a8111856c52ba103a1e508c01b82dfc61",
|
||||
"addons/core/Missions/ERR_Everon_Base.conf.meta": "9b16267c644d815bcf98a3a3aaff30b93d7224fb24d3a2bac66730a28011f317",
|
||||
"addons/core/Prefabs/ERR/AssaultParachute.et": "b556997989605e2a05982418b7e9f26d12d427eb3ea6e3bc50e85c67ea7aa4b8",
|
||||
"addons/core/Prefabs/ERR/AssaultParachute.et.meta": "e9dea2d533ad1ce6ce689e0e2815c97a6382e1b90c35ce1efa88a885527e8e18",
|
||||
"addons/core/Prefabs/ERR/ConvoyCrew.et": "29a525a29605386dfcf292dc2316e9fc7650ce39db9fbaa4ce4372ad0de66db4",
|
||||
"addons/core/Prefabs/ERR/ConvoyCrew.et.meta": "0a909a15b7dcca34202ded136b3bdbbe8898153c9589e1cce1388433d362da02",
|
||||
"addons/core/Prefabs/ERR/Epinephrine.et": "e09c70b3d47a4dc5b92fd332c8222b99554b28a8a0c93cb5caac18eec4501571",
|
||||
"addons/core/Prefabs/ERR/Epinephrine.et.meta": "f1861f0b0ccace1b7b3d9c29768e37a83bf0c6fae5a411b1bd61d6b2eec7ed89",
|
||||
"addons/core/Prefabs/ERR/Extraction.et": "4d24c7811415c06386205e5bf5c132a23fcf21e96c75c7657ccd5f3ac914ac50",
|
||||
"addons/core/Prefabs/ERR/Extraction.et.meta": "c2a838633001e2e3a202d39cb33aa744ebcd996017ad032359069641b5d13853",
|
||||
"addons/core/Prefabs/ERR/FactionManager.et": "5a7b330f33956cc1781c8dc843e8186f2d37a98653ab36e7c42b9019df3c89f5",
|
||||
"addons/core/Prefabs/ERR/FactionManager.et.meta": "9bf53d5e4bcbe60dd1a4ece1409fc23c349055c860708620f5f6e9716290a97d",
|
||||
"addons/core/Prefabs/ERR/FieldCover.et": "e403d5cb3a5966f0cea81f15e0e825d482ba1a7a27b12498319ba45a414963b0",
|
||||
"addons/core/Prefabs/ERR/FieldCover.et.meta": "83461ffa76244e1d69f20b053a9741ccdf7d127009182bd540a7e5ba6150c3d9",
|
||||
"addons/core/Prefabs/ERR/GameMode.et": "4d3e5e2df28cbb8292c436ae05d4fc7e5ca789a123450a6968d9a718b6ecef20",
|
||||
"addons/core/Prefabs/ERR/GameMode.et.meta": "106769cd34525c9d440057072836cb7401a6752148c40edd7fe61c03bd58328c",
|
||||
"addons/core/Prefabs/ERR/Items/EmergencyRepairKit.et": "0157bc235eeb78a0e1373b561fd22a1dcb225c833ff7c2d4abae688bca0ec92a",
|
||||
"addons/core/Prefabs/ERR/Items/EmergencyRepairKit.et.meta": "da6f065cb2414b5a4cbe9ef0f0b1295b2466f26ad406c0bddb83845d4598efb3",
|
||||
"addons/core/Prefabs/ERR/MortarCrew.et": "21086e886fe3199624208c9a866f883ec109f7d08746c2b56b497e59857fb656",
|
||||
"addons/core/Prefabs/ERR/MortarCrew.et.meta": "fdfd4fcd21a67c3d698fa4aadc4e5c76e665cebf4be86013bc389e493fab63cc",
|
||||
"addons/core/Prefabs/ERR/ObjectiveDocument.et": "5118ecaf9d2038eea44a4b785f05d2e78781dc1387249aa58a6782c7e6752e14",
|
||||
"addons/core/Prefabs/ERR/ObjectiveDocument.et.meta": "eaba9903be147b98a1106e2273e2270773df73b9b22f2cd4e20136a8e281382e",
|
||||
"addons/core/Prefabs/ERR/Patrol.et": "d3eca8fe9197c57a27a285cdb3baf168b037b198d92b39df28a338ae2cfd0c74",
|
||||
"addons/core/Prefabs/ERR/Patrol.et.meta": "7c5da568fa2fcf0709ee2959253cb068d7c7ed7c2467af3b247a7e70efd96b69",
|
||||
"addons/core/Prefabs/ERR/Prison.et": "c0ca5219aa2d6322ba7d094b92000640b259112ff6611a745c0713c8875d09d4",
|
||||
"addons/core/Prefabs/ERR/Prison.et.meta": "2e426ef3de68f4107907854b51e818bc11d84649a01c538e3f18dd9ebec766bb",
|
||||
"addons/core/Prefabs/ERR/PrisonBackpack.et": "ae750f08fc9af645561f59d7e5809bd22f4cec26ca8fa6409d09730765958c91",
|
||||
"addons/core/Prefabs/ERR/PrisonBackpack.et.meta": "7da6aa45467250edc910ad7230dc244d1b041e8a6f55881eb3747ce51f9212ba",
|
||||
"addons/core/Prefabs/ERR/PrisonDoor.et": "b0ff94443fe334032113a663917de23f920a8b73ffadc9c8e9f11b545022b3d2",
|
||||
"addons/core/Prefabs/ERR/PrisonDoor.et.meta": "b8f3db52bf186426026668fbb9d633c3cbd4d438ab301fba880398f6a0e781c2",
|
||||
"addons/core/Prefabs/ERR/PrisonPatrol.et": "dc88c31cf5c415573a874f74e13572f0add9e6122c8fcad507fe82860d789c47",
|
||||
"addons/core/Prefabs/ERR/PrisonPatrol.et.meta": "5528e0d778dce5ed39c3e504c6427625527127b23269d20fbf12ca2bffe52ffe",
|
||||
"addons/core/Prefabs/ERR/PrisonWall.et": "9b410b7c85bb001be4601ad93f750e17b8318b850306d84f29c4dc1b02723d7c",
|
||||
"addons/core/Prefabs/ERR/PrisonWall.et.meta": "0294bc5dbb56f90f8153d62459bb0a6ad91d76a479812bbec9c7db182fdb58d6",
|
||||
"addons/core/Prefabs/ERR/Prisoner.et": "e6d345ac98ad9ec742bf6c3b8686839c3256df9833d31bb4bdf605cd41d0ba5c",
|
||||
"addons/core/Prefabs/ERR/Prisoner.et.meta": "974278ba49fafeed70b619a0067bbc70ae4d534be441c812ce2bef4a5fb3c022",
|
||||
"addons/core/Prefabs/ERR/Radio.et": "99b1d80b49d1e7f9d30aa4283772a36fd66e962369f288f5fe329c7fc911bb1b",
|
||||
"addons/core/Prefabs/ERR/Radio.et.meta": "bc91137b68ba550217914fb8892bb44d7e1920e4a1086f3e506623832a44212f",
|
||||
"addons/core/Prefabs/ERR/RadioCamp.et": "5e6216bf8e6e160da5d9f966c8f7c2081bf6dd16dfac1b89d682a14b3b8a6716",
|
||||
"addons/core/Prefabs/ERR/RadioCamp.et.meta": "3cb8d3d553ab6d8d111a74f721cf4e69ee1011cbb90248b83cdc7275697276bd",
|
||||
"addons/core/Prefabs/ERR/ReconCrew.et": "33953379ceb725bcd0cbe505cd643c94adaed17dbbfa95dadd404d6b8e345715",
|
||||
"addons/core/Prefabs/ERR/ReconCrew.et.meta": "2653e8c5b1cdb857de5badd5959ddd9826a6a298ab3c166628dbb835d7104d90",
|
||||
"addons/core/Prefabs/ERR/ReconHelicopter.et": "c609ee59ab145e0a1936f95726b86df643f5cc425c43924029e9c1abc69ebbd0",
|
||||
"addons/core/Prefabs/ERR/ReconHelicopter.et.meta": "d80f1c3d6a6f9104562b89729996c1c92ad240f08cdcf48d4c390a09d2047c08",
|
||||
"addons/core/Prefabs/ERR/ReconPilotEast.et": "d961f329823b991eafed80d085de1bd89b44a4575be98d8dac385d6b77741ba2",
|
||||
"addons/core/Prefabs/ERR/ReconPilotEast.et.meta": "d73df3c896359a54514d2efcd851f579feca7a2619b76c2a38f607649a31a4f1",
|
||||
"addons/core/Prefabs/ERR/ReconPilotWest.et": "8f8221927269352e55c8026ee5b00e026c281c79af6684b386f24e7dc4675fb8",
|
||||
"addons/core/Prefabs/ERR/ReconPilotWest.et.meta": "4785f23bb492c6af420ee7896ddbfc9767e0db1e06de95207df2dc949a1b1814",
|
||||
"addons/core/Prefabs/ERR/ScoutEast.et": "b4593aab494c4f21637757b3daff4f349da77b4c48ec5e8a4a2917a6a12cf811",
|
||||
"addons/core/Prefabs/ERR/ScoutEast.et.meta": "7c72af632537f687e92f30b52d97fc7d70dadd39d33f37e0b1004f9596f55012",
|
||||
"addons/core/Prefabs/ERR/ScoutGroup.et": "8dc0fce8ee3decc1c367411b00b6d8518df9d8458281cec0881464a2ce906af0",
|
||||
"addons/core/Prefabs/ERR/ScoutGroup.et.meta": "62e43fd152ce57aa4ceb2187a49e4aecdeb9f428b3a1e8318f86bb83dbf8a259",
|
||||
"addons/core/Prefabs/ERR/ScoutRadioPack.et": "f1c4911e2556c0e0caa8b896982190c5e7d0433e850b4610e19442caf9117607",
|
||||
"addons/core/Prefabs/ERR/ScoutRadioPack.et.meta": "825506e3d814d30a52d5dbf64124470641c07a0453543ba71426841e6c783635",
|
||||
"addons/core/Prefabs/ERR/ScoutWest.et": "2681b5a3f8621adb44195f0dbca6f3e79ef7decad8f9d0dd0e1a801ec2549627",
|
||||
"addons/core/Prefabs/ERR/ScoutWest.et.meta": "22a6607b4b8fe606ca75a634a0b2ac3178e7bedae7f9ff01e7a4989f3b39a3da",
|
||||
"addons/core/Prefabs/ERR/SpectatorCamera.et": "cd2dcaca0df4c39816e582c594591a535525ed77827ffa3de24d27b79996544d",
|
||||
"addons/core/Prefabs/ERR/SpectatorCamera.et.meta": "2a16558f93915e31908a674509e9c89976470f78a84a1174a64b94b68b8f77ad",
|
||||
"addons/core/Prefabs/ERR/SupplyCache.et": "4c97b0514fe7e723046f40f0b396f6573b12eb9981ca5df70b9e8aa3cf29323e",
|
||||
"addons/core/Prefabs/ERR/SupplyCache.et.meta": "2f5de3a4aab1e9d0e35521f48dc57b95bd6e449c383dec4f1c258e10295904cb",
|
||||
"addons/core/Prefabs/ERR/SupplySite.et": "f33681281d26676fac88736091834d5a7b87fe0fa01883582542df964dcfc694",
|
||||
"addons/core/Prefabs/ERR/SupplySite.et.meta": "b41944b12eb3528ff7a3ac94258b18c66ef161aa6a38894aee300a1ac4798630",
|
||||
"addons/core/Prefabs/ERR/TerrainConnector.et": "cf9cb28f5a3f41931380864a29ac979aa1d5e843456f564ac7a7de78f88e1aa8",
|
||||
"addons/core/Prefabs/ERR/TerrainConnector.et.meta": "9f37c979ae282aabca29ce84beb0db851ee8b9a19f7f3a64d387c175616127f3",
|
||||
"addons/core/Prefabs/ERR/TerrainTakeover.et": "6206fe2eb4e2c6c1a9e3ddf2898535ae08981c115adc6ddd926017ac20d4b535",
|
||||
"addons/core/Prefabs/ERR/TerrainTakeover.et.meta": "64e953e378ab1d2a75ee7246f876f4ef93ae8a4e3fddb5002d7ba37268cb959d",
|
||||
"addons/core/Prefabs/ERR/Vehicles/SupplyUAZ.et": "29f157849f413261494a63d4d5b0a97e8bbe61cb076efcd59d6c940653f23352",
|
||||
"addons/core/Prefabs/ERR/Vehicles/SupplyUAZ.et.meta": "544c94cf1c26757a10654de7856cd6cc48b821ce3bdc02add13cfe6514269915",
|
||||
"addons/core/Prefabs/ERR/Vehicles/SupplyUAZRearSeats.et": "cd4acdcecad299445952aea0adefc85f2b9e9b43f8186f100e0505c5621b3656",
|
||||
"addons/core/Prefabs/ERR/Vehicles/SupplyUAZRearSeats.et.meta": "123955da03462befb90e293b3bb856d49cc761166611b38ff47cb48ec2fbe95c",
|
||||
"addons/core/Prefabs/Items/Equipment/ERRM_SharedFieldMap.et": "30dee8e9eab459ea32a7d835a9fb89d43df47708057cab829f067b25a24cd581",
|
||||
"addons/core/Prefabs/Items/Equipment/ERRM_SharedFieldMap.et.meta": "59093e9072c50d99c86da7609c87541016da5bcf92b98d99db4c524e1c8e0e8d",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_Actions.c": "cabb21413c90b252d29708b62228d0679c51c76e39ee0e483953ad7061b2b9d6",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_Actors.c": "980d30964845600a261693cc5c5553e1472e8e54867bdc06133ff5c7b36c9128",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_AdminMenu.c": "3b96a99832ed40002598a186dd8de1d21410c2e690df37a6319fdbeeeb4eeab0",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_AdminPlayerTools.c": "56780d78bf423f54f482d8620f821b8d3eb0199194482b4f12e37f5ec3f55ef5",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_AdminProvider.c": "62e05aceb49da07fed7aa89fb6b2f8eb3efc373ac09eff286fba983c3ad570eb",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_AdminService.c": "c3e008c8bbf538c5bca3a82a975decc7a283a38543a9d2639d90a81ce592c51e",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_AdminSession.c": "89d92f138a201ad7e752e027ba3930a2e0bf647d7b3a2c576346c1467f8bea3a",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_AirfieldPlacement.c": "0c2f4d31a2abc8f3f90bda20546543f2a1cf9306e9bf93351dda1883b990770e",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyGroundSupport.c": "26f0c7ebe8563bb022f7c383674e7d8997b0cc35c7ea321d39d74f2493c1ed9d",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyLoadingFeedback.c": "e46988b92243df19a5400eca7406d6969b8b1174d8e3efad48fa0a936cbfdd07",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyLoadingGameMode.c": "f4cf19440583ac24346831a2d5f1d7f734c031e46dc266c499972329dd0533cf",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyLoadingOwner.c": "6346a05ddda030f7d9b6f026f977d5f018ee16002fa519e8c49dcd700c323dc7",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyLoadingService.c": "e6f22813f7a04e2c0ea000d054407191f2be8badfa6c51e062e9dbf84b95c67b",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ChatClient.c": "4bf937ff74e0483c17fa0103f73bfee3afd8f67a37c0c248b08772a17bfcc349",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ContentDefinition.c": "bc1dd4ed27ec894cf4bd617fb226cb8140b544aaa9ef6d8654e815d81e7f6fd0",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ContentMenu.c": "3dfc424b1fc83dbc094054ea2e969a4aa584c724b77f23623e2fec9cba83ec52",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ContentPolicy.c": "3a4987345d5a7159234a7e1a08bf5ac40dd5a23031e9b1953fc43a0501d9924b",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ContentSettings.c": "3e2734dfb935a4e93d79b66ca4a7c883723a1fc348e3595432dbf2bfca643923",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_DebugAI.c": "bc5529c60591a6c36c39cdb753b1af948690fc3c3c725f38a8d595b41a499235",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_DebugIntel.c": "a9f6e7e42a3214879a21052e897f9afc0653c12ff15d5bee7766e26a1af6ab17",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_DiscoveryMap.c": "dd350bdda1bdf427ab8cefab623fe60cce5332b062d1a29686fe52f73e9e83f1",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_DiscoveryService.c": "34458b3a4f7062375c9c5b5599308e9cea67fc4a316420836f6694ca2c646ffc",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_DocumentComponent.c": "885c8ab4fc9e64c3f8b40056536096c8c32b011cb340b25ca00353a96da15c69",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_EnvironmentService.c": "c0fae5bf51ccf507bc84d44adc2d1dff021cd83653c0468b7645a4f343e3fc8d",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_Epinephrine.c": "e04c53c2f665997023b2daee744265cd22f4f0101444e4d9b0efbd114f74fa9a",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_EscapeGameOverScreenInfo.c": "6e3c65e55b05cf205040c310b9086faa41b88582c7f9faf49c010afd59da5b07",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ExtractionPlacement.c": "6d388fe21f08b25cbdb5dfa4e198d94a4c80c5092f8d17630a4654e18bf8b3f5",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ExtractionService.c": "91357099b4e0401196b67d48963be54be30e56bdba57cdac67dc20b8ebb883e9",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_FactionCatalog.c": "a5a8c53acf21259e14f59cb919535910f30dabff5a9179c664bc6a7a4d744d6e",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_FactionMenu.c": "3549339d7796e67fc646680493c226e545b6fb95daa0270af9901795bdf8ed50",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_FactionSelection.c": "04b8bd8a042cf743ab8a87ec3711f9758e7b0112995a9d363e81a63df4eabe5e",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ForceLedger.c": "0ecaf1c5a52568e751678b0b1236e91e6adb538f8fbf010d38b61a312d1bf253",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ForceSimulation.c": "2bbb8888c752a3ffc042f3059937526d25ae288af5b4db024cc683025a2605ce",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_GameMode.c": "89a29c03ba225acbbb9fa3c58a721aced91a77bc0c77046d697005a6d7c48bb9",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_GeneratedSites.c": "4a23058f27e3ab074df6f8f7bb6f08a8fd26fbadb8943c6fb8d64dcc9c221751",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_InitialGuardRules.c": "8c9d6b1dc4c2af96284e34f487eebb5a221091016ef108006dec60b4e3836558",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_Inventory.c": "b63e679d5b650b63a7a91dfc3f42a62f4be58b0338f6df3313e66d29a93bebf6",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_InventoryLayout.c": "1af5df45a0f06d19a017954e9bf4b2d722e2d2389f8ffdeb1d024435b9a08be8",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ItemPreferences.c": "690a39a28a84ffe7ccbd27d4af50679925a870b53accf18d6573fe94e71d35ba",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ItemStationTeardown.c": "102e61216e86e47ad243cc19f6f66da1fcd8cc77f8799354ceaeb4a6dc74622e",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_JournalText.c": "87a6c19429f12c5630ed73170ca9a8a6d2255d6cd38b130166a78aacd15f2de0",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_LoadCasualtyAction.c": "1521af55a34110ce1c971b5226a618a9c6d931622abaae4946d9c0d27c05a273",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_LocalAdmission.c": "a076922d1ae966cf5cc67b198166ca6b1288358fb7f641207a4681e6a610a2ae",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_Location.c": "5b0b058130ccac02bdc1dcd6474d51a6f45da4dd52ed6c37906692fca3f194b1",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_MissionRules.c": "f7abc38ad8fdc375ce7fa63a65f0bade027d22b37e09de5e3f94ba8c3c63cc41",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAdminMenuProbe.c": "ec8d04b6550b39b9688ef67b40cb2f14a9d98c8fff62b6dfb8d4a43e19b4e4c6",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAdminSettingsProbe.c": "73e58561e08e50008d33f81eed606dd4e8109fb69a627e892d28ca468d641f7d",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAggressionProbe.c": "85a34cf60018e90d974cb67ab0f358f3073b6b9f02c563ec200e062f1d249e3b",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAirfieldMarkersProbe.c": "593e59664dbd7330b52674e5d4cc7b70db588cb75a1259ed808b74602501d541",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeBaseSmoke.c": "e811e985048e07365569acde6b5f045d57e9bbf13927f85b74e6e347fd2ef571",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeCasualtyGroundProbe.c": "41f40db3735f8aa535c0061458d9892dcfe972222b8a17238e67b65633c46bc3",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeCasualtyLoadProbe.c": "94c533deea654ec546df3f1ebb7cd213e6cd79b1125d99bab5303ef8e87b018b",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeCasualtyRemoveProbe.c": "4cfc06f6d43b709b63caae714155ffc562502e884f49a9825623c6f46972ad36",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeCasualtyServiceProbe.c": "02a9d70d1f4ba20326df199ba41489cfbae12b7bb0aab441361421cee38ad9ea",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeContentProbe.c": "cb0ccfe1e1575f9ed80a8054058b471f3543378db059e6af2fed8eb42a262638",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeContractsProbe.c": "421e4b901afe6118b6bf44e8f678db8ccdf1c83b39da0cf816baa36f7275ccdd",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeDefinitionProbe.c": "904d8d4c3e7b91d49dadfe495fc7b4f02f300e4aaf7efa348df5ca17ec4a6e8a",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeDiscoveryMapProbe.c": "9ed32d391d08d937ff4f9f33bd11c3a204ce9a2230c2d72b6761e0320b31f24f",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeEndProbe.c": "2dec80c7e247ec5c257407f95d9d5edd42fe0cc44d6af9f724f6ebd10d8a355f",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeEnemyLoadoutProbe.c": "0885ca69f6fa7f53414ce1792cfc3c49916886b8173783c634135c13c5d37429",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeEnvironmentProbe.c": "9e2e66ac5d9778a1c65445348e3300cbb90b68b3f669f3ddf1d2b78a858430eb",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeEnvironmentRestartProbe.c": "7a836a206381b8e8de24c92baf141beb30575723675dd6948d738169ed26b507",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeExtractionProbe.c": "4b09385f73206de004f4f3c38a6192fd658a0d2012482dc5a84dff1599ceb972",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFactionCatalogProbe.c": "e3011fa47b67122d7b2c23af8f91b7a217599d6cc114c4f9de628744b9c948d3",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFactionSelectionProbe.c": "946879d822e7be2d48e03a3140aa1aad3e3d44dd18507fa3cdedb4c6d7dd81b9",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFlightFootprint.c": "a8862a04ac784426f431e2e9cd3f1f19f820b38a081674d29549b8b00277c72d",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFlightInputDiagnostics.c": "e231dcbdaefe81beb3bd587cb73be8fb3d3184bc86d18dbaa30a43ca4ba5dcc4",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeGeneratedSitesProbe.c": "83ab84ca4de7b545963896ed9d14e6545c23a2b940515730d74acc2f6b3dd18d",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeGuardCancelProbe.c": "bfa1c65cb039e19c3d1891e4a3fd33469e974c97cc7f42128efc31a8f587d514",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeInfantryCombatProbe.c": "3e4c4382ab91f470357268927b954fd101685df6b2244df483f0422d6c0d7da2",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeItemStationTeardownProbe.c": "028588a49fa9207087cd27ec9396979cd932daa071e2490bd0262cd71dae30d9",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeLifecycleProbe.c": "b613a5dbe81c2032fd02d31070ae5631166d14d0b02cdbec3b63b782f0bbc115",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeLocalAdmissionProbe.c": "29c860ca3e51cdaa463f3c23a98ff45ee0499ce9bbc322046e0efbed587f1e09",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeMedicalCombatProbe.c": "3b9c557b249728c518f9d6b5cb24b725ecc32a69ae12df069cdfb0da70a80b95",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeMedicalProbe.c": "4b73e7cf35e9c8fddb089678a320ea58272e1b6611318d0a762754c171eff785",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeObjectiveLossProbe.c": "6b80fd317a8c6e8583bd4337870838a86251e3b8a681d0aa07e8b52e22abfc48",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeObjectiveMapProbe.c": "2d07b895cb74af58454605fb1c536a566733e3001a9375dd0677d5f274bf2a46",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeObjectiveProbe.c": "71fbd2479a70048f83d8b262ad1452f427be2c0afc8b071ef13bff477b9dc29b",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeOpeningToolsProbe.c": "0c5d6b96ed5a7cb1cf0d098d534dc7190449ed09339062e6b584729d53a61b4c",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeOptionalSiteProbe.c": "19fc19e22348e6213827f620f4fdb5dc26144ea2ce0032de773e79c1fb155a26",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativePatrolProbe.c": "5a2af71cc4cfccc7dd7c23584398a38290eba1a8894cd46f6967252ff3a7087c",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativePoweredFlightProbe.c": "7ae5d6f85bbbebec214c66bfdf6f53b93c802f109fcd5bcfbad82c5d61d6cb9f",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativePreparationStatusProbe.c": "456f4d7c3272b89d5f4c6713617baa5596d846994152356fee9a659839bcd8b5",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativePrisonBreachProbe.c": "4889e0d3799a6a21b9f84bcb2f2ae78dce16269cccd1329f8d1fcc1a23e7c22c",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativePrisonerProbe.c": "e2d1ffe5d269add55124601ff0d1dc032a398c7d51010736e6f0e4cbeb38ae86",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeProgressionIdentityProbe.c": "1d3fe20bce761a1082964bca9bad9ce79d1fa8b04db9b5053bae98da380ae560",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeRadioCampProbe.c": "67f1a088f9b20e5f0f11ed3aa083ffa772bffd7c74d85b7a307344ac3d47e09a",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeRadioDefenceProbe.c": "ff1e27a0ce75b123a86e7df31354831880ca62ea90b6c5d7c60d3ba168e1fff0",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeRadioInteractionProbe.c": "7b27552d233813894f65c08eb9f04b547c4ca9ff96a2370a763cb94bd4a555c3",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeRecoveryProbe.c": "d6691f22432b3ce37d07d448aeb3ce7feb5cd09e852e0167b5e4676afd24bb21",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeResultProbe.c": "c9a89cae067f221b9f33965b4d3ab311b78ba79ea383ca65032c4001df44b472",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeSiteGarrisonsProbe.c": "1a5ff8747d7501862085b5e9162043fee3b05e82c73c516ad8093aaada53dc60",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeSiteSurvey.c": "ac0203753ade0cdff6d483132797a80e4520f14546c3f9dea288281cd4cd9c4f",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeStationTeardownDiagnostic.c": "172248540932174341882861bb78a9720a6cf89981fcdf9dffe63f7fd4023f2c",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeTimeProbe.c": "4a2c6ffd947334a0a71eac083d10c853c524b00042e9ea0987497c4cee60c3d5",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeTransportProbe.c": "7a3fe04aa1c5ed1061ff63d9d5180e8b925932b62d76c1ffb49bd3dc23530993",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeTransportSurvey.c": "816df9a2a9072f9f7db75e56168d8a8fa1e665ee8f7dfa79af011b354254909d",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_NativeVehicleSecurityProbe.c": "59bce863142e4fba4b6fb2f544bb8a58061f0e99b1a38e5ac291cea919563763",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ObjectiveDetails.c": "628ebd166dcb5544c2d18dce489619984887ee18296cf2446fc6d894f89dd5bf",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ObjectiveMapPresentation.c": "f189f8987244e10df61ac577bbbc952ed5c4e6c431a8e3cd192a10fe2e8c3bec",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ObjectiveText.c": "8d75b35ab977be0cb1a2e3d3d1cb8ef875cdbfba69c35784c3d195451ef944c6",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_Objectives.c": "b9cd5bb3b193c20401175c4328405be1b121e8a60b7b5999910b6a71f834af8a",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_Observer.c": "682aa5549470c69fc72d261fbfcf9f7a04a41a66e0101b269ccc00bc282ad05d",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_OrdinaryGateObserver.c": "1e376ca83c0005cf532539e14d7f47363c47b7c5b03fe3d55405a59208705fd7",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_OrdinaryInputObserver.c": "808a46cc1e4b31b65dbbbcdd55493f594ebb3974bbec38b4a2402334c653c0ef",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_OrdinaryLookObserver.c": "d5a1b636938d65e9d11c78b31487f2924400c34d98e2ec812954a2a224da7dc0",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_OrdinaryScenarioLaunch.c": "a4e7e56d174ebd15b4730202dae4c8ed06144f3f27c23ed49c99e2d297dc421a",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerAdminCommands.c": "eca9baa3b07da48a740851583540840f8bf5f65f7be854902a3778f76967faad",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerEscapeResult.c": "3124ab4d2d6d471409a47aba0af528790734df53243c03fe0cdac3e407047c14",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerGuide.c": "e49bab76a015ab545088af7e5eaa3cc45811907db4e5b1c5fa8c18afef34b62f",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerMedical.c": "270454d50235bc28df9bba4fde2689934578874c4eca9560afb9f0f6324d7215",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerRoster.c": "c038dac0f749bd29ebc35a4e952904b41a34417ba738904d5efcd1833a263e0b",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_PreparationStatus.c": "43a406822a0361f916abc363f27e0c578ee94855036981d876bf47c68233c71a",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonAI.c": "8709753e86dc2ca777183f08cb8fbb9851e0c0de495ca01520ebcb1b3dfa59b9",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonEscapeService.c": "535cf17e21fc8e62716c7d9da88d976ee2f526501c6a4752b822f1252e742bf4",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonPatrol.c": "284618391ee2da84dbcda4a99ca3c072eae3d67b8a9ef40a86827b9ea00810f9",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ProfileConfig.c": "9df8ccf45fc2ed12f4b14d08270878696e8785760a3ae51fe032b6f3818fc0e6",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_RadioDefenceService.c": "f5f0bf1352141f933d0edb5630e30541e001dc07e1d2c8529b29cc159c126b13",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_RadioFeedback.c": "545262e65e9b3645d9e514a0521e442fe08f0c2e4e7c83ba638c5105d09818db",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ReaperRHSCompat.c": "bcdf98c05ac6cdf0c7eaa854531b02e9ee4f53fbb346ae01d58114e572e7dd4f",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_RecoveryService.c": "86f9a7769e3ccb19fc61127fe2fee2ad0dd825487a5cd59f334de8b9741c93cf",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_Resources.c": "d0169aac6fd0c38928c47a9002ded0fd8ba558ea3314a600e792d307ac1ca3ee",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ScenarioComponent.c": "81bf30d358c7b100248be17cbc2e6beb2f107300c939aede8a92d273eb7dae1f",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_SelectionStyle.c": "f8a545dc9c21ebe397a5f790f6dd85d3c8ab18e444ac3b486b386f7d0df15008",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ServerItemCatalog.c": "d3385219f4f28e95b32cfae27092168ed09ace6baab4fe8c755963bdb8a795a6",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ServerItemsMenu.c": "0ac154f77852b959244716e2494f632b6a2d8cd08171a4681af0365fcd5e7436",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_Settings.c": "2951c36cf3a72ae079ab8991879b4759fae783d719c61878f1aad7126836dae6",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_SiteDefinition.c": "2088c45798f0eced702e0abd97550b8d1fc97ebcc34c3d497978b7424f6c670d",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_SiteDiscoveryRules.c": "dcbce3b7aee89bfc47a50e9de89209758af1f1bb462b99af67a8ad7a26e9f229",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_SiteService.c": "15a28876954bbbe0e80d5b5b19e7336f154023cd05b67d65dd709ae7fd9ac712",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_SiteSquads.c": "183883783a4e8399cf62851a4cc65a5d091d25131bc53b4323cf17286315b2e0",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnClientScene.c": "b56f99a91cdc53bdb93d320d10839339022d7e61e6b101eee8296271abd7d3cb",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnFinalization.c": "c949642366ad124dd2abc4111cd598eb94aa257fbae01b6fb3a0f1882a23e83e",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnLogic.c": "47a39c951be71bfcf1cc50526d507d0f9d8ef2fc09408697b6fe6b0dc5a529e2",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnPlacement.c": "270bf465808d23627a11e720c6632d4fea35d0c679e63aa64046ef8874d68ceb",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnSceneInventory.c": "76b79d5bd9d1f367e1ed19724302b7d49f8b0ede85cf19e89c452582ef651f8f",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnSceneLease.c": "20de7f96bacc9037580d88d4424664b4554b2c082d82e7d29913e9dfe390b594",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_Supplies.c": "752e8a56b0b8cde33cf532032cb0a203553017b686faac2e19bee06f7a9c0713",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainCatalog.c": "ba2e68543a8c929492d06f8725a743d26849a630d6f8c09be0f23894f92d0990",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainMenu.c": "1da542ef60ff7c1897b1f12432c636ef6a08cc710bac520ef186589d506e9a54",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainPreference.c": "93fc55f2c33e95adbcf2bead3430aa14bdb55154315760bcc9647f89dc8286ff",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainSelection.c": "ee75cac068b99e7403f5eaabe556152513cf5d973602cc6e6b8967d25402f6ad",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainSites.c": "63ad027dac5bafb9e93805c361cbb27bf82af0567ea181a760ddedea98204c06",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeover.c": "487f1d004aa4f7a5f58c12c37724b26fcd54fc62b4096d48f3a7436d9958274c",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeoverClient.c": "458b84b3fb31c5a2bd1b7c3d65f25e0aeab91f5505ef0813231435c8a3c7d2b7",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeoverManagers.c": "5b7661a5617b7124a10d3c18e087a4e2363a967eecc5c87ecc94573f2abc07f2",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeoverPresentation.c": "d66a29a44e999cc3f2e56ba9c3c6bc936c027747312e08778ce301c1837f2112",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeoverSettings.c": "da22775930b13e41d4a71409e37af3bb99e4cc1d94bdea0e3b59fbdcd4d40132",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_TimeService.c": "63867760876d523a1794f619118a52c5cd387d5d92756cd286b2c16a348a6c7b",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_UnconsciousCameraProbe.c": "66b1c4591b0ecc67cb08418a115bb02ed2b0168b7ae970f1e0a1ea335c59dc5b",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_UnconsciousWeapon.c": "24d31bc857486638e55c605283c17cde0cdbd3c5c6021eac1ec93611387b10d1",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_VehicleSecurityActions.c": "bd7d0aeb4abcc9d8044e4888f9a92f9e5fc97c098bdfa3bbad57e1a29697a779",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_VehicleSecurityComponent.c": "2ffec4e646584ec546147fc4b08249825cb32b531aba26467b586d760485adc3",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ViewDistance.c": "8514f72f8207f12570d2317e64094a45507a1647dfd45a1501499ef81e90189f",
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_WelcomeVoice.c": "a01d4163d3ab5b480ffbd2ceeff7384d8df6b7dd64036d580cd0c462b0135d25",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AirAmmoMission.c": "0a471a40c8f7dfb797d8d35e41c5b1ff91e8d2ab13b43cf866e46c0e4ab4ed9d",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AirAssaultLoad.c": "5554994115cd7d56152ac78ba53034bf934b71c5634b17d35e96884dbb3b8a24",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AirAssaultSystem.c": "2eaf9816eee3e1cd2ac70744a6ef7ea5a90d0a3eebdf925e384028a7edde6a42",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AirReconSystem.c": "f8a0e3cf4552d8133efd33c2126ea15a7694676773a7047c15e00021c1d9721e",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AirSupportPolicy.c": "b5dad011d5a0574a406d6469e0744a9d37700cb41930dada28c5143d556acf53",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftAmmo.c": "2be282406d0c45ab2e35b0ced791b5e494c662588f536701a4e82e6f5fb7c913",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftControlBridge.c": "b8f0141644d8f043c6db4c2d4bb93215c548e5c27ab5468c66e996d62bdf905a",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFieldEnvelope.c": "0f53c7d9ab167a804eb904d63725decebb53fd5796fdf27864a75abed5679838",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFieldFlight.c": "c04e264cff9963821852094c451502d31bf9c96d4deae2e8ff8a2373b53b5665",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFieldRules.c": "30be68f4ca2db7e169f6f0432815821179cddf9159f7b150341dc8eb479bbd17",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFlight.c": "aa25a8e67a30c48677bf528236402b7f8e5d815dc18df93b878520ad3d1fe8a7",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFlightEnvelope.c": "8125cef61fb283d0d7c4dd2df3c04b062b448f1101fd48dd53f4f4097df5fef3",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftRouteEnvelope.c": "e8fcef844239c47a1f2f36be420afe943bc450091b05859435406b46c87fa511",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftRouteFlight.c": "1d8d92bf6d97429d68a9f62018232e90cc124cc8d7445efeabe863706a31e2b9",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftService.c": "3f05209227986b5c6bfb193f8f53783cfd4ef083bce898e22257c3e63daed913",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AirfieldSupport.c": "c6d88ede0b1b6bac5a7075b6e2e783ccfa8850210aabd28bfa4bcdb698cc5f87",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AssaultParachute.c": "a93c996059e7166988e9d1b0b498cbfd36f19a1cf8520cb4e9215a8884752e18",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_AutomaticEquipment.c": "5832cbd3a43748e77f4e7f1b59361801c6d0445e0e15165e97d7a897b338709e",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_BodyRecovery.c": "47d9374095d04f5f1339c220caf518a40938ffc20f891b1b51ae38579e7e1c25",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyBoardingProgress.c": "328f8a5eabb8174b7727eee1d675db83a2eb0be7b8e834db4e950a645ca5d7a3",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyBudget.c": "ca49c274146d56e30cc93fa1652cc34c0fe68ea95725b0b3e33ab3673a6463c4",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyCombat.c": "5c4b7576b28d51edea868cbb91a0ab31a40e6ddb558f1b8a38e07e20fdb2969d",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyMineStock.c": "4497d6b790a45df2b76d18541ddaf299b406def88b868caa29f096849026a42c",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyPlacement.c": "aac2a2c508aebcd9eed0a0cd310c2f3774357bb9b1fc383f305182b41d29caf3",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyRoadPlan.c": "fae404f85cae63e63976938a5fdb73efc988ba25c5846564f12edca04fb88551",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyService.c": "cc8dc67129457623505d959a097df765a1364ba4616313954ed6bf4ff0eb3542",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyStartup.c": "360228fd45aa6ecd9426e36120b5e637d2feee1e3a4a89aac8207526b871c87e",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyEquipment.c": "c52d4a3cc0e71eb136487c42df2fcd5bd6da1c33d31dbd3d6429c237dcf4a8d9",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyGunnerSkill.c": "adf8bac5a6f7e40b2f9caff5fe9be590c4e4ce2b2b387ba39e741a3c4f4cc564",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyLoadout.c": "a48f32dbd7f209bf08fce2840aaffc1781c571fc679763be58987f6b082e776c",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyMapMarking.c": "0f161fd3e08a54e3e1063679127549e482c40253a022e9d06cd9ee4d740b8625",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyMedicine.c": "05d341a9a000bfa2084057bd67d476d6e35adca6c8518d74c27cd31b551bbb95",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyOptics.c": "759e0a88ff30cb781ee69b8a935865d63ede5b1d97f31d344018f650a967c37f",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyRadio.c": "3a97e5c3de9ff33873d97c6b2d84ae505cfc4f3146e047b928e76ec3b22c8789",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_EnemySkillAwareness.c": "00c450d033e43fc45c9e2cb64a1d81161d123cc594a4292cfc5f68eb6c17ee60",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_EngineerMine.c": "defb12924ea5dfe68f86c2bbb4b07362f016ffee810f720d13f01d81881b3cfc",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_EngineerMinePosts.c": "bcddb72845189b52e5ed71c687d7dd4b0b40b91b7306c3f6edf84a631002fc5b",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_EngineerMineSite.c": "d838f5693d4fa5d252d529e59777f560674c02532f1041a5598e938b3a850839",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_FiniteMagazineReservation.c": "8278590ced1936d618905b0cbd0b5aebddda238d426a6a2a52e455fc36bbb502",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotHQ.c": "c51fccd0ecdb0a1d6ba99ae965e2e572fc1ea65a5d8dc2e1e2a058698dae45c3",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotLoading.c": "6abb278409527bb67db084138a773de240d99ba7f63f9ac740f8167615d53f1d",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotTransfer.c": "21daa9ed8cb5f2dc08a0fa85e305fa4b4f3e7b01e16c71fd1ca98d66a4e8b652",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQ.c": "d873b5b689e918f8c907918d673304a184ac2e4a4cb6face527b37a67821ee9f",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQAdminProvider.c": "e9bb5f2f3ec270074964fc8607e5a07c23f224308a4446837598d93e201d7775",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQAmmoReporting.c": "95c024cbdd35c02d9b0c3d389d29bb042e5dda6ffd2f5f0d896078274b3adb35",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQAmmoSampler.c": "8bb0ec1422887feaa340307d3c60bae50fc82d424fce6390876e580ff8b75e8b",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQBodyObserver.c": "f59421c1e0c83f0f480d7dd4d048b4b0a41193ed8fe8f2f627d2b6a696420ea1",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQCoverage.c": "8d9668858c47b7e9fee2b12d3ebd4e7cb88146b817cf615c4b0dade26c81b2ec",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQDeliveredCasualties.c": "1f738127e55e843ee2705007cedb5c08741f52f63c75eca7c80242177af82273",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQDoctrine.c": "6335728e89ed40ce11b811f00b61bfea76e94dd3379e4357cbfc438b05522bb0",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQJournal.c": "53563ff54fc4e0656713d6eaec5e88ddf69fd4bfa8ef6a67cfa13380d24031e1",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQLocalAwareness.c": "124260280ac8eda0e920bfcfc86932c9b21df6b1f7a6aa8acfc43feea3da149f",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQLocalHandoff.c": "2dd700dae9d9b232d22ca63ff01af75a3f5cc213ac24b7c0a43ffa38bc0b9ffa",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQMemory.c": "ec2047a477fb4273e22ae6bb68e7365f321f55c583b5d2c48c4abf2ac38e3b7d",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQMineSampler.c": "2a0fdc4d27e947a1d77b02ae23f757c7fa074eb456f817b7df0766583d757f55",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQMountedAmmoSampler.c": "2f0db77ba999586e4290e440d112f1002da17ab5fd20bb4f5b7ff6df99f58a81",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQMountedDispatch.c": "f62f8bb8fde222f3f47d89df1439083deb6f5b14633402a2afb7c6a97803582f",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQMountedIntercept.c": "5f45545c11de5e183969203cdf07e29089697ddc89752a9c5aea0fa2a1a33a97",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQNetwork.c": "0b73be993628a55e3b21c8670d540e39c938093dd5cb4d586e800ac530509b25",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQObservation.c": "57ad3f0b68d150791e30a7e4bd7dfedfb1ddd78a1c76f228e67b33ea9cb7144e",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQPursuit.c": "ab6ca0e1a7f36c104e664db06a74c80a528cbfd1de599af42e2194ef0a4f4ca3",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQReport.c": "12ea8ba08753d1e6d38b237087c1209cd2f9574b53c3ff0f27c082bed029c9ea",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQRoadIntercept.c": "0897e82d7805ef56f05f2b9c23903280285ea6bfa51796a2df86bb564ece78f7",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQStatusSampler.c": "b937eaed913a5095afa8e678dc1c36b5c805541bf8cd5be927069533d6baed1c",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQTask.c": "1147904bae6d72e9de47ce17bdada3dab489de4ed6e781dbf15bdbb30599ff6e",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HQWatch.c": "abe634cf6003ae920ec1ed18e305ed462920204960894520d3dd11f7e5ef1c33",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HelicopterAvailability.c": "60eaef2f6d4b2fd44861c5a4434ef97e732e40a5ff7401e2da451ed2dd9c2762",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HunterCombat.c": "df1c319d10efd07ed6f971cf0e41d8d7e377b04ea7f0fe143bf94df733fd1d9c",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HunterCrewRecovery.c": "e76af0fbf6f436a9c3c9d4c7b779bc08a78f6fe705c08bf6d9757bbeb65ee8eb",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HunterOpeningPlan.c": "0b6275221dab491f148426df05e132579f3acc20de5559226c3b38975618355c",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_HunterService.c": "79369d5cc30cf628f02df0023157ab423e40497325dfd6a73b218757f2b689d4",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoAccess.c": "ab4262f78d54782c5ecbf5fff4ebe3da16d72329658d7e18c0c35387dc8b3c7d",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoTransfer.c": "99fa26beb0c0869d0cd694500f3bfc0705c2c1cf674dea90d98fb93a59570ef7",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryCombat.c": "5684fcbee128a35107312452297f7ae2bec28aaa1b63f619fa649f36df8ea476",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryMineTransfer.c": "02c399413f80879c22b4891e8ec807c67a6235677095fc4b98bafdc360d6944c",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c": "ca8eee2704e7758172e33014404bb1307c683f19b561b840d4592f6312051e62",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_InfantrySupplyPool.c": "c8e454573cf064ff392291d6feebf1f23be64390b5b8e944c03dd065f9f46b42",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_InterceptVehicleFootprint.c": "5dea67d14ebab67231c485e14bc92f34c005a5f1bf6d9c0943db28e9857e958a",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarAimSolution.c": "59e8343d09f7a44871d8d3335d6ad1d02216abb5deed30d38b5ec9ba3f2c0649",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarBattery.c": "157024afc8fd3c1ffeea6ae923ff091e5773b9ffcf5f5864f8040d001e689110",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarCourierTransfer.c": "968e58ca700b4a11e5e04a5c159696f514a0b1bce531210172b913e495f7e2b7",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarFiring.c": "f2597d44c10d10de2462aa5e5450a22b8a5ad0eb99bd0cc09a8cf1ca2dd4a350",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarLogistics.c": "b3624e4a00a2bdef16f6c100bbd79910e3bb8c2ae8ec5fe2ad5aa70bffecd303",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarPrediction.c": "05863b2b4f9f70cdb288f91c722cbea163c13f2a2927dc485482e5bd4fa7d57f",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarReadiness.c": "4c3799b3f2681e977669de0cbfaeb307d9a682b04365bfc9f59079e762965758",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarRefresh.c": "52ae8d9d6cad92f42d68c634091b80a474d2666b6c06d63a8c30a3fab71494c4",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarReportLedger.c": "42a96040b63e56677353e55164ae23031c90f70b4d6673a9f412ad7b19e636ae",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSalvo.c": "c128850c7a78a4d8fee00ad38f48b265f1fbd1d9b24b092ddc5c205b0f0ad6da",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarStation.c": "cbbd7c86f722b664c85ab7c070ae1131d2ce5c41d1dacb4381bff9c1720a1866",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSupplyTransfer.c": "ad71084f507ad9c32d3055e7ec6844a1ec5ddf568c0216ab8391e902b56e417c",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSystem.c": "bc290ee8bed299d869598cbf41ec281653e0cc7f3c64c7214613df8a0fc83829",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MountedAmmoPickup.c": "5f7ca5b31f3b405c2a6ca32ff91042f5b4dac6ab9640ce67fb10d7a74236ba69",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MountedAmmoTransfer.c": "0b195784497672fdaf651f336c14f7be98c257f98c85cfbeb4f96fe1a401999b",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MountedMagazineSeed.c": "b42d0aac142907433df8bedc40de24c94813544016cf5f451846f1980250f995",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_MountedResupply.c": "c26ad43705765be1c20eca37fbe2978b8c647151f6620ed37141657a4b7dc312",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirAssaultProbe.c": "c1d55b338b157b758e6ffb993d5f689029b28b13929797c91e5dcb15b5e561ea",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirLogisticsProbe.c": "58fe863775d0ad575cb566c78cef696c9826691cf49ef9adde76376be7316db1",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirReconProbe.c": "c1216e0512a0268e4dbb82429e228334401c0c3cac52ba4486ae6dc91e41576d",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAircraftControlProbe.c": "0cf3e72ccdc42e6ef20fb71d743f0e037a9e69b2e082c720fa705628cf790205",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAircraftFieldProbe.c": "b64907c7566a894ca2f3c49ede5d972d4087a938da1a0ca87bcbd7c2203b2c52",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAircraftRouteProbe.c": "8d0dca97e5106d1c84b64992c789e1af0689514beefc027e713ca6ab901fc470",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarCourierProbe.c": "740c8bebbd4128a9311b1167d1058549475d6b46f81c9b6c0d19650f4b50616f",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarFiringProbe.c": "ee570d21bede8baebefc799399712d9582b3e30ebda7299f6c941777f02ad2a2",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarSalvoProbe.c": "fb9ccc6b36247ab3ad828ffbb2556abf5c2838d93ea6cd1ad259c0a015142f5e",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarStationProbe.c": "a110f0abc753cb1d2f781e457e637dd5346ecd2e924eb5eb3a5c7dca3d1e2340",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarTransferProbe.c": "399c21940ef10777b46fdb3e905430ce43404ce1de2f4a6bb62f9c61c1a0689c",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativePatrolHQProbe.c": "a58f57530e333976dc96fc5a0f9cb6cf0cb069c55788824950c5fb2f965d8e26",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeScoutProbe.c": "41b39b1abe5e51a5b8a428d533cccbfb0dda9d7a570228dc3489408c60543f17",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_NativeTownProbe.c": "ade130f49fc9d868281cee7fde383f084f70ed8d4b876dacebbaed8538e84999",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_ObjectiveDefence.c": "83ef91c2118521aedb4c1838b2e47909c80e0950086449b98ced168f1fd87080",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_ReconAirports.c": "7551347d776d6e0eec818d6468cacbca7ac53daee7317e0a1618ca3d39ebc762",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_ReconCrewLocks.c": "684bc5b9858c7ed90ed2ca6d52fc0e731a7e37a116db776090257b72a63621ab",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_ReconFlightComponent.c": "4966dad504b3f8f28a9ffc8ac17cc548b00066fe05213c49c662ea56de34c9d4",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_ScoutSystem.c": "63287a252e4e7d5aefce840279f26ce3e1f286cb79cadb32596c37897cec7119",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_SettlementSafety.c": "e5c0ebc95521a9a33a3f7d9cca6c551dda862a08b7af20b017877aba9584795b",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoyColumn.c": "35678ec625fb0a3c0871e2c373fcff49816440a97a165ed25c8798dd72ef059f",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoyService.c": "5b1578afbf6da736453cc9d3872979eddd1649746aa32d3b0c7a9e3cab50057e",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoySystem.c": "f09aa817c27d6af0ccfb544f4ab1ae2afafb63d626641e03d87cfe159475d821",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoyTactics.c": "dc3acdffc8ca48f11b131f66d30d679ca68f3b3004344bdc78723bc9305915e0",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_SupportScenario.c": "a7b46253e1bb37cea7c29bb557fbf43ca207022d0f1cc927349441b2d1615279",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_TownGarrisons.c": "57f862476751087972fc78d0b27ab44e72361e27d32f15d55f9fe7fd7d6bd0e0",
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_VehicleAlarmPerception.c": "45ac71d25e10a057a26a5b0fc7128935baaf47f4c0f87208a4420fa52086fd98",
|
||||
"addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelAdminProvider.c": "d63ab5c547021aeb61d398b8a773afeedee4662d3ce15d9fd9d0e9e37262f8b7",
|
||||
"addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelDiscoveryFeedback.c": "62f2c408383f410782d9d41fa50acd6bd8cf66eeb80d2b79f91852b9d2cf8d97",
|
||||
"addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelEvidence.c": "6bbf8d3b83e2c09fd9a23a9a5e5e11d7c29af2e618116bee613562fc45af2b33",
|
||||
"addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelReroll.c": "d8b04de9ea789732cc78ebce9aa60786c86fe46d05f671cf251eefa68a214b59",
|
||||
"addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelService.c": "2911325c79a7a372628b18ffa0e110d11919ce2c2cd7b19277bfd608fdb03dfc",
|
||||
"addons/core/Scripts/Game/ERR/20_Intel/ERR_MineIntel.c": "3ce16cebaa9703b2f9803df7c11614f94de6460a9136dab8f80dcad41ae2b1c2",
|
||||
"addons/core/Scripts/Game/ERR/30_Map/ERRM_NativeMapOwnershipProbe.c": "32418602f085e3edba7343f42a6a691630b533be262002f29248e8ae87a38254",
|
||||
"addons/core/Scripts/Game/ERR/30_Map/ERRM_SharedMapComponent.c": "3a10f6ea25bf88a400bc3e6c339823433845c5db4f2f423835ccf99a1b1a843f",
|
||||
"addons/core/Scripts/Game/ERR/30_Map/ERR_ScenarioMap.c": "75fa1d742129ef7f33c005cd48f56db7f49ee7bde3c5428532b0b501b032b0a3",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_AdminCommands.c": "282fe1463add7af8771aa58507b254e69d2d06f50274d4c77321db073f8394f0",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeAlarmHearingProbe.c": "5dbb6a48909b76cd141e3a79ef01d2e68cafee55153821c4471f85c761fff94f",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeConvoyCoverProbe.c": "d2450140cf9bdf09210473234605b4c0d818ea5b91f9532209166a35c5d13701",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeConvoyProbe.c": "4bdc920e87fa768b0ef0ed893c70ddbbcc9255d74163d7b657fd2ec7c4f14c32",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeHQBodyProbe.c": "811244cc8297817efbfc3ee4edf01c868eae23c88127ba0c72e98ee7422da72f",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeHQMemoryProbe.c": "d8fec6c138bb0f5bdbf99ee82ffc3ac9b44d1045d8833da63f8aa5f39beeb7e5",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeHQResponseProof.c": "0f8b09fd8753234c91fd6baaca0e2f812e409ae1c4be8f340b648ae59b69c2f3",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeInfantryTransferProbe.c": "9b2de4dc22bdadd51b0271219a971dc8dc07f70ed3534f306acf03ed81b29424",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeLocalHandoffProbe.c": "0d4d61c424a16008595f86fa61f3b848caf9bd6e9ebbacea9c10254d88ba378e",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMaintenanceProbe.c": "852b9b397efc3f919c97fec63bc3df1a850cd7833421af8441994afd191951d4",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMortarProbe.c": "ddb892141500c192c0787b011d57dd8c07dd8c9a3ca5fdc407f6c271897bde0a",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedAmmoProbe.c": "8d197f7a1398625e5a19db3284b0bf72c6ee6e032843a3e4d9a4e58de42b6825",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedCourierProbe.c": "12710e9e5548fe8856f7a52f3566338369a8a1eedf0bd92af16229271872ada5",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedInterceptProbe.c": "34b0b1e38a59f14c4e83d93ec412779945388e6f4d697bda2f6cb90f519a6372",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedSwapProbe.c": "a6721fcaaccadf8eddb06687c7d587d0a3e377d5d1bb0b8e72e630fede8690ac",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeRadioProbe.c": "84524163c63402755b4f834f74dfe6d8e5c397dc26031f532593c6f79f5a93b1",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeRandomRadiusTrace.c": "7e946406067092e30b6b75cc6ef0c56db7f866249e02bd13648156933ee578d9",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c": "595fce681ec74e0d3ffe7a29c527c1551874469108ded479bed72a0fcf6c732e",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSupplyConvoyProbe.c": "701311de6a2c9fe8f0534a22056323c34072df26595dc70a7d4df45bc06e6c13",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSupplyTravelProbe.c": "32e6074e912491f2643a24cb44311b9fe5b069c76e4e94a45e7409ac82d36507",
|
||||
"addons/core/Scripts/Game/ERR/40_Chat/ERR_OrdinaryScenarioLaunchChat.c": "a747af09599ce4d0c52051f18f00c4624d24d137e328341b580b82e896c6bf65",
|
||||
"addons/core/Scripts/GameLib/ERR/00_Core/ERR_DiagnosticNoSplash.c": "0ea1b402f8927b6d68bf6f7e5caa2967f7e3a39147634faab147796b791933b5",
|
||||
"addons/core/Scripts/WorkbenchGame/ERR/00_Core/ERR_ValidateBaseWorldPlugin.c": "49a38c37b51e5318c7dcbcb01543dd9a6300d053f0d39808b3974f4edc45b871",
|
||||
"addons/core/Scripts/WorkbenchGame/ERR/40_Chat/ERR_ValidateWorldPlugin.c": "f567518b54f43b88747df2838cdfd6ebb34605c0919a3e7d271d28dd8b67a9b6",
|
||||
"addons/core/UI/layouts/ERR/AdminMenu.layout": "6577a8ee61db2ab1cd4e9a5a27a3c6fb5ca6ccffddd9df80577c5d7ec1e63bc0",
|
||||
"addons/core/UI/layouts/ERR/AdminMenu.layout.meta": "9deeece996f43b1f1fed6b5ec89279645c7b6424250200a42580cc088142e9bf",
|
||||
"addons/core/UI/layouts/ERR/AdminValue.layout": "cd811af6d2fb187f01c74e20ea07ad85669546b0ad70efae2ce52921ce26cbca",
|
||||
"addons/core/UI/layouts/ERR/AdminValue.layout.meta": "56b3d2335db400c1308e07c4a35d278b23ef32013dfd6dc82951866327428d08",
|
||||
"addons/core/UI/layouts/ERR/ContentRow.layout": "942e33bf2e08550446b40bcac31fb4504b7d8c717a42c196f54bf4025c72706c",
|
||||
"addons/core/UI/layouts/ERR/ContentRow.layout.meta": "8c4bc13b41e7aee38e0ca640a97813ed1a6964a00e2cff9e1fe4ebd71fc2fdc6",
|
||||
"addons/core/UI/layouts/ERR/ItemRow.layout": "6d364ce48158b90abd2185ca87ee27b095d0f7a5c8d59a0c65940e4be5488ac3",
|
||||
"addons/core/UI/layouts/ERR/ItemRow.layout.meta": "33eaef9c403ea3a030e58ec17f78e46af457048243571ad5856fff04101fb60b",
|
||||
"addons/core/UI/layouts/ERR/PauseModsButton.layout": "d21d436291e2c1b262e33dc228b0d60a1d188dc9e85cfda6d2373f8281431b79",
|
||||
"addons/core/UI/layouts/ERR/PauseModsButton.layout.meta": "9ed6adabd8f53eb9a562d7186789876bba5c4202155ca894c1af866ca47354f3",
|
||||
"addons/core/UI/layouts/ERR/PreparationStatus.layout": "bd269cf8dc6f27735423743dd5b78242550518414448a0256e5e12fa6b92c459",
|
||||
"addons/core/UI/layouts/ERR/PreparationStatus.layout.meta": "75b12176a443bb911fc4ad446982d762201fda42ed38736b79bc5439fca31ccc",
|
||||
"addons/core/UI/layouts/ERRMap/ObjectiveMapElement.layout": "b364752c44896d67dad07e466a04f4504a50813fb36ee7c34c9189ea9677b4e9",
|
||||
"addons/core/UI/layouts/ERRMap/ObjectiveMapElement.layout.meta": "8691fe2eaf46568bca4a9f8128b247a8da810bb87a5546aa7ca3334e740270d6",
|
||||
"addons/core/UI/layouts/ERRMap/SharedMapRenderTarget.layout": "6e83a9c70282aff43b23a08b732739e7a241a31e8abf200498c90a745d3d60dd",
|
||||
"addons/core/UI/layouts/ERRMap/SharedMapRenderTarget.layout.meta": "5c846445cc089e2e08899ba703059d4adb805ff30ab5a16409a3cd59718cbd54",
|
||||
"addons/core/Worlds/ERR_Everon.ent": "22324bc7eb0d80dec8a1f3bd61a9df9201b72f749f4e751766b0c9d0b7d46b87",
|
||||
"addons/core/Worlds/ERR_Everon.ent.meta": "19d1903ca72baa326b4724a6791d0da1104a1e53f3f31dc1ca41a856efd68e83",
|
||||
"addons/core/Worlds/ERR_Everon_Layers/default.layer": "6bcb7fbb27b6282719dae8a37486e518d4cbaea385f2ea9af1918b36bb28b175",
|
||||
"addons/core/addon.gproj": "73e973a1f1c5910393e16f86a3a40d792031bb2fa3fc7f4dd87a06a16c3e34a4"
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"rdb_path": "/home/jakub/.local/share/Steam/steamapps/common/Arma Reforger/addons/data/resourceDatabase.rdb",
|
||||
"rdb_sha256": "c5344847875ab4c94cf3cda88c5f9cc60878b799f33b2137c8e4a18726c19b7c",
|
||||
"resource_path": "Prefabs/Characters/Core/Character_Base.et",
|
||||
"resource_guid": "37578B1666981FCE",
|
||||
"matching_records": 1,
|
||||
"assets_copied": false
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"complete": true,
|
||||
"resource": "Prefabs/Characters/Core/Character_Base.et",
|
||||
"guid": "37578B1666981FCE",
|
||||
"database": "/home/jakub/.local/share/Steam/steamapps/common/Arma Reforger/addons/data/resourceDatabase.rdb",
|
||||
"database_sha256": "c5344847875ab4c94cf3cda88c5f9cc60878b799f33b2137c8e4a18726c19b7c",
|
||||
"record_offset": 5909418,
|
||||
"record_hex": "507265666162732f436861726163746572732f436f72652f4368617261637465725f426173652e657400060000000000ce1f9866168b5737",
|
||||
"occurrences": 1,
|
||||
"ordinary_hard_resource_validation": true,
|
||||
"no_external_dependency_change": true,
|
||||
"manifest_before_sha256": "588192d151f382b612ca6ce9a564193b57d4a9e7ce9a3918bf8ad2f7e877d1f4",
|
||||
"manifest_proposed_sha256": "e10f60ce74a743b4619b0c2f2cc7fefcf09a94ab3ca1cbb332f386d6fb0da387"
|
||||
}
|
||||
+434
@@ -0,0 +1,434 @@
|
||||
{
|
||||
"README.md": "36f856473704853eaba0fb33227c83b6ece02a3368cfd5625b3fc6ffc986469e",
|
||||
"handoff.json": "f3d4996ea7d85e8ccb37f2efa427ee13d216245feafad36e46e1075b5a948933",
|
||||
"packages/core/addon.gproj": "73e973a1f1c5910393e16f86a3a40d792031bb2fa3fc7f4dd87a06a16c3e34a4",
|
||||
"packages/core/data.pak": "a03f4df43bc84df8b63b01089af37dcc08ee822fc3d9a486f375775ba2fbdcc7",
|
||||
"packages/core/resourceDatabase.rdb": "c71778b1869e5b0d2617fbdb90f6ddecc67041359bcacd6b1ee535f8424cf14f",
|
||||
"source/BUNDLE-MANIFEST.json": "7a3be024863703f162ca39adf57ef19364f15323e6a42422433aebedadc2c07c",
|
||||
"source/BUNDLE-README.md": "c46c89a66c56aa6ba4349c50e66b8368bfe53914d1019912f961da83938ba4ad",
|
||||
"source/EXTERNAL-ADDONS.json": "172e62d5bb83a3423192205c2e002de0257170314d2fbca346cf8fd72a26ab1f",
|
||||
"source/addons/core/AI/BehaviorTrees/ERR/MortarRapidFire.bt": "16b263bcb2fb3ae361367a600753a829425620d2e6b350a891c51fba47437ab6",
|
||||
"source/addons/core/AI/BehaviorTrees/ERR/MortarRapidFire.bt.meta": "f2a44ece28891240e6bfa1d01af29428adcadbe82c80e287eb33cd5e58f1f90a",
|
||||
"source/addons/core/Configs/ERR/AdminMenus.conf": "a7f889f260e43656136fc159342129e5f48748d28c426f65f9faac37b624cf94",
|
||||
"source/addons/core/Configs/ERR/AdminMenus.conf.meta": "5faf5ddc0a51c1d0f82d60af00d91edc22fe9c39aac50d8d04b772a2c9271be1",
|
||||
"source/addons/core/Configs/ERR/Content/Registry.conf": "546a5a407c9e6c25c9157ae4392898fa3f40c04c7956649e62201f9ac0ba187c",
|
||||
"source/addons/core/Configs/ERR/Content/Registry.conf.meta": "046aa988bf8e972afcf7a60b6f2312f605f016f98625dbbd9cd75ebf9ea88800",
|
||||
"source/addons/core/Configs/ERR/EveronSites.conf": "a66c30039c7141e5a0f22af21aa522728fe4aa5cde821158aea3b716d11457a1",
|
||||
"source/addons/core/Configs/ERR/EveronSites.conf.meta": "d5fe68025ef4e7c1e16082cf5873b7c7172eacbfaef4ab29b7e0e3c98f8dca56",
|
||||
"source/addons/core/Configs/ERR/Factions/MissionVehicles.conf": "5f74f4a7089c7e7b54ad62463159ce8f0bab25a6b85268dc3872ea6001e048fb",
|
||||
"source/addons/core/Configs/ERR/Factions/MissionVehicles.conf.meta": "00c368b6271d3440cc8bf627b03a384d247635723923fc5ad2104b8b4007b035",
|
||||
"source/addons/core/Configs/ERR/Factions/US.conf": "4c3da063abb6e3ee39a6e4e0c5a9ffd5eae9d209d58470ea18b45dba5528db1b",
|
||||
"source/addons/core/Configs/ERR/Factions/US.conf.meta": "a05469aef028e9e17eba545e81e2af2887b59f0fef17dac51a23c7b8155e381b",
|
||||
"source/addons/core/Configs/ERR/Factions/USSR.conf": "407ea27f80a64c5184c089d43cdd0bdabfc5974c84f1d2a245081fdf2afa3f30",
|
||||
"source/addons/core/Configs/ERR/Factions/USSR.conf.meta": "057397d97096346791b51b7b13fbe18af218bcf78e9984d9c01b49a2403de611",
|
||||
"source/addons/core/Configs/ERR/GameOverScreens.conf": "45231061911a1462d45fb6db0fecc2b0793f17b5ae71017174954ff4fbd20236",
|
||||
"source/addons/core/Configs/ERR/GameOverScreens.conf.meta": "eb654b745c0b97b41c991694569ef4877a3c2315e0826f9556337cd68690843e",
|
||||
"source/addons/core/Configs/ERR/ObserverInput.conf": "e898d645911e85b6ba902366cb23890d8bb14bbd2c485102e6d49ea728e9b054",
|
||||
"source/addons/core/Configs/ERR/ObserverInput.conf.meta": "9714dce6c38ee81bcc513c8ebef51d7af63fd15bcdda2e40946937c625dc3ba4",
|
||||
"source/addons/core/Configs/ERR/Tests/LegacySites.conf": "3864eb638d0ed4dd313013d2d787f975ae6ce4bbe238569919f76b73d5f7ca42",
|
||||
"source/addons/core/Configs/ERR/Tests/LegacySites.conf.meta": "097ac7daef4fc18344699a8471fdd77f9d158f8c70bab394068d7a08e4777ac0",
|
||||
"source/addons/core/Configs/ERR/VanillaFactions.conf": "db890b61b48ee15484041fd2245a862d9fa9e7ba21b1229c281ff37c448a35b1",
|
||||
"source/addons/core/Configs/ERR/VanillaFactions.conf.meta": "ac77725c0c21974991ef47a466b88122e939de8b46fd23e68889e7674cbb2bfd",
|
||||
"source/addons/core/Materials/ERRM_MapRenderTarget.emat": "9877c5b175c5f30dd80bea36c711b21ab38219aa7075adf9ae79932e1d4c76bc",
|
||||
"source/addons/core/Materials/ERRM_MapRenderTarget.emat.meta": "5ee1a705f8011a44020ca2691f5ccc17d44bf596fef9a36e98d1f267eb58fab0",
|
||||
"source/addons/core/Missions/ERR_Everon.conf": "936619df7789a6b4b80bd763f702526e1145ab4d5c300516c07e7e70dfe57d92",
|
||||
"source/addons/core/Missions/ERR_Everon.conf.meta": "0a23c98bf83873536c65fa17d38dea33a1d7b9e4ab210f90633ff688abcc551f",
|
||||
"source/addons/core/Missions/ERR_Everon_Base.conf": "b46e1f4aeef383a8dbe7ef2b5c12a55a8111856c52ba103a1e508c01b82dfc61",
|
||||
"source/addons/core/Missions/ERR_Everon_Base.conf.meta": "9b16267c644d815bcf98a3a3aaff30b93d7224fb24d3a2bac66730a28011f317",
|
||||
"source/addons/core/Prefabs/ERR/AssaultParachute.et": "b556997989605e2a05982418b7e9f26d12d427eb3ea6e3bc50e85c67ea7aa4b8",
|
||||
"source/addons/core/Prefabs/ERR/AssaultParachute.et.meta": "e9dea2d533ad1ce6ce689e0e2815c97a6382e1b90c35ce1efa88a885527e8e18",
|
||||
"source/addons/core/Prefabs/ERR/ConvoyCrew.et": "29a525a29605386dfcf292dc2316e9fc7650ce39db9fbaa4ce4372ad0de66db4",
|
||||
"source/addons/core/Prefabs/ERR/ConvoyCrew.et.meta": "0a909a15b7dcca34202ded136b3bdbbe8898153c9589e1cce1388433d362da02",
|
||||
"source/addons/core/Prefabs/ERR/Epinephrine.et": "e09c70b3d47a4dc5b92fd332c8222b99554b28a8a0c93cb5caac18eec4501571",
|
||||
"source/addons/core/Prefabs/ERR/Epinephrine.et.meta": "f1861f0b0ccace1b7b3d9c29768e37a83bf0c6fae5a411b1bd61d6b2eec7ed89",
|
||||
"source/addons/core/Prefabs/ERR/Extraction.et": "4d24c7811415c06386205e5bf5c132a23fcf21e96c75c7657ccd5f3ac914ac50",
|
||||
"source/addons/core/Prefabs/ERR/Extraction.et.meta": "c2a838633001e2e3a202d39cb33aa744ebcd996017ad032359069641b5d13853",
|
||||
"source/addons/core/Prefabs/ERR/FactionManager.et": "5a7b330f33956cc1781c8dc843e8186f2d37a98653ab36e7c42b9019df3c89f5",
|
||||
"source/addons/core/Prefabs/ERR/FactionManager.et.meta": "9bf53d5e4bcbe60dd1a4ece1409fc23c349055c860708620f5f6e9716290a97d",
|
||||
"source/addons/core/Prefabs/ERR/FieldCover.et": "e403d5cb3a5966f0cea81f15e0e825d482ba1a7a27b12498319ba45a414963b0",
|
||||
"source/addons/core/Prefabs/ERR/FieldCover.et.meta": "83461ffa76244e1d69f20b053a9741ccdf7d127009182bd540a7e5ba6150c3d9",
|
||||
"source/addons/core/Prefabs/ERR/GameMode.et": "4d3e5e2df28cbb8292c436ae05d4fc7e5ca789a123450a6968d9a718b6ecef20",
|
||||
"source/addons/core/Prefabs/ERR/GameMode.et.meta": "106769cd34525c9d440057072836cb7401a6752148c40edd7fe61c03bd58328c",
|
||||
"source/addons/core/Prefabs/ERR/Items/EmergencyRepairKit.et": "0157bc235eeb78a0e1373b561fd22a1dcb225c833ff7c2d4abae688bca0ec92a",
|
||||
"source/addons/core/Prefabs/ERR/Items/EmergencyRepairKit.et.meta": "da6f065cb2414b5a4cbe9ef0f0b1295b2466f26ad406c0bddb83845d4598efb3",
|
||||
"source/addons/core/Prefabs/ERR/MortarCrew.et": "21086e886fe3199624208c9a866f883ec109f7d08746c2b56b497e59857fb656",
|
||||
"source/addons/core/Prefabs/ERR/MortarCrew.et.meta": "fdfd4fcd21a67c3d698fa4aadc4e5c76e665cebf4be86013bc389e493fab63cc",
|
||||
"source/addons/core/Prefabs/ERR/ObjectiveDocument.et": "5118ecaf9d2038eea44a4b785f05d2e78781dc1387249aa58a6782c7e6752e14",
|
||||
"source/addons/core/Prefabs/ERR/ObjectiveDocument.et.meta": "eaba9903be147b98a1106e2273e2270773df73b9b22f2cd4e20136a8e281382e",
|
||||
"source/addons/core/Prefabs/ERR/Patrol.et": "d3eca8fe9197c57a27a285cdb3baf168b037b198d92b39df28a338ae2cfd0c74",
|
||||
"source/addons/core/Prefabs/ERR/Patrol.et.meta": "7c5da568fa2fcf0709ee2959253cb068d7c7ed7c2467af3b247a7e70efd96b69",
|
||||
"source/addons/core/Prefabs/ERR/Prison.et": "c0ca5219aa2d6322ba7d094b92000640b259112ff6611a745c0713c8875d09d4",
|
||||
"source/addons/core/Prefabs/ERR/Prison.et.meta": "2e426ef3de68f4107907854b51e818bc11d84649a01c538e3f18dd9ebec766bb",
|
||||
"source/addons/core/Prefabs/ERR/PrisonBackpack.et": "ae750f08fc9af645561f59d7e5809bd22f4cec26ca8fa6409d09730765958c91",
|
||||
"source/addons/core/Prefabs/ERR/PrisonBackpack.et.meta": "7da6aa45467250edc910ad7230dc244d1b041e8a6f55881eb3747ce51f9212ba",
|
||||
"source/addons/core/Prefabs/ERR/PrisonDoor.et": "b0ff94443fe334032113a663917de23f920a8b73ffadc9c8e9f11b545022b3d2",
|
||||
"source/addons/core/Prefabs/ERR/PrisonDoor.et.meta": "b8f3db52bf186426026668fbb9d633c3cbd4d438ab301fba880398f6a0e781c2",
|
||||
"source/addons/core/Prefabs/ERR/PrisonPatrol.et": "dc88c31cf5c415573a874f74e13572f0add9e6122c8fcad507fe82860d789c47",
|
||||
"source/addons/core/Prefabs/ERR/PrisonPatrol.et.meta": "5528e0d778dce5ed39c3e504c6427625527127b23269d20fbf12ca2bffe52ffe",
|
||||
"source/addons/core/Prefabs/ERR/PrisonWall.et": "9b410b7c85bb001be4601ad93f750e17b8318b850306d84f29c4dc1b02723d7c",
|
||||
"source/addons/core/Prefabs/ERR/PrisonWall.et.meta": "0294bc5dbb56f90f8153d62459bb0a6ad91d76a479812bbec9c7db182fdb58d6",
|
||||
"source/addons/core/Prefabs/ERR/Prisoner.et": "e6d345ac98ad9ec742bf6c3b8686839c3256df9833d31bb4bdf605cd41d0ba5c",
|
||||
"source/addons/core/Prefabs/ERR/Prisoner.et.meta": "974278ba49fafeed70b619a0067bbc70ae4d534be441c812ce2bef4a5fb3c022",
|
||||
"source/addons/core/Prefabs/ERR/Radio.et": "99b1d80b49d1e7f9d30aa4283772a36fd66e962369f288f5fe329c7fc911bb1b",
|
||||
"source/addons/core/Prefabs/ERR/Radio.et.meta": "bc91137b68ba550217914fb8892bb44d7e1920e4a1086f3e506623832a44212f",
|
||||
"source/addons/core/Prefabs/ERR/RadioCamp.et": "5e6216bf8e6e160da5d9f966c8f7c2081bf6dd16dfac1b89d682a14b3b8a6716",
|
||||
"source/addons/core/Prefabs/ERR/RadioCamp.et.meta": "3cb8d3d553ab6d8d111a74f721cf4e69ee1011cbb90248b83cdc7275697276bd",
|
||||
"source/addons/core/Prefabs/ERR/ReconCrew.et": "33953379ceb725bcd0cbe505cd643c94adaed17dbbfa95dadd404d6b8e345715",
|
||||
"source/addons/core/Prefabs/ERR/ReconCrew.et.meta": "2653e8c5b1cdb857de5badd5959ddd9826a6a298ab3c166628dbb835d7104d90",
|
||||
"source/addons/core/Prefabs/ERR/ReconHelicopter.et": "c609ee59ab145e0a1936f95726b86df643f5cc425c43924029e9c1abc69ebbd0",
|
||||
"source/addons/core/Prefabs/ERR/ReconHelicopter.et.meta": "d80f1c3d6a6f9104562b89729996c1c92ad240f08cdcf48d4c390a09d2047c08",
|
||||
"source/addons/core/Prefabs/ERR/ReconPilotEast.et": "d961f329823b991eafed80d085de1bd89b44a4575be98d8dac385d6b77741ba2",
|
||||
"source/addons/core/Prefabs/ERR/ReconPilotEast.et.meta": "d73df3c896359a54514d2efcd851f579feca7a2619b76c2a38f607649a31a4f1",
|
||||
"source/addons/core/Prefabs/ERR/ReconPilotWest.et": "8f8221927269352e55c8026ee5b00e026c281c79af6684b386f24e7dc4675fb8",
|
||||
"source/addons/core/Prefabs/ERR/ReconPilotWest.et.meta": "4785f23bb492c6af420ee7896ddbfc9767e0db1e06de95207df2dc949a1b1814",
|
||||
"source/addons/core/Prefabs/ERR/ScoutEast.et": "b4593aab494c4f21637757b3daff4f349da77b4c48ec5e8a4a2917a6a12cf811",
|
||||
"source/addons/core/Prefabs/ERR/ScoutEast.et.meta": "7c72af632537f687e92f30b52d97fc7d70dadd39d33f37e0b1004f9596f55012",
|
||||
"source/addons/core/Prefabs/ERR/ScoutGroup.et": "8dc0fce8ee3decc1c367411b00b6d8518df9d8458281cec0881464a2ce906af0",
|
||||
"source/addons/core/Prefabs/ERR/ScoutGroup.et.meta": "62e43fd152ce57aa4ceb2187a49e4aecdeb9f428b3a1e8318f86bb83dbf8a259",
|
||||
"source/addons/core/Prefabs/ERR/ScoutRadioPack.et": "f1c4911e2556c0e0caa8b896982190c5e7d0433e850b4610e19442caf9117607",
|
||||
"source/addons/core/Prefabs/ERR/ScoutRadioPack.et.meta": "825506e3d814d30a52d5dbf64124470641c07a0453543ba71426841e6c783635",
|
||||
"source/addons/core/Prefabs/ERR/ScoutWest.et": "2681b5a3f8621adb44195f0dbca6f3e79ef7decad8f9d0dd0e1a801ec2549627",
|
||||
"source/addons/core/Prefabs/ERR/ScoutWest.et.meta": "22a6607b4b8fe606ca75a634a0b2ac3178e7bedae7f9ff01e7a4989f3b39a3da",
|
||||
"source/addons/core/Prefabs/ERR/SpectatorCamera.et": "cd2dcaca0df4c39816e582c594591a535525ed77827ffa3de24d27b79996544d",
|
||||
"source/addons/core/Prefabs/ERR/SpectatorCamera.et.meta": "2a16558f93915e31908a674509e9c89976470f78a84a1174a64b94b68b8f77ad",
|
||||
"source/addons/core/Prefabs/ERR/SupplyCache.et": "4c97b0514fe7e723046f40f0b396f6573b12eb9981ca5df70b9e8aa3cf29323e",
|
||||
"source/addons/core/Prefabs/ERR/SupplyCache.et.meta": "2f5de3a4aab1e9d0e35521f48dc57b95bd6e449c383dec4f1c258e10295904cb",
|
||||
"source/addons/core/Prefabs/ERR/SupplySite.et": "f33681281d26676fac88736091834d5a7b87fe0fa01883582542df964dcfc694",
|
||||
"source/addons/core/Prefabs/ERR/SupplySite.et.meta": "b41944b12eb3528ff7a3ac94258b18c66ef161aa6a38894aee300a1ac4798630",
|
||||
"source/addons/core/Prefabs/ERR/TerrainConnector.et": "cf9cb28f5a3f41931380864a29ac979aa1d5e843456f564ac7a7de78f88e1aa8",
|
||||
"source/addons/core/Prefabs/ERR/TerrainConnector.et.meta": "9f37c979ae282aabca29ce84beb0db851ee8b9a19f7f3a64d387c175616127f3",
|
||||
"source/addons/core/Prefabs/ERR/TerrainTakeover.et": "6206fe2eb4e2c6c1a9e3ddf2898535ae08981c115adc6ddd926017ac20d4b535",
|
||||
"source/addons/core/Prefabs/ERR/TerrainTakeover.et.meta": "64e953e378ab1d2a75ee7246f876f4ef93ae8a4e3fddb5002d7ba37268cb959d",
|
||||
"source/addons/core/Prefabs/ERR/Vehicles/SupplyUAZ.et": "29f157849f413261494a63d4d5b0a97e8bbe61cb076efcd59d6c940653f23352",
|
||||
"source/addons/core/Prefabs/ERR/Vehicles/SupplyUAZ.et.meta": "544c94cf1c26757a10654de7856cd6cc48b821ce3bdc02add13cfe6514269915",
|
||||
"source/addons/core/Prefabs/ERR/Vehicles/SupplyUAZRearSeats.et": "cd4acdcecad299445952aea0adefc85f2b9e9b43f8186f100e0505c5621b3656",
|
||||
"source/addons/core/Prefabs/ERR/Vehicles/SupplyUAZRearSeats.et.meta": "123955da03462befb90e293b3bb856d49cc761166611b38ff47cb48ec2fbe95c",
|
||||
"source/addons/core/Prefabs/Items/Equipment/ERRM_SharedFieldMap.et": "30dee8e9eab459ea32a7d835a9fb89d43df47708057cab829f067b25a24cd581",
|
||||
"source/addons/core/Prefabs/Items/Equipment/ERRM_SharedFieldMap.et.meta": "59093e9072c50d99c86da7609c87541016da5bcf92b98d99db4c524e1c8e0e8d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Actions.c": "cabb21413c90b252d29708b62228d0679c51c76e39ee0e483953ad7061b2b9d6",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Actors.c": "980d30964845600a261693cc5c5553e1472e8e54867bdc06133ff5c7b36c9128",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminMenu.c": "3b96a99832ed40002598a186dd8de1d21410c2e690df37a6319fdbeeeb4eeab0",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminPlayerTools.c": "56780d78bf423f54f482d8620f821b8d3eb0199194482b4f12e37f5ec3f55ef5",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminProvider.c": "62e05aceb49da07fed7aa89fb6b2f8eb3efc373ac09eff286fba983c3ad570eb",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminService.c": "c3e008c8bbf538c5bca3a82a975decc7a283a38543a9d2639d90a81ce592c51e",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminSession.c": "89d92f138a201ad7e752e027ba3930a2e0bf647d7b3a2c576346c1467f8bea3a",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_AirfieldPlacement.c": "0c2f4d31a2abc8f3f90bda20546543f2a1cf9306e9bf93351dda1883b990770e",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyGroundSupport.c": "26f0c7ebe8563bb022f7c383674e7d8997b0cc35c7ea321d39d74f2493c1ed9d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyLoadingFeedback.c": "e46988b92243df19a5400eca7406d6969b8b1174d8e3efad48fa0a936cbfdd07",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyLoadingGameMode.c": "f4cf19440583ac24346831a2d5f1d7f734c031e46dc266c499972329dd0533cf",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyLoadingOwner.c": "6346a05ddda030f7d9b6f026f977d5f018ee16002fa519e8c49dcd700c323dc7",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyLoadingService.c": "e6f22813f7a04e2c0ea000d054407191f2be8badfa6c51e062e9dbf84b95c67b",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ChatClient.c": "4bf937ff74e0483c17fa0103f73bfee3afd8f67a37c0c248b08772a17bfcc349",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ContentDefinition.c": "bc1dd4ed27ec894cf4bd617fb226cb8140b544aaa9ef6d8654e815d81e7f6fd0",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ContentMenu.c": "c82b173496e7524b4570b2afc5493cb970252a19aed740a53011988db7700a01",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ContentPolicy.c": "3a4987345d5a7159234a7e1a08bf5ac40dd5a23031e9b1953fc43a0501d9924b",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ContentSettings.c": "572cc36f88255a37e8f0e9f284fb96e07c6c4032506b34b8c77d688f02785400",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_DebugAI.c": "bc5529c60591a6c36c39cdb753b1af948690fc3c3c725f38a8d595b41a499235",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_DebugIntel.c": "a9f6e7e42a3214879a21052e897f9afc0653c12ff15d5bee7766e26a1af6ab17",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_DiscoveryMap.c": "dd350bdda1bdf427ab8cefab623fe60cce5332b062d1a29686fe52f73e9e83f1",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_DiscoveryService.c": "34458b3a4f7062375c9c5b5599308e9cea67fc4a316420836f6694ca2c646ffc",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_DocumentComponent.c": "885c8ab4fc9e64c3f8b40056536096c8c32b011cb340b25ca00353a96da15c69",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_EnvironmentService.c": "c0fae5bf51ccf507bc84d44adc2d1dff021cd83653c0468b7645a4f343e3fc8d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Epinephrine.c": "e04c53c2f665997023b2daee744265cd22f4f0101444e4d9b0efbd114f74fa9a",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_EscapeGameOverScreenInfo.c": "6e3c65e55b05cf205040c310b9086faa41b88582c7f9faf49c010afd59da5b07",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ExtractionPlacement.c": "6d388fe21f08b25cbdb5dfa4e198d94a4c80c5092f8d17630a4654e18bf8b3f5",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ExtractionService.c": "91357099b4e0401196b67d48963be54be30e56bdba57cdac67dc20b8ebb883e9",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_FactionCatalog.c": "a5a8c53acf21259e14f59cb919535910f30dabff5a9179c664bc6a7a4d744d6e",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_FactionMenu.c": "3549339d7796e67fc646680493c226e545b6fb95daa0270af9901795bdf8ed50",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_FactionSelection.c": "077c09491f4444fc58f093975fe9b3c294ea1fc966abef847ee5f13aa795ee29",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ForceLedger.c": "0ecaf1c5a52568e751678b0b1236e91e6adb538f8fbf010d38b61a312d1bf253",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ForceSimulation.c": "2bbb8888c752a3ffc042f3059937526d25ae288af5b4db024cc683025a2605ce",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_GameMode.c": "89a29c03ba225acbbb9fa3c58a721aced91a77bc0c77046d697005a6d7c48bb9",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_GeneratedSites.c": "4a23058f27e3ab074df6f8f7bb6f08a8fd26fbadb8943c6fb8d64dcc9c221751",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_InitialGuardRules.c": "8c9d6b1dc4c2af96284e34f487eebb5a221091016ef108006dec60b4e3836558",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Inventory.c": "b63e679d5b650b63a7a91dfc3f42a62f4be58b0338f6df3313e66d29a93bebf6",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_InventoryLayout.c": "1af5df45a0f06d19a017954e9bf4b2d722e2d2389f8ffdeb1d024435b9a08be8",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ItemPreferences.c": "1c4bc25a6ce9b5ee10f82592f955b0019d13ddb4084a783fadb98d267bd0f4fc",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ItemStationTeardown.c": "102e61216e86e47ad243cc19f6f66da1fcd8cc77f8799354ceaeb4a6dc74622e",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_JournalText.c": "87a6c19429f12c5630ed73170ca9a8a6d2255d6cd38b130166a78aacd15f2de0",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_LoadCasualtyAction.c": "1521af55a34110ce1c971b5226a618a9c6d931622abaae4946d9c0d27c05a273",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_LocalAdmission.c": "a076922d1ae966cf5cc67b198166ca6b1288358fb7f641207a4681e6a610a2ae",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Location.c": "5b0b058130ccac02bdc1dcd6474d51a6f45da4dd52ed6c37906692fca3f194b1",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_MissionRules.c": "f7abc38ad8fdc375ce7fa63a65f0bade027d22b37e09de5e3f94ba8c3c63cc41",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAdminMenuProbe.c": "ec8d04b6550b39b9688ef67b40cb2f14a9d98c8fff62b6dfb8d4a43e19b4e4c6",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAdminSettingsProbe.c": "73e58561e08e50008d33f81eed606dd4e8109fb69a627e892d28ca468d641f7d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAggressionProbe.c": "85a34cf60018e90d974cb67ab0f358f3073b6b9f02c563ec200e062f1d249e3b",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAirfieldMarkersProbe.c": "593e59664dbd7330b52674e5d4cc7b70db588cb75a1259ed808b74602501d541",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeBaseSmoke.c": "e811e985048e07365569acde6b5f045d57e9bbf13927f85b74e6e347fd2ef571",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeCasualtyGroundProbe.c": "41f40db3735f8aa535c0061458d9892dcfe972222b8a17238e67b65633c46bc3",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeCasualtyLoadProbe.c": "94c533deea654ec546df3f1ebb7cd213e6cd79b1125d99bab5303ef8e87b018b",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeCasualtyRemoveProbe.c": "4cfc06f6d43b709b63caae714155ffc562502e884f49a9825623c6f46972ad36",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeCasualtyServiceProbe.c": "02a9d70d1f4ba20326df199ba41489cfbae12b7bb0aab441361421cee38ad9ea",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeContentProbe.c": "cb0ccfe1e1575f9ed80a8054058b471f3543378db059e6af2fed8eb42a262638",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeContractsProbe.c": "421e4b901afe6118b6bf44e8f678db8ccdf1c83b39da0cf816baa36f7275ccdd",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeDefinitionProbe.c": "904d8d4c3e7b91d49dadfe495fc7b4f02f300e4aaf7efa348df5ca17ec4a6e8a",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeDiscoveryMapProbe.c": "9ed32d391d08d937ff4f9f33bd11c3a204ce9a2230c2d72b6761e0320b31f24f",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeEndProbe.c": "2dec80c7e247ec5c257407f95d9d5edd42fe0cc44d6af9f724f6ebd10d8a355f",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeEnemyLoadoutProbe.c": "0885ca69f6fa7f53414ce1792cfc3c49916886b8173783c634135c13c5d37429",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeEnvironmentProbe.c": "9e2e66ac5d9778a1c65445348e3300cbb90b68b3f669f3ddf1d2b78a858430eb",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeEnvironmentRestartProbe.c": "7a836a206381b8e8de24c92baf141beb30575723675dd6948d738169ed26b507",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeExtractionProbe.c": "4b09385f73206de004f4f3c38a6192fd658a0d2012482dc5a84dff1599ceb972",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFactionCatalogProbe.c": "e3011fa47b67122d7b2c23af8f91b7a217599d6cc114c4f9de628744b9c948d3",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFactionSelectionProbe.c": "946879d822e7be2d48e03a3140aa1aad3e3d44dd18507fa3cdedb4c6d7dd81b9",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFlightFootprint.c": "a8862a04ac784426f431e2e9cd3f1f19f820b38a081674d29549b8b00277c72d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFlightInputDiagnostics.c": "e231dcbdaefe81beb3bd587cb73be8fb3d3184bc86d18dbaa30a43ca4ba5dcc4",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeGeneratedSitesProbe.c": "83ab84ca4de7b545963896ed9d14e6545c23a2b940515730d74acc2f6b3dd18d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeGuardCancelProbe.c": "bfa1c65cb039e19c3d1891e4a3fd33469e974c97cc7f42128efc31a8f587d514",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeInfantryCombatProbe.c": "3e4c4382ab91f470357268927b954fd101685df6b2244df483f0422d6c0d7da2",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeItemStationTeardownProbe.c": "028588a49fa9207087cd27ec9396979cd932daa071e2490bd0262cd71dae30d9",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeLifecycleProbe.c": "b613a5dbe81c2032fd02d31070ae5631166d14d0b02cdbec3b63b782f0bbc115",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeLocalAdmissionProbe.c": "29c860ca3e51cdaa463f3c23a98ff45ee0499ce9bbc322046e0efbed587f1e09",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeMedicalCombatProbe.c": "3b9c557b249728c518f9d6b5cb24b725ecc32a69ae12df069cdfb0da70a80b95",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeMedicalProbe.c": "4b73e7cf35e9c8fddb089678a320ea58272e1b6611318d0a762754c171eff785",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeObjectiveLossProbe.c": "6b80fd317a8c6e8583bd4337870838a86251e3b8a681d0aa07e8b52e22abfc48",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeObjectiveMapProbe.c": "2d07b895cb74af58454605fb1c536a566733e3001a9375dd0677d5f274bf2a46",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeObjectiveProbe.c": "71fbd2479a70048f83d8b262ad1452f427be2c0afc8b071ef13bff477b9dc29b",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeOpeningToolsProbe.c": "0c5d6b96ed5a7cb1cf0d098d534dc7190449ed09339062e6b584729d53a61b4c",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeOptionalSiteProbe.c": "19fc19e22348e6213827f620f4fdb5dc26144ea2ce0032de773e79c1fb155a26",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativePatrolProbe.c": "5a2af71cc4cfccc7dd7c23584398a38290eba1a8894cd46f6967252ff3a7087c",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativePoweredFlightProbe.c": "7ae5d6f85bbbebec214c66bfdf6f53b93c802f109fcd5bcfbad82c5d61d6cb9f",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativePreparationStatusProbe.c": "456f4d7c3272b89d5f4c6713617baa5596d846994152356fee9a659839bcd8b5",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativePrisonBreachProbe.c": "4889e0d3799a6a21b9f84bcb2f2ae78dce16269cccd1329f8d1fcc1a23e7c22c",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativePrisonerProbe.c": "e2d1ffe5d269add55124601ff0d1dc032a398c7d51010736e6f0e4cbeb38ae86",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeProgressionIdentityProbe.c": "1d3fe20bce761a1082964bca9bad9ce79d1fa8b04db9b5053bae98da380ae560",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeRadioCampProbe.c": "67f1a088f9b20e5f0f11ed3aa083ffa772bffd7c74d85b7a307344ac3d47e09a",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeRadioDefenceProbe.c": "ff1e27a0ce75b123a86e7df31354831880ca62ea90b6c5d7c60d3ba168e1fff0",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeRadioInteractionProbe.c": "7b27552d233813894f65c08eb9f04b547c4ca9ff96a2370a763cb94bd4a555c3",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeRecoveryProbe.c": "d6691f22432b3ce37d07d448aeb3ce7feb5cd09e852e0167b5e4676afd24bb21",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeResultProbe.c": "c9a89cae067f221b9f33965b4d3ab311b78ba79ea383ca65032c4001df44b472",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeSiteGarrisonsProbe.c": "1a5ff8747d7501862085b5e9162043fee3b05e82c73c516ad8093aaada53dc60",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeSiteSurvey.c": "ac0203753ade0cdff6d483132797a80e4520f14546c3f9dea288281cd4cd9c4f",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeStationTeardownDiagnostic.c": "172248540932174341882861bb78a9720a6cf89981fcdf9dffe63f7fd4023f2c",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeTimeProbe.c": "4a2c6ffd947334a0a71eac083d10c853c524b00042e9ea0987497c4cee60c3d5",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeTransportProbe.c": "7a3fe04aa1c5ed1061ff63d9d5180e8b925932b62d76c1ffb49bd3dc23530993",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeTransportSurvey.c": "816df9a2a9072f9f7db75e56168d8a8fa1e665ee8f7dfa79af011b354254909d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeVehicleSecurityProbe.c": "59bce863142e4fba4b6fb2f544bb8a58061f0e99b1a38e5ac291cea919563763",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ObjectiveDetails.c": "628ebd166dcb5544c2d18dce489619984887ee18296cf2446fc6d894f89dd5bf",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ObjectiveMapPresentation.c": "f189f8987244e10df61ac577bbbc952ed5c4e6c431a8e3cd192a10fe2e8c3bec",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ObjectiveText.c": "8d75b35ab977be0cb1a2e3d3d1cb8ef875cdbfba69c35784c3d195451ef944c6",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Objectives.c": "b9cd5bb3b193c20401175c4328405be1b121e8a60b7b5999910b6a71f834af8a",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Observer.c": "682aa5549470c69fc72d261fbfcf9f7a04a41a66e0101b269ccc00bc282ad05d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_OrdinaryGateObserver.c": "1e376ca83c0005cf532539e14d7f47363c47b7c5b03fe3d55405a59208705fd7",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_OrdinaryInputObserver.c": "808a46cc1e4b31b65dbbbcdd55493f594ebb3974bbec38b4a2402334c653c0ef",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_OrdinaryLookObserver.c": "d5a1b636938d65e9d11c78b31487f2924400c34d98e2ec812954a2a224da7dc0",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_OrdinaryScenarioLaunch.c": "a4e7e56d174ebd15b4730202dae4c8ed06144f3f27c23ed49c99e2d297dc421a",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerAdminCommands.c": "eca9baa3b07da48a740851583540840f8bf5f65f7be854902a3778f76967faad",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerEscapeResult.c": "3124ab4d2d6d471409a47aba0af528790734df53243c03fe0cdac3e407047c14",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerGuide.c": "e49bab76a015ab545088af7e5eaa3cc45811907db4e5b1c5fa8c18afef34b62f",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerMedical.c": "270454d50235bc28df9bba4fde2689934578874c4eca9560afb9f0f6324d7215",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerRoster.c": "c038dac0f749bd29ebc35a4e952904b41a34417ba738904d5efcd1833a263e0b",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PreparationStatus.c": "43a406822a0361f916abc363f27e0c578ee94855036981d876bf47c68233c71a",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonAI.c": "8709753e86dc2ca777183f08cb8fbb9851e0c0de495ca01520ebcb1b3dfa59b9",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonEscapeService.c": "535cf17e21fc8e62716c7d9da88d976ee2f526501c6a4752b822f1252e742bf4",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonPatrol.c": "284618391ee2da84dbcda4a99ca3c072eae3d67b8a9ef40a86827b9ea00810f9",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_RadioDefenceService.c": "f5f0bf1352141f933d0edb5630e30541e001dc07e1d2c8529b29cc159c126b13",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_RadioFeedback.c": "545262e65e9b3645d9e514a0521e442fe08f0c2e4e7c83ba638c5105d09818db",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_RecoveryService.c": "86f9a7769e3ccb19fc61127fe2fee2ad0dd825487a5cd59f334de8b9741c93cf",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Resources.c": "d0169aac6fd0c38928c47a9002ded0fd8ba558ea3314a600e792d307ac1ca3ee",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ScenarioComponent.c": "81bf30d358c7b100248be17cbc2e6beb2f107300c939aede8a92d273eb7dae1f",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ServerItemCatalog.c": "e306b9d179b97d0478f821be3ca606c71908a21a4f87085b37a5fd18c4e3575d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ServerItemsMenu.c": "c0c3d9d1cf4615f38c793f1250315bbdb9349f33afa0841851da89433a303c3e",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Settings.c": "1b466886e9f5fbde1de0be20395e3887046c6b5a9a239dae92cecbfb721714c2",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SiteDefinition.c": "2088c45798f0eced702e0abd97550b8d1fc97ebcc34c3d497978b7424f6c670d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SiteDiscoveryRules.c": "dcbce3b7aee89bfc47a50e9de89209758af1f1bb462b99af67a8ad7a26e9f229",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SiteService.c": "15a28876954bbbe0e80d5b5b19e7336f154023cd05b67d65dd709ae7fd9ac712",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SiteSquads.c": "183883783a4e8399cf62851a4cc65a5d091d25131bc53b4323cf17286315b2e0",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnClientScene.c": "b56f99a91cdc53bdb93d320d10839339022d7e61e6b101eee8296271abd7d3cb",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnFinalization.c": "c949642366ad124dd2abc4111cd598eb94aa257fbae01b6fb3a0f1882a23e83e",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnLogic.c": "47a39c951be71bfcf1cc50526d507d0f9d8ef2fc09408697b6fe6b0dc5a529e2",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnPlacement.c": "270bf465808d23627a11e720c6632d4fea35d0c679e63aa64046ef8874d68ceb",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnSceneInventory.c": "76b79d5bd9d1f367e1ed19724302b7d49f8b0ede85cf19e89c452582ef651f8f",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnSceneLease.c": "20de7f96bacc9037580d88d4424664b4554b2c082d82e7d29913e9dfe390b594",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Supplies.c": "752e8a56b0b8cde33cf532032cb0a203553017b686faac2e19bee06f7a9c0713",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainCatalog.c": "ba2e68543a8c929492d06f8725a743d26849a630d6f8c09be0f23894f92d0990",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainMenu.c": "1da542ef60ff7c1897b1f12432c636ef6a08cc710bac520ef186589d506e9a54",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainPreference.c": "ec25e5c3a5b97527f9cd70341c10d69d7124048089d26883ac2f8c9b3fd2815d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainSelection.c": "ee75cac068b99e7403f5eaabe556152513cf5d973602cc6e6b8967d25402f6ad",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainSites.c": "63ad027dac5bafb9e93805c361cbb27bf82af0567ea181a760ddedea98204c06",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeover.c": "487f1d004aa4f7a5f58c12c37724b26fcd54fc62b4096d48f3a7436d9958274c",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeoverClient.c": "458b84b3fb31c5a2bd1b7c3d65f25e0aeab91f5505ef0813231435c8a3c7d2b7",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeoverManagers.c": "5b7661a5617b7124a10d3c18e087a4e2363a967eecc5c87ecc94573f2abc07f2",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeoverPresentation.c": "d66a29a44e999cc3f2e56ba9c3c6bc936c027747312e08778ce301c1837f2112",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeoverSettings.c": "da22775930b13e41d4a71409e37af3bb99e4cc1d94bdea0e3b59fbdcd4d40132",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TimeService.c": "63867760876d523a1794f619118a52c5cd387d5d92756cd286b2c16a348a6c7b",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_UnconsciousCameraProbe.c": "66b1c4591b0ecc67cb08418a115bb02ed2b0168b7ae970f1e0a1ea335c59dc5b",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_UnconsciousWeapon.c": "24d31bc857486638e55c605283c17cde0cdbd3c5c6021eac1ec93611387b10d1",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_VehicleSecurityActions.c": "bd7d0aeb4abcc9d8044e4888f9a92f9e5fc97c098bdfa3bbad57e1a29697a779",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_VehicleSecurityComponent.c": "2ffec4e646584ec546147fc4b08249825cb32b531aba26467b586d760485adc3",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ViewDistance.c": "8514f72f8207f12570d2317e64094a45507a1647dfd45a1501499ef81e90189f",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AirAmmoMission.c": "0a471a40c8f7dfb797d8d35e41c5b1ff91e8d2ab13b43cf866e46c0e4ab4ed9d",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AirAssaultLoad.c": "5554994115cd7d56152ac78ba53034bf934b71c5634b17d35e96884dbb3b8a24",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AirAssaultSystem.c": "2eaf9816eee3e1cd2ac70744a6ef7ea5a90d0a3eebdf925e384028a7edde6a42",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AirReconSystem.c": "f8a0e3cf4552d8133efd33c2126ea15a7694676773a7047c15e00021c1d9721e",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AirSupportPolicy.c": "b5dad011d5a0574a406d6469e0744a9d37700cb41930dada28c5143d556acf53",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftAmmo.c": "2be282406d0c45ab2e35b0ced791b5e494c662588f536701a4e82e6f5fb7c913",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftControlBridge.c": "b8f0141644d8f043c6db4c2d4bb93215c548e5c27ab5468c66e996d62bdf905a",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFieldEnvelope.c": "0f53c7d9ab167a804eb904d63725decebb53fd5796fdf27864a75abed5679838",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFieldFlight.c": "c04e264cff9963821852094c451502d31bf9c96d4deae2e8ff8a2373b53b5665",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFieldRules.c": "30be68f4ca2db7e169f6f0432815821179cddf9159f7b150341dc8eb479bbd17",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFlight.c": "aa25a8e67a30c48677bf528236402b7f8e5d815dc18df93b878520ad3d1fe8a7",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFlightEnvelope.c": "8125cef61fb283d0d7c4dd2df3c04b062b448f1101fd48dd53f4f4097df5fef3",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftRouteEnvelope.c": "e8fcef844239c47a1f2f36be420afe943bc450091b05859435406b46c87fa511",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftRouteFlight.c": "1d8d92bf6d97429d68a9f62018232e90cc124cc8d7445efeabe863706a31e2b9",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftService.c": "3f05209227986b5c6bfb193f8f53783cfd4ef083bce898e22257c3e63daed913",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AirfieldSupport.c": "c6d88ede0b1b6bac5a7075b6e2e783ccfa8850210aabd28bfa4bcdb698cc5f87",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AssaultParachute.c": "a93c996059e7166988e9d1b0b498cbfd36f19a1cf8520cb4e9215a8884752e18",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AutomaticEquipment.c": "5832cbd3a43748e77f4e7f1b59361801c6d0445e0e15165e97d7a897b338709e",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_BodyRecovery.c": "47d9374095d04f5f1339c220caf518a40938ffc20f891b1b51ae38579e7e1c25",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyBoardingProgress.c": "328f8a5eabb8174b7727eee1d675db83a2eb0be7b8e834db4e950a645ca5d7a3",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyBudget.c": "ca49c274146d56e30cc93fa1652cc34c0fe68ea95725b0b3e33ab3673a6463c4",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyCombat.c": "5c4b7576b28d51edea868cbb91a0ab31a40e6ddb558f1b8a38e07e20fdb2969d",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyMineStock.c": "4497d6b790a45df2b76d18541ddaf299b406def88b868caa29f096849026a42c",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyPlacement.c": "4d0e8b6e147486fb65db82a1060f0c5641c1319ba9e418bdec99cb5a422a7fbe",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyRoadPlan.c": "fae404f85cae63e63976938a5fdb73efc988ba25c5846564f12edca04fb88551",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyService.c": "b59016d83cb9d40136b98b4e0067ea490bc553574fc53603593efd5522dbed20",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyStartup.c": "360228fd45aa6ecd9426e36120b5e637d2feee1e3a4a89aac8207526b871c87e",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyEquipment.c": "c52d4a3cc0e71eb136487c42df2fcd5bd6da1c33d31dbd3d6429c237dcf4a8d9",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyGunnerSkill.c": "adf8bac5a6f7e40b2f9caff5fe9be590c4e4ce2b2b387ba39e741a3c4f4cc564",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyLoadout.c": "a48f32dbd7f209bf08fce2840aaffc1781c571fc679763be58987f6b082e776c",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyMapMarking.c": "0f161fd3e08a54e3e1063679127549e482c40253a022e9d06cd9ee4d740b8625",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyMedicine.c": "05d341a9a000bfa2084057bd67d476d6e35adca6c8518d74c27cd31b551bbb95",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyOptics.c": "759e0a88ff30cb781ee69b8a935865d63ede5b1d97f31d344018f650a967c37f",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyRadio.c": "3a97e5c3de9ff33873d97c6b2d84ae505cfc4f3146e047b928e76ec3b22c8789",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemySkillAwareness.c": "00c450d033e43fc45c9e2cb64a1d81161d123cc594a4292cfc5f68eb6c17ee60",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EngineerMine.c": "defb12924ea5dfe68f86c2bbb4b07362f016ffee810f720d13f01d81881b3cfc",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EngineerMinePosts.c": "bcddb72845189b52e5ed71c687d7dd4b0b40b91b7306c3f6edf84a631002fc5b",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EngineerMineSite.c": "d838f5693d4fa5d252d529e59777f560674c02532f1041a5598e938b3a850839",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_FiniteMagazineReservation.c": "8278590ced1936d618905b0cbd0b5aebddda238d426a6a2a52e455fc36bbb502",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotHQ.c": "c51fccd0ecdb0a1d6ba99ae965e2e572fc1ea65a5d8dc2e1e2a058698dae45c3",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotLoading.c": "6abb278409527bb67db084138a773de240d99ba7f63f9ac740f8167615d53f1d",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotTransfer.c": "21daa9ed8cb5f2dc08a0fa85e305fa4b4f3e7b01e16c71fd1ca98d66a4e8b652",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQ.c": "d873b5b689e918f8c907918d673304a184ac2e4a4cb6face527b37a67821ee9f",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQAdminProvider.c": "e9bb5f2f3ec270074964fc8607e5a07c23f224308a4446837598d93e201d7775",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQAmmoReporting.c": "95c024cbdd35c02d9b0c3d389d29bb042e5dda6ffd2f5f0d896078274b3adb35",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQAmmoSampler.c": "8bb0ec1422887feaa340307d3c60bae50fc82d424fce6390876e580ff8b75e8b",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQBodyObserver.c": "f59421c1e0c83f0f480d7dd4d048b4b0a41193ed8fe8f2f627d2b6a696420ea1",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQCoverage.c": "8d9668858c47b7e9fee2b12d3ebd4e7cb88146b817cf615c4b0dade26c81b2ec",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQDeliveredCasualties.c": "1f738127e55e843ee2705007cedb5c08741f52f63c75eca7c80242177af82273",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQDoctrine.c": "6335728e89ed40ce11b811f00b61bfea76e94dd3379e4357cbfc438b05522bb0",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQJournal.c": "53563ff54fc4e0656713d6eaec5e88ddf69fd4bfa8ef6a67cfa13380d24031e1",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQLocalAwareness.c": "124260280ac8eda0e920bfcfc86932c9b21df6b1f7a6aa8acfc43feea3da149f",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQLocalHandoff.c": "2dd700dae9d9b232d22ca63ff01af75a3f5cc213ac24b7c0a43ffa38bc0b9ffa",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQMemory.c": "ec2047a477fb4273e22ae6bb68e7365f321f55c583b5d2c48c4abf2ac38e3b7d",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQMineSampler.c": "2a0fdc4d27e947a1d77b02ae23f757c7fa074eb456f817b7df0766583d757f55",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQMountedAmmoSampler.c": "88ea0fc0e13d7e3c22c7ce8b652816d1d137e4e6e37a72f48f0bdf515b936ae7",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQMountedDispatch.c": "cee3ae301ac2f211c290450b644a7942c9786a2a40d06f16e2a47efa96fd15b6",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQMountedIntercept.c": "a37edcf66e43945f331db47fe81cb2e0e767a7aaf8115244dcf9e6295932be98",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQNetwork.c": "0b73be993628a55e3b21c8670d540e39c938093dd5cb4d586e800ac530509b25",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQObservation.c": "57ad3f0b68d150791e30a7e4bd7dfedfb1ddd78a1c76f228e67b33ea9cb7144e",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQPursuit.c": "ab6ca0e1a7f36c104e664db06a74c80a528cbfd1de599af42e2194ef0a4f4ca3",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQReport.c": "12ea8ba08753d1e6d38b237087c1209cd2f9574b53c3ff0f27c082bed029c9ea",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQRoadIntercept.c": "0897e82d7805ef56f05f2b9c23903280285ea6bfa51796a2df86bb564ece78f7",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQStatusSampler.c": "b937eaed913a5095afa8e678dc1c36b5c805541bf8cd5be927069533d6baed1c",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQTask.c": "1147904bae6d72e9de47ce17bdada3dab489de4ed6e781dbf15bdbb30599ff6e",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQWatch.c": "abe634cf6003ae920ec1ed18e305ed462920204960894520d3dd11f7e5ef1c33",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HelicopterAvailability.c": "60eaef2f6d4b2fd44861c5a4434ef97e732e40a5ff7401e2da451ed2dd9c2762",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HunterCombat.c": "df1c319d10efd07ed6f971cf0e41d8d7e377b04ea7f0fe143bf94df733fd1d9c",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HunterCrewRecovery.c": "e76af0fbf6f436a9c3c9d4c7b779bc08a78f6fe705c08bf6d9757bbeb65ee8eb",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HunterOpeningPlan.c": "0b6275221dab491f148426df05e132579f3acc20de5559226c3b38975618355c",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HunterService.c": "79369d5cc30cf628f02df0023157ab423e40497325dfd6a73b218757f2b689d4",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoAccess.c": "ab4262f78d54782c5ecbf5fff4ebe3da16d72329658d7e18c0c35387dc8b3c7d",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoTransfer.c": "99fa26beb0c0869d0cd694500f3bfc0705c2c1cf674dea90d98fb93a59570ef7",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryCombat.c": "5684fcbee128a35107312452297f7ae2bec28aaa1b63f619fa649f36df8ea476",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryMineTransfer.c": "02c399413f80879c22b4891e8ec807c67a6235677095fc4b98bafdc360d6944c",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c": "1bfc1079961eaecee0c1ebb434570aaeb359c008f9f309033b33582092557b35",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantrySupplyPool.c": "c8e454573cf064ff392291d6feebf1f23be64390b5b8e944c03dd065f9f46b42",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarAimSolution.c": "59e8343d09f7a44871d8d3335d6ad1d02216abb5deed30d38b5ec9ba3f2c0649",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarBattery.c": "157024afc8fd3c1ffeea6ae923ff091e5773b9ffcf5f5864f8040d001e689110",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarCourierTransfer.c": "968e58ca700b4a11e5e04a5c159696f514a0b1bce531210172b913e495f7e2b7",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarFiring.c": "f2597d44c10d10de2462aa5e5450a22b8a5ad0eb99bd0cc09a8cf1ca2dd4a350",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarLogistics.c": "b3624e4a00a2bdef16f6c100bbd79910e3bb8c2ae8ec5fe2ad5aa70bffecd303",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarPrediction.c": "05863b2b4f9f70cdb288f91c722cbea163c13f2a2927dc485482e5bd4fa7d57f",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarReadiness.c": "4c3799b3f2681e977669de0cbfaeb307d9a682b04365bfc9f59079e762965758",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarRefresh.c": "52ae8d9d6cad92f42d68c634091b80a474d2666b6c06d63a8c30a3fab71494c4",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarReportLedger.c": "42a96040b63e56677353e55164ae23031c90f70b4d6673a9f412ad7b19e636ae",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSalvo.c": "c128850c7a78a4d8fee00ad38f48b265f1fbd1d9b24b092ddc5c205b0f0ad6da",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarStation.c": "cbbd7c86f722b664c85ab7c070ae1131d2ce5c41d1dacb4381bff9c1720a1866",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSupplyTransfer.c": "ad71084f507ad9c32d3055e7ec6844a1ec5ddf568c0216ab8391e902b56e417c",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSystem.c": "bc290ee8bed299d869598cbf41ec281653e0cc7f3c64c7214613df8a0fc83829",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MountedAmmoPickup.c": "5f7ca5b31f3b405c2a6ca32ff91042f5b4dac6ab9640ce67fb10d7a74236ba69",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MountedAmmoTransfer.c": "0b195784497672fdaf651f336c14f7be98c257f98c85cfbeb4f96fe1a401999b",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MountedMagazineSeed.c": "b42d0aac142907433df8bedc40de24c94813544016cf5f451846f1980250f995",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MountedResupply.c": "c26ad43705765be1c20eca37fbe2978b8c647151f6620ed37141657a4b7dc312",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirAssaultProbe.c": "c1d55b338b157b758e6ffb993d5f689029b28b13929797c91e5dcb15b5e561ea",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirLogisticsProbe.c": "58fe863775d0ad575cb566c78cef696c9826691cf49ef9adde76376be7316db1",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirReconProbe.c": "c1216e0512a0268e4dbb82429e228334401c0c3cac52ba4486ae6dc91e41576d",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAircraftControlProbe.c": "0cf3e72ccdc42e6ef20fb71d743f0e037a9e69b2e082c720fa705628cf790205",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAircraftFieldProbe.c": "b64907c7566a894ca2f3c49ede5d972d4087a938da1a0ca87bcbd7c2203b2c52",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAircraftRouteProbe.c": "8d0dca97e5106d1c84b64992c789e1af0689514beefc027e713ca6ab901fc470",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarCourierProbe.c": "740c8bebbd4128a9311b1167d1058549475d6b46f81c9b6c0d19650f4b50616f",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarFiringProbe.c": "ee570d21bede8baebefc799399712d9582b3e30ebda7299f6c941777f02ad2a2",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarSalvoProbe.c": "fb9ccc6b36247ab3ad828ffbb2556abf5c2838d93ea6cd1ad259c0a015142f5e",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarStationProbe.c": "a110f0abc753cb1d2f781e457e637dd5346ecd2e924eb5eb3a5c7dca3d1e2340",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarTransferProbe.c": "399c21940ef10777b46fdb3e905430ce43404ce1de2f4a6bb62f9c61c1a0689c",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativePatrolHQProbe.c": "a58f57530e333976dc96fc5a0f9cb6cf0cb069c55788824950c5fb2f965d8e26",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeScoutProbe.c": "41b39b1abe5e51a5b8a428d533cccbfb0dda9d7a570228dc3489408c60543f17",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeTownProbe.c": "ade130f49fc9d868281cee7fde383f084f70ed8d4b876dacebbaed8538e84999",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ObjectiveDefence.c": "83ef91c2118521aedb4c1838b2e47909c80e0950086449b98ced168f1fd87080",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ReconAirports.c": "7551347d776d6e0eec818d6468cacbca7ac53daee7317e0a1618ca3d39ebc762",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ReconCrewLocks.c": "684bc5b9858c7ed90ed2ca6d52fc0e731a7e37a116db776090257b72a63621ab",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ReconFlightComponent.c": "4966dad504b3f8f28a9ffc8ac17cc548b00066fe05213c49c662ea56de34c9d4",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ScoutSystem.c": "63287a252e4e7d5aefce840279f26ce3e1f286cb79cadb32596c37897cec7119",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_SettlementSafety.c": "e5c0ebc95521a9a33a3f7d9cca6c551dda862a08b7af20b017877aba9584795b",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoyColumn.c": "35678ec625fb0a3c0871e2c373fcff49816440a97a165ed25c8798dd72ef059f",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoyService.c": "5b1578afbf6da736453cc9d3872979eddd1649746aa32d3b0c7a9e3cab50057e",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoySystem.c": "f09aa817c27d6af0ccfb544f4ab1ae2afafb63d626641e03d87cfe159475d821",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoyTactics.c": "dc3acdffc8ca48f11b131f66d30d679ca68f3b3004344bdc78723bc9305915e0",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_SupportScenario.c": "a7b46253e1bb37cea7c29bb557fbf43ca207022d0f1cc927349441b2d1615279",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_TownGarrisons.c": "57f862476751087972fc78d0b27ab44e72361e27d32f15d55f9fe7fd7d6bd0e0",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_VehicleAlarmPerception.c": "45ac71d25e10a057a26a5b0fc7128935baaf47f4c0f87208a4420fa52086fd98",
|
||||
"source/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelAdminProvider.c": "d63ab5c547021aeb61d398b8a773afeedee4662d3ce15d9fd9d0e9e37262f8b7",
|
||||
"source/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelDiscoveryFeedback.c": "62f2c408383f410782d9d41fa50acd6bd8cf66eeb80d2b79f91852b9d2cf8d97",
|
||||
"source/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelEvidence.c": "6bbf8d3b83e2c09fd9a23a9a5e5e11d7c29af2e618116bee613562fc45af2b33",
|
||||
"source/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelReroll.c": "d8b04de9ea789732cc78ebce9aa60786c86fe46d05f671cf251eefa68a214b59",
|
||||
"source/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelService.c": "2911325c79a7a372628b18ffa0e110d11919ce2c2cd7b19277bfd608fdb03dfc",
|
||||
"source/addons/core/Scripts/Game/ERR/20_Intel/ERR_MineIntel.c": "3ce16cebaa9703b2f9803df7c11614f94de6460a9136dab8f80dcad41ae2b1c2",
|
||||
"source/addons/core/Scripts/Game/ERR/30_Map/ERRM_NativeMapOwnershipProbe.c": "32418602f085e3edba7343f42a6a691630b533be262002f29248e8ae87a38254",
|
||||
"source/addons/core/Scripts/Game/ERR/30_Map/ERRM_SharedMapComponent.c": "3a10f6ea25bf88a400bc3e6c339823433845c5db4f2f423835ccf99a1b1a843f",
|
||||
"source/addons/core/Scripts/Game/ERR/30_Map/ERR_ScenarioMap.c": "75fa1d742129ef7f33c005cd48f56db7f49ee7bde3c5428532b0b501b032b0a3",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_AdminCommands.c": "282fe1463add7af8771aa58507b254e69d2d06f50274d4c77321db073f8394f0",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeAlarmHearingProbe.c": "5dbb6a48909b76cd141e3a79ef01d2e68cafee55153821c4471f85c761fff94f",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeConvoyCoverProbe.c": "d2450140cf9bdf09210473234605b4c0d818ea5b91f9532209166a35c5d13701",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeConvoyProbe.c": "4bdc920e87fa768b0ef0ed893c70ddbbcc9255d74163d7b657fd2ec7c4f14c32",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeHQBodyProbe.c": "811244cc8297817efbfc3ee4edf01c868eae23c88127ba0c72e98ee7422da72f",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeHQMemoryProbe.c": "d8fec6c138bb0f5bdbf99ee82ffc3ac9b44d1045d8833da63f8aa5f39beeb7e5",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeHQResponseProof.c": "0f8b09fd8753234c91fd6baaca0e2f812e409ae1c4be8f340b648ae59b69c2f3",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeInfantryTransferProbe.c": "9b2de4dc22bdadd51b0271219a971dc8dc07f70ed3534f306acf03ed81b29424",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeLocalHandoffProbe.c": "0d4d61c424a16008595f86fa61f3b848caf9bd6e9ebbacea9c10254d88ba378e",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMaintenanceProbe.c": "852b9b397efc3f919c97fec63bc3df1a850cd7833421af8441994afd191951d4",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMortarProbe.c": "ddb892141500c192c0787b011d57dd8c07dd8c9a3ca5fdc407f6c271897bde0a",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedAmmoProbe.c": "8d197f7a1398625e5a19db3284b0bf72c6ee6e032843a3e4d9a4e58de42b6825",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedCourierProbe.c": "12710e9e5548fe8856f7a52f3566338369a8a1eedf0bd92af16229271872ada5",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedInterceptProbe.c": "34b0b1e38a59f14c4e83d93ec412779945388e6f4d697bda2f6cb90f519a6372",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedSwapProbe.c": "a6721fcaaccadf8eddb06687c7d587d0a3e377d5d1bb0b8e72e630fede8690ac",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeRadioProbe.c": "84524163c63402755b4f834f74dfe6d8e5c397dc26031f532593c6f79f5a93b1",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeRandomRadiusTrace.c": "7e946406067092e30b6b75cc6ef0c56db7f866249e02bd13648156933ee578d9",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c": "595fce681ec74e0d3ffe7a29c527c1551874469108ded479bed72a0fcf6c732e",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSupplyConvoyProbe.c": "701311de6a2c9fe8f0534a22056323c34072df26595dc70a7d4df45bc06e6c13",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSupplyTravelProbe.c": "32e6074e912491f2643a24cb44311b9fe5b069c76e4e94a45e7409ac82d36507",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_OrdinaryScenarioLaunchChat.c": "a747af09599ce4d0c52051f18f00c4624d24d137e328341b580b82e896c6bf65",
|
||||
"source/addons/core/Scripts/GameLib/ERR/00_Core/ERR_DiagnosticNoSplash.c": "0ea1b402f8927b6d68bf6f7e5caa2967f7e3a39147634faab147796b791933b5",
|
||||
"source/addons/core/Scripts/WorkbenchGame/ERR/00_Core/ERR_ValidateBaseWorldPlugin.c": "49a38c37b51e5318c7dcbcb01543dd9a6300d053f0d39808b3974f4edc45b871",
|
||||
"source/addons/core/Scripts/WorkbenchGame/ERR/40_Chat/ERR_ValidateWorldPlugin.c": "f567518b54f43b88747df2838cdfd6ebb34605c0919a3e7d271d28dd8b67a9b6",
|
||||
"source/addons/core/UI/layouts/ERR/AdminMenu.layout": "e8d570f7bf3b8c4067ad81d47bca7f35514b2f8c8748f5fa5f775fbe27debeac",
|
||||
"source/addons/core/UI/layouts/ERR/AdminMenu.layout.meta": "9deeece996f43b1f1fed6b5ec89279645c7b6424250200a42580cc088142e9bf",
|
||||
"source/addons/core/UI/layouts/ERR/AdminValue.layout": "cd811af6d2fb187f01c74e20ea07ad85669546b0ad70efae2ce52921ce26cbca",
|
||||
"source/addons/core/UI/layouts/ERR/AdminValue.layout.meta": "56b3d2335db400c1308e07c4a35d278b23ef32013dfd6dc82951866327428d08",
|
||||
"source/addons/core/UI/layouts/ERR/ContentRow.layout": "62d2c95814c99d906266fa96c6112e04a7fab1667e1a05e558d1d3974adc2d76",
|
||||
"source/addons/core/UI/layouts/ERR/ContentRow.layout.meta": "8c4bc13b41e7aee38e0ca640a97813ed1a6964a00e2cff9e1fe4ebd71fc2fdc6",
|
||||
"source/addons/core/UI/layouts/ERR/ItemRow.layout": "8ac6fbc7fe0ce0ffc3185516197303bb892a4415948f75ae06f3bc289fefcac6",
|
||||
"source/addons/core/UI/layouts/ERR/ItemRow.layout.meta": "33eaef9c403ea3a030e58ec17f78e46af457048243571ad5856fff04101fb60b",
|
||||
"source/addons/core/UI/layouts/ERR/PauseModsButton.layout": "d21d436291e2c1b262e33dc228b0d60a1d188dc9e85cfda6d2373f8281431b79",
|
||||
"source/addons/core/UI/layouts/ERR/PauseModsButton.layout.meta": "9ed6adabd8f53eb9a562d7186789876bba5c4202155ca894c1af866ca47354f3",
|
||||
"source/addons/core/UI/layouts/ERR/PreparationStatus.layout": "bd269cf8dc6f27735423743dd5b78242550518414448a0256e5e12fa6b92c459",
|
||||
"source/addons/core/UI/layouts/ERR/PreparationStatus.layout.meta": "75b12176a443bb911fc4ad446982d762201fda42ed38736b79bc5439fca31ccc",
|
||||
"source/addons/core/UI/layouts/ERRMap/ObjectiveMapElement.layout": "b364752c44896d67dad07e466a04f4504a50813fb36ee7c34c9189ea9677b4e9",
|
||||
"source/addons/core/UI/layouts/ERRMap/ObjectiveMapElement.layout.meta": "8691fe2eaf46568bca4a9f8128b247a8da810bb87a5546aa7ca3334e740270d6",
|
||||
"source/addons/core/UI/layouts/ERRMap/SharedMapRenderTarget.layout": "6e83a9c70282aff43b23a08b732739e7a241a31e8abf200498c90a745d3d60dd",
|
||||
"source/addons/core/UI/layouts/ERRMap/SharedMapRenderTarget.layout.meta": "5c846445cc089e2e08899ba703059d4adb805ff30ab5a16409a3cd59718cbd54",
|
||||
"source/addons/core/Worlds/ERR_Everon.ent": "22324bc7eb0d80dec8a1f3bd61a9df9201b72f749f4e751766b0c9d0b7d46b87",
|
||||
"source/addons/core/Worlds/ERR_Everon.ent.meta": "19d1903ca72baa326b4724a6791d0da1104a1e53f3f31dc1ca41a856efd68e83",
|
||||
"source/addons/core/Worlds/ERR_Everon_Layers/default.layer": "6bcb7fbb27b6282719dae8a37486e518d4cbaea385f2ea9af1918b36bb28b175",
|
||||
"source/addons/core/addon.gproj": "73e973a1f1c5910393e16f86a3a40d792031bb2fa3fc7f4dd87a06a16c3e34a4",
|
||||
"source.zip": "a7b9d8106c2eae8fc8a3762937eb7d4df4907012892853b7ad932da75683f94d"
|
||||
}
|
||||
+434
@@ -0,0 +1,434 @@
|
||||
{
|
||||
"README.md": "f1025a0a5753041e2906c8f3016c77344bfe6d04a8403b1f991d2734772a51a4",
|
||||
"handoff.json": "2229ab3b5339c484c262ab9d934a49a7872bf2676e3d06fac074b831ab51a79b",
|
||||
"packages/core/addon.gproj": "73e973a1f1c5910393e16f86a3a40d792031bb2fa3fc7f4dd87a06a16c3e34a4",
|
||||
"packages/core/data.pak": "7125b375e05ed3319864400a232f6e2a115aaf82fea67e24553578d2906e7d99",
|
||||
"packages/core/resourceDatabase.rdb": "64e1e333d55d08ee240c69395a3c2bb51fac8e8653b3786c77694d386801d569",
|
||||
"source/BUNDLE-MANIFEST.json": "e8bd3eb58897d057514d1909e71f71b6f3cdf6f358b875dbada64877d3228c91",
|
||||
"source/BUNDLE-README.md": "c46c89a66c56aa6ba4349c50e66b8368bfe53914d1019912f961da83938ba4ad",
|
||||
"source/EXTERNAL-ADDONS.json": "172e62d5bb83a3423192205c2e002de0257170314d2fbca346cf8fd72a26ab1f",
|
||||
"source/addons/core/AI/BehaviorTrees/ERR/MortarRapidFire.bt": "16b263bcb2fb3ae361367a600753a829425620d2e6b350a891c51fba47437ab6",
|
||||
"source/addons/core/AI/BehaviorTrees/ERR/MortarRapidFire.bt.meta": "f2a44ece28891240e6bfa1d01af29428adcadbe82c80e287eb33cd5e58f1f90a",
|
||||
"source/addons/core/Configs/ERR/AdminMenus.conf": "a7f889f260e43656136fc159342129e5f48748d28c426f65f9faac37b624cf94",
|
||||
"source/addons/core/Configs/ERR/AdminMenus.conf.meta": "5faf5ddc0a51c1d0f82d60af00d91edc22fe9c39aac50d8d04b772a2c9271be1",
|
||||
"source/addons/core/Configs/ERR/Content/Registry.conf": "546a5a407c9e6c25c9157ae4392898fa3f40c04c7956649e62201f9ac0ba187c",
|
||||
"source/addons/core/Configs/ERR/Content/Registry.conf.meta": "046aa988bf8e972afcf7a60b6f2312f605f016f98625dbbd9cd75ebf9ea88800",
|
||||
"source/addons/core/Configs/ERR/EveronSites.conf": "b479000b36154a6a3af6b519b086251d981ef63cb86a973d00529499cfd4238c",
|
||||
"source/addons/core/Configs/ERR/EveronSites.conf.meta": "d5fe68025ef4e7c1e16082cf5873b7c7172eacbfaef4ab29b7e0e3c98f8dca56",
|
||||
"source/addons/core/Configs/ERR/Factions/MissionVehicles.conf": "5f74f4a7089c7e7b54ad62463159ce8f0bab25a6b85268dc3872ea6001e048fb",
|
||||
"source/addons/core/Configs/ERR/Factions/MissionVehicles.conf.meta": "00c368b6271d3440cc8bf627b03a384d247635723923fc5ad2104b8b4007b035",
|
||||
"source/addons/core/Configs/ERR/Factions/US.conf": "4c3da063abb6e3ee39a6e4e0c5a9ffd5eae9d209d58470ea18b45dba5528db1b",
|
||||
"source/addons/core/Configs/ERR/Factions/US.conf.meta": "a05469aef028e9e17eba545e81e2af2887b59f0fef17dac51a23c7b8155e381b",
|
||||
"source/addons/core/Configs/ERR/Factions/USSR.conf": "407ea27f80a64c5184c089d43cdd0bdabfc5974c84f1d2a245081fdf2afa3f30",
|
||||
"source/addons/core/Configs/ERR/Factions/USSR.conf.meta": "057397d97096346791b51b7b13fbe18af218bcf78e9984d9c01b49a2403de611",
|
||||
"source/addons/core/Configs/ERR/GameOverScreens.conf": "45231061911a1462d45fb6db0fecc2b0793f17b5ae71017174954ff4fbd20236",
|
||||
"source/addons/core/Configs/ERR/GameOverScreens.conf.meta": "eb654b745c0b97b41c991694569ef4877a3c2315e0826f9556337cd68690843e",
|
||||
"source/addons/core/Configs/ERR/ObserverInput.conf": "e898d645911e85b6ba902366cb23890d8bb14bbd2c485102e6d49ea728e9b054",
|
||||
"source/addons/core/Configs/ERR/ObserverInput.conf.meta": "9714dce6c38ee81bcc513c8ebef51d7af63fd15bcdda2e40946937c625dc3ba4",
|
||||
"source/addons/core/Configs/ERR/Tests/LegacySites.conf": "3864eb638d0ed4dd313013d2d787f975ae6ce4bbe238569919f76b73d5f7ca42",
|
||||
"source/addons/core/Configs/ERR/Tests/LegacySites.conf.meta": "097ac7daef4fc18344699a8471fdd77f9d158f8c70bab394068d7a08e4777ac0",
|
||||
"source/addons/core/Configs/ERR/VanillaFactions.conf": "db890b61b48ee15484041fd2245a862d9fa9e7ba21b1229c281ff37c448a35b1",
|
||||
"source/addons/core/Configs/ERR/VanillaFactions.conf.meta": "ac77725c0c21974991ef47a466b88122e939de8b46fd23e68889e7674cbb2bfd",
|
||||
"source/addons/core/Materials/ERRM_MapRenderTarget.emat": "9877c5b175c5f30dd80bea36c711b21ab38219aa7075adf9ae79932e1d4c76bc",
|
||||
"source/addons/core/Materials/ERRM_MapRenderTarget.emat.meta": "5ee1a705f8011a44020ca2691f5ccc17d44bf596fef9a36e98d1f267eb58fab0",
|
||||
"source/addons/core/Missions/ERR_Everon.conf": "936619df7789a6b4b80bd763f702526e1145ab4d5c300516c07e7e70dfe57d92",
|
||||
"source/addons/core/Missions/ERR_Everon.conf.meta": "0a23c98bf83873536c65fa17d38dea33a1d7b9e4ab210f90633ff688abcc551f",
|
||||
"source/addons/core/Missions/ERR_Everon_Base.conf": "b46e1f4aeef383a8dbe7ef2b5c12a55a8111856c52ba103a1e508c01b82dfc61",
|
||||
"source/addons/core/Missions/ERR_Everon_Base.conf.meta": "9b16267c644d815bcf98a3a3aaff30b93d7224fb24d3a2bac66730a28011f317",
|
||||
"source/addons/core/Prefabs/ERR/AssaultParachute.et": "b556997989605e2a05982418b7e9f26d12d427eb3ea6e3bc50e85c67ea7aa4b8",
|
||||
"source/addons/core/Prefabs/ERR/AssaultParachute.et.meta": "e9dea2d533ad1ce6ce689e0e2815c97a6382e1b90c35ce1efa88a885527e8e18",
|
||||
"source/addons/core/Prefabs/ERR/ConvoyCrew.et": "29a525a29605386dfcf292dc2316e9fc7650ce39db9fbaa4ce4372ad0de66db4",
|
||||
"source/addons/core/Prefabs/ERR/ConvoyCrew.et.meta": "0a909a15b7dcca34202ded136b3bdbbe8898153c9589e1cce1388433d362da02",
|
||||
"source/addons/core/Prefabs/ERR/Epinephrine.et": "e09c70b3d47a4dc5b92fd332c8222b99554b28a8a0c93cb5caac18eec4501571",
|
||||
"source/addons/core/Prefabs/ERR/Epinephrine.et.meta": "f1861f0b0ccace1b7b3d9c29768e37a83bf0c6fae5a411b1bd61d6b2eec7ed89",
|
||||
"source/addons/core/Prefabs/ERR/Extraction.et": "4d24c7811415c06386205e5bf5c132a23fcf21e96c75c7657ccd5f3ac914ac50",
|
||||
"source/addons/core/Prefabs/ERR/Extraction.et.meta": "c2a838633001e2e3a202d39cb33aa744ebcd996017ad032359069641b5d13853",
|
||||
"source/addons/core/Prefabs/ERR/FactionManager.et": "5a7b330f33956cc1781c8dc843e8186f2d37a98653ab36e7c42b9019df3c89f5",
|
||||
"source/addons/core/Prefabs/ERR/FactionManager.et.meta": "9bf53d5e4bcbe60dd1a4ece1409fc23c349055c860708620f5f6e9716290a97d",
|
||||
"source/addons/core/Prefabs/ERR/FieldCover.et": "e403d5cb3a5966f0cea81f15e0e825d482ba1a7a27b12498319ba45a414963b0",
|
||||
"source/addons/core/Prefabs/ERR/FieldCover.et.meta": "83461ffa76244e1d69f20b053a9741ccdf7d127009182bd540a7e5ba6150c3d9",
|
||||
"source/addons/core/Prefabs/ERR/GameMode.et": "4d3e5e2df28cbb8292c436ae05d4fc7e5ca789a123450a6968d9a718b6ecef20",
|
||||
"source/addons/core/Prefabs/ERR/GameMode.et.meta": "106769cd34525c9d440057072836cb7401a6752148c40edd7fe61c03bd58328c",
|
||||
"source/addons/core/Prefabs/ERR/Items/EmergencyRepairKit.et": "0157bc235eeb78a0e1373b561fd22a1dcb225c833ff7c2d4abae688bca0ec92a",
|
||||
"source/addons/core/Prefabs/ERR/Items/EmergencyRepairKit.et.meta": "da6f065cb2414b5a4cbe9ef0f0b1295b2466f26ad406c0bddb83845d4598efb3",
|
||||
"source/addons/core/Prefabs/ERR/MortarCrew.et": "21086e886fe3199624208c9a866f883ec109f7d08746c2b56b497e59857fb656",
|
||||
"source/addons/core/Prefabs/ERR/MortarCrew.et.meta": "fdfd4fcd21a67c3d698fa4aadc4e5c76e665cebf4be86013bc389e493fab63cc",
|
||||
"source/addons/core/Prefabs/ERR/ObjectiveDocument.et": "5118ecaf9d2038eea44a4b785f05d2e78781dc1387249aa58a6782c7e6752e14",
|
||||
"source/addons/core/Prefabs/ERR/ObjectiveDocument.et.meta": "eaba9903be147b98a1106e2273e2270773df73b9b22f2cd4e20136a8e281382e",
|
||||
"source/addons/core/Prefabs/ERR/Patrol.et": "d3eca8fe9197c57a27a285cdb3baf168b037b198d92b39df28a338ae2cfd0c74",
|
||||
"source/addons/core/Prefabs/ERR/Patrol.et.meta": "7c5da568fa2fcf0709ee2959253cb068d7c7ed7c2467af3b247a7e70efd96b69",
|
||||
"source/addons/core/Prefabs/ERR/Prison.et": "c0ca5219aa2d6322ba7d094b92000640b259112ff6611a745c0713c8875d09d4",
|
||||
"source/addons/core/Prefabs/ERR/Prison.et.meta": "2e426ef3de68f4107907854b51e818bc11d84649a01c538e3f18dd9ebec766bb",
|
||||
"source/addons/core/Prefabs/ERR/PrisonBackpack.et": "ae750f08fc9af645561f59d7e5809bd22f4cec26ca8fa6409d09730765958c91",
|
||||
"source/addons/core/Prefabs/ERR/PrisonBackpack.et.meta": "7da6aa45467250edc910ad7230dc244d1b041e8a6f55881eb3747ce51f9212ba",
|
||||
"source/addons/core/Prefabs/ERR/PrisonDoor.et": "b0ff94443fe334032113a663917de23f920a8b73ffadc9c8e9f11b545022b3d2",
|
||||
"source/addons/core/Prefabs/ERR/PrisonDoor.et.meta": "b8f3db52bf186426026668fbb9d633c3cbd4d438ab301fba880398f6a0e781c2",
|
||||
"source/addons/core/Prefabs/ERR/PrisonPatrol.et": "dc88c31cf5c415573a874f74e13572f0add9e6122c8fcad507fe82860d789c47",
|
||||
"source/addons/core/Prefabs/ERR/PrisonPatrol.et.meta": "5528e0d778dce5ed39c3e504c6427625527127b23269d20fbf12ca2bffe52ffe",
|
||||
"source/addons/core/Prefabs/ERR/PrisonWall.et": "9b410b7c85bb001be4601ad93f750e17b8318b850306d84f29c4dc1b02723d7c",
|
||||
"source/addons/core/Prefabs/ERR/PrisonWall.et.meta": "0294bc5dbb56f90f8153d62459bb0a6ad91d76a479812bbec9c7db182fdb58d6",
|
||||
"source/addons/core/Prefabs/ERR/Prisoner.et": "e6d345ac98ad9ec742bf6c3b8686839c3256df9833d31bb4bdf605cd41d0ba5c",
|
||||
"source/addons/core/Prefabs/ERR/Prisoner.et.meta": "974278ba49fafeed70b619a0067bbc70ae4d534be441c812ce2bef4a5fb3c022",
|
||||
"source/addons/core/Prefabs/ERR/Radio.et": "99b1d80b49d1e7f9d30aa4283772a36fd66e962369f288f5fe329c7fc911bb1b",
|
||||
"source/addons/core/Prefabs/ERR/Radio.et.meta": "bc91137b68ba550217914fb8892bb44d7e1920e4a1086f3e506623832a44212f",
|
||||
"source/addons/core/Prefabs/ERR/RadioCamp.et": "5e6216bf8e6e160da5d9f966c8f7c2081bf6dd16dfac1b89d682a14b3b8a6716",
|
||||
"source/addons/core/Prefabs/ERR/RadioCamp.et.meta": "3cb8d3d553ab6d8d111a74f721cf4e69ee1011cbb90248b83cdc7275697276bd",
|
||||
"source/addons/core/Prefabs/ERR/ReconCrew.et": "33953379ceb725bcd0cbe505cd643c94adaed17dbbfa95dadd404d6b8e345715",
|
||||
"source/addons/core/Prefabs/ERR/ReconCrew.et.meta": "2653e8c5b1cdb857de5badd5959ddd9826a6a298ab3c166628dbb835d7104d90",
|
||||
"source/addons/core/Prefabs/ERR/ReconHelicopter.et": "c609ee59ab145e0a1936f95726b86df643f5cc425c43924029e9c1abc69ebbd0",
|
||||
"source/addons/core/Prefabs/ERR/ReconHelicopter.et.meta": "d80f1c3d6a6f9104562b89729996c1c92ad240f08cdcf48d4c390a09d2047c08",
|
||||
"source/addons/core/Prefabs/ERR/ReconPilotEast.et": "d961f329823b991eafed80d085de1bd89b44a4575be98d8dac385d6b77741ba2",
|
||||
"source/addons/core/Prefabs/ERR/ReconPilotEast.et.meta": "d73df3c896359a54514d2efcd851f579feca7a2619b76c2a38f607649a31a4f1",
|
||||
"source/addons/core/Prefabs/ERR/ReconPilotWest.et": "8f8221927269352e55c8026ee5b00e026c281c79af6684b386f24e7dc4675fb8",
|
||||
"source/addons/core/Prefabs/ERR/ReconPilotWest.et.meta": "4785f23bb492c6af420ee7896ddbfc9767e0db1e06de95207df2dc949a1b1814",
|
||||
"source/addons/core/Prefabs/ERR/ScoutEast.et": "b4593aab494c4f21637757b3daff4f349da77b4c48ec5e8a4a2917a6a12cf811",
|
||||
"source/addons/core/Prefabs/ERR/ScoutEast.et.meta": "7c72af632537f687e92f30b52d97fc7d70dadd39d33f37e0b1004f9596f55012",
|
||||
"source/addons/core/Prefabs/ERR/ScoutGroup.et": "8dc0fce8ee3decc1c367411b00b6d8518df9d8458281cec0881464a2ce906af0",
|
||||
"source/addons/core/Prefabs/ERR/ScoutGroup.et.meta": "62e43fd152ce57aa4ceb2187a49e4aecdeb9f428b3a1e8318f86bb83dbf8a259",
|
||||
"source/addons/core/Prefabs/ERR/ScoutRadioPack.et": "f1c4911e2556c0e0caa8b896982190c5e7d0433e850b4610e19442caf9117607",
|
||||
"source/addons/core/Prefabs/ERR/ScoutRadioPack.et.meta": "825506e3d814d30a52d5dbf64124470641c07a0453543ba71426841e6c783635",
|
||||
"source/addons/core/Prefabs/ERR/ScoutWest.et": "2681b5a3f8621adb44195f0dbca6f3e79ef7decad8f9d0dd0e1a801ec2549627",
|
||||
"source/addons/core/Prefabs/ERR/ScoutWest.et.meta": "22a6607b4b8fe606ca75a634a0b2ac3178e7bedae7f9ff01e7a4989f3b39a3da",
|
||||
"source/addons/core/Prefabs/ERR/SpectatorCamera.et": "cd2dcaca0df4c39816e582c594591a535525ed77827ffa3de24d27b79996544d",
|
||||
"source/addons/core/Prefabs/ERR/SpectatorCamera.et.meta": "2a16558f93915e31908a674509e9c89976470f78a84a1174a64b94b68b8f77ad",
|
||||
"source/addons/core/Prefabs/ERR/SupplyCache.et": "4c97b0514fe7e723046f40f0b396f6573b12eb9981ca5df70b9e8aa3cf29323e",
|
||||
"source/addons/core/Prefabs/ERR/SupplyCache.et.meta": "2f5de3a4aab1e9d0e35521f48dc57b95bd6e449c383dec4f1c258e10295904cb",
|
||||
"source/addons/core/Prefabs/ERR/SupplySite.et": "f33681281d26676fac88736091834d5a7b87fe0fa01883582542df964dcfc694",
|
||||
"source/addons/core/Prefabs/ERR/SupplySite.et.meta": "b41944b12eb3528ff7a3ac94258b18c66ef161aa6a38894aee300a1ac4798630",
|
||||
"source/addons/core/Prefabs/ERR/TerrainConnector.et": "cf9cb28f5a3f41931380864a29ac979aa1d5e843456f564ac7a7de78f88e1aa8",
|
||||
"source/addons/core/Prefabs/ERR/TerrainConnector.et.meta": "9f37c979ae282aabca29ce84beb0db851ee8b9a19f7f3a64d387c175616127f3",
|
||||
"source/addons/core/Prefabs/ERR/TerrainTakeover.et": "6206fe2eb4e2c6c1a9e3ddf2898535ae08981c115adc6ddd926017ac20d4b535",
|
||||
"source/addons/core/Prefabs/ERR/TerrainTakeover.et.meta": "64e953e378ab1d2a75ee7246f876f4ef93ae8a4e3fddb5002d7ba37268cb959d",
|
||||
"source/addons/core/Prefabs/ERR/Vehicles/SupplyUAZ.et": "29f157849f413261494a63d4d5b0a97e8bbe61cb076efcd59d6c940653f23352",
|
||||
"source/addons/core/Prefabs/ERR/Vehicles/SupplyUAZ.et.meta": "544c94cf1c26757a10654de7856cd6cc48b821ce3bdc02add13cfe6514269915",
|
||||
"source/addons/core/Prefabs/ERR/Vehicles/SupplyUAZRearSeats.et": "cd4acdcecad299445952aea0adefc85f2b9e9b43f8186f100e0505c5621b3656",
|
||||
"source/addons/core/Prefabs/ERR/Vehicles/SupplyUAZRearSeats.et.meta": "123955da03462befb90e293b3bb856d49cc761166611b38ff47cb48ec2fbe95c",
|
||||
"source/addons/core/Prefabs/Items/Equipment/ERRM_SharedFieldMap.et": "30dee8e9eab459ea32a7d835a9fb89d43df47708057cab829f067b25a24cd581",
|
||||
"source/addons/core/Prefabs/Items/Equipment/ERRM_SharedFieldMap.et.meta": "59093e9072c50d99c86da7609c87541016da5bcf92b98d99db4c524e1c8e0e8d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Actions.c": "cabb21413c90b252d29708b62228d0679c51c76e39ee0e483953ad7061b2b9d6",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Actors.c": "980d30964845600a261693cc5c5553e1472e8e54867bdc06133ff5c7b36c9128",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminMenu.c": "3b96a99832ed40002598a186dd8de1d21410c2e690df37a6319fdbeeeb4eeab0",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminPlayerTools.c": "56780d78bf423f54f482d8620f821b8d3eb0199194482b4f12e37f5ec3f55ef5",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminProvider.c": "62e05aceb49da07fed7aa89fb6b2f8eb3efc373ac09eff286fba983c3ad570eb",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminService.c": "c3e008c8bbf538c5bca3a82a975decc7a283a38543a9d2639d90a81ce592c51e",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminSession.c": "89d92f138a201ad7e752e027ba3930a2e0bf647d7b3a2c576346c1467f8bea3a",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_AirfieldPlacement.c": "0c2f4d31a2abc8f3f90bda20546543f2a1cf9306e9bf93351dda1883b990770e",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyGroundSupport.c": "26f0c7ebe8563bb022f7c383674e7d8997b0cc35c7ea321d39d74f2493c1ed9d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyLoadingFeedback.c": "e46988b92243df19a5400eca7406d6969b8b1174d8e3efad48fa0a936cbfdd07",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyLoadingGameMode.c": "f4cf19440583ac24346831a2d5f1d7f734c031e46dc266c499972329dd0533cf",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyLoadingOwner.c": "6346a05ddda030f7d9b6f026f977d5f018ee16002fa519e8c49dcd700c323dc7",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyLoadingService.c": "e6f22813f7a04e2c0ea000d054407191f2be8badfa6c51e062e9dbf84b95c67b",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ChatClient.c": "4bf937ff74e0483c17fa0103f73bfee3afd8f67a37c0c248b08772a17bfcc349",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ContentDefinition.c": "bc1dd4ed27ec894cf4bd617fb226cb8140b544aaa9ef6d8654e815d81e7f6fd0",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ContentMenu.c": "c82b173496e7524b4570b2afc5493cb970252a19aed740a53011988db7700a01",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ContentPolicy.c": "3a4987345d5a7159234a7e1a08bf5ac40dd5a23031e9b1953fc43a0501d9924b",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ContentSettings.c": "572cc36f88255a37e8f0e9f284fb96e07c6c4032506b34b8c77d688f02785400",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_DebugAI.c": "bc5529c60591a6c36c39cdb753b1af948690fc3c3c725f38a8d595b41a499235",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_DebugIntel.c": "a9f6e7e42a3214879a21052e897f9afc0653c12ff15d5bee7766e26a1af6ab17",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_DiscoveryMap.c": "dd350bdda1bdf427ab8cefab623fe60cce5332b062d1a29686fe52f73e9e83f1",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_DiscoveryService.c": "34458b3a4f7062375c9c5b5599308e9cea67fc4a316420836f6694ca2c646ffc",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_DocumentComponent.c": "885c8ab4fc9e64c3f8b40056536096c8c32b011cb340b25ca00353a96da15c69",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_EnvironmentService.c": "c0fae5bf51ccf507bc84d44adc2d1dff021cd83653c0468b7645a4f343e3fc8d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Epinephrine.c": "e04c53c2f665997023b2daee744265cd22f4f0101444e4d9b0efbd114f74fa9a",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_EscapeGameOverScreenInfo.c": "6e3c65e55b05cf205040c310b9086faa41b88582c7f9faf49c010afd59da5b07",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ExtractionPlacement.c": "6d388fe21f08b25cbdb5dfa4e198d94a4c80c5092f8d17630a4654e18bf8b3f5",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ExtractionService.c": "91357099b4e0401196b67d48963be54be30e56bdba57cdac67dc20b8ebb883e9",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_FactionCatalog.c": "a5a8c53acf21259e14f59cb919535910f30dabff5a9179c664bc6a7a4d744d6e",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_FactionMenu.c": "3549339d7796e67fc646680493c226e545b6fb95daa0270af9901795bdf8ed50",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_FactionSelection.c": "077c09491f4444fc58f093975fe9b3c294ea1fc966abef847ee5f13aa795ee29",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ForceLedger.c": "0ecaf1c5a52568e751678b0b1236e91e6adb538f8fbf010d38b61a312d1bf253",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ForceSimulation.c": "2bbb8888c752a3ffc042f3059937526d25ae288af5b4db024cc683025a2605ce",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_GameMode.c": "89a29c03ba225acbbb9fa3c58a721aced91a77bc0c77046d697005a6d7c48bb9",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_GeneratedSites.c": "4a23058f27e3ab074df6f8f7bb6f08a8fd26fbadb8943c6fb8d64dcc9c221751",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_InitialGuardRules.c": "8c9d6b1dc4c2af96284e34f487eebb5a221091016ef108006dec60b4e3836558",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Inventory.c": "b63e679d5b650b63a7a91dfc3f42a62f4be58b0338f6df3313e66d29a93bebf6",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_InventoryLayout.c": "1af5df45a0f06d19a017954e9bf4b2d722e2d2389f8ffdeb1d024435b9a08be8",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ItemPreferences.c": "1c4bc25a6ce9b5ee10f82592f955b0019d13ddb4084a783fadb98d267bd0f4fc",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ItemStationTeardown.c": "102e61216e86e47ad243cc19f6f66da1fcd8cc77f8799354ceaeb4a6dc74622e",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_JournalText.c": "87a6c19429f12c5630ed73170ca9a8a6d2255d6cd38b130166a78aacd15f2de0",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_LoadCasualtyAction.c": "1521af55a34110ce1c971b5226a618a9c6d931622abaae4946d9c0d27c05a273",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_LocalAdmission.c": "a076922d1ae966cf5cc67b198166ca6b1288358fb7f641207a4681e6a610a2ae",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Location.c": "5b0b058130ccac02bdc1dcd6474d51a6f45da4dd52ed6c37906692fca3f194b1",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_MissionRules.c": "f7abc38ad8fdc375ce7fa63a65f0bade027d22b37e09de5e3f94ba8c3c63cc41",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAdminMenuProbe.c": "ec8d04b6550b39b9688ef67b40cb2f14a9d98c8fff62b6dfb8d4a43e19b4e4c6",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAdminSettingsProbe.c": "73e58561e08e50008d33f81eed606dd4e8109fb69a627e892d28ca468d641f7d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAggressionProbe.c": "85a34cf60018e90d974cb67ab0f358f3073b6b9f02c563ec200e062f1d249e3b",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAirfieldMarkersProbe.c": "593e59664dbd7330b52674e5d4cc7b70db588cb75a1259ed808b74602501d541",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeBaseSmoke.c": "e811e985048e07365569acde6b5f045d57e9bbf13927f85b74e6e347fd2ef571",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeCasualtyGroundProbe.c": "41f40db3735f8aa535c0061458d9892dcfe972222b8a17238e67b65633c46bc3",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeCasualtyLoadProbe.c": "94c533deea654ec546df3f1ebb7cd213e6cd79b1125d99bab5303ef8e87b018b",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeCasualtyRemoveProbe.c": "4cfc06f6d43b709b63caae714155ffc562502e884f49a9825623c6f46972ad36",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeCasualtyServiceProbe.c": "02a9d70d1f4ba20326df199ba41489cfbae12b7bb0aab441361421cee38ad9ea",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeContentProbe.c": "cb0ccfe1e1575f9ed80a8054058b471f3543378db059e6af2fed8eb42a262638",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeContractsProbe.c": "421e4b901afe6118b6bf44e8f678db8ccdf1c83b39da0cf816baa36f7275ccdd",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeDefinitionProbe.c": "904d8d4c3e7b91d49dadfe495fc7b4f02f300e4aaf7efa348df5ca17ec4a6e8a",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeDiscoveryMapProbe.c": "9ed32d391d08d937ff4f9f33bd11c3a204ce9a2230c2d72b6761e0320b31f24f",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeEndProbe.c": "2dec80c7e247ec5c257407f95d9d5edd42fe0cc44d6af9f724f6ebd10d8a355f",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeEnemyLoadoutProbe.c": "0885ca69f6fa7f53414ce1792cfc3c49916886b8173783c634135c13c5d37429",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeEnvironmentProbe.c": "9e2e66ac5d9778a1c65445348e3300cbb90b68b3f669f3ddf1d2b78a858430eb",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeEnvironmentRestartProbe.c": "7a836a206381b8e8de24c92baf141beb30575723675dd6948d738169ed26b507",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeExtractionProbe.c": "4b09385f73206de004f4f3c38a6192fd658a0d2012482dc5a84dff1599ceb972",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFactionCatalogProbe.c": "e3011fa47b67122d7b2c23af8f91b7a217599d6cc114c4f9de628744b9c948d3",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFactionSelectionProbe.c": "946879d822e7be2d48e03a3140aa1aad3e3d44dd18507fa3cdedb4c6d7dd81b9",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFlightFootprint.c": "a8862a04ac784426f431e2e9cd3f1f19f820b38a081674d29549b8b00277c72d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFlightInputDiagnostics.c": "e231dcbdaefe81beb3bd587cb73be8fb3d3184bc86d18dbaa30a43ca4ba5dcc4",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeGeneratedSitesProbe.c": "83ab84ca4de7b545963896ed9d14e6545c23a2b940515730d74acc2f6b3dd18d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeGuardCancelProbe.c": "bfa1c65cb039e19c3d1891e4a3fd33469e974c97cc7f42128efc31a8f587d514",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeInfantryCombatProbe.c": "3e4c4382ab91f470357268927b954fd101685df6b2244df483f0422d6c0d7da2",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeItemStationTeardownProbe.c": "028588a49fa9207087cd27ec9396979cd932daa071e2490bd0262cd71dae30d9",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeLifecycleProbe.c": "b613a5dbe81c2032fd02d31070ae5631166d14d0b02cdbec3b63b782f0bbc115",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeLocalAdmissionProbe.c": "29c860ca3e51cdaa463f3c23a98ff45ee0499ce9bbc322046e0efbed587f1e09",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeMedicalCombatProbe.c": "3b9c557b249728c518f9d6b5cb24b725ecc32a69ae12df069cdfb0da70a80b95",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeMedicalProbe.c": "4b73e7cf35e9c8fddb089678a320ea58272e1b6611318d0a762754c171eff785",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeObjectiveLossProbe.c": "6b80fd317a8c6e8583bd4337870838a86251e3b8a681d0aa07e8b52e22abfc48",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeObjectiveMapProbe.c": "2d07b895cb74af58454605fb1c536a566733e3001a9375dd0677d5f274bf2a46",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeObjectiveProbe.c": "71fbd2479a70048f83d8b262ad1452f427be2c0afc8b071ef13bff477b9dc29b",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeOpeningToolsProbe.c": "0c5d6b96ed5a7cb1cf0d098d534dc7190449ed09339062e6b584729d53a61b4c",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeOptionalSiteProbe.c": "19fc19e22348e6213827f620f4fdb5dc26144ea2ce0032de773e79c1fb155a26",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativePatrolProbe.c": "5a2af71cc4cfccc7dd7c23584398a38290eba1a8894cd46f6967252ff3a7087c",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativePoweredFlightProbe.c": "7ae5d6f85bbbebec214c66bfdf6f53b93c802f109fcd5bcfbad82c5d61d6cb9f",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativePreparationStatusProbe.c": "456f4d7c3272b89d5f4c6713617baa5596d846994152356fee9a659839bcd8b5",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativePrisonBreachProbe.c": "4889e0d3799a6a21b9f84bcb2f2ae78dce16269cccd1329f8d1fcc1a23e7c22c",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativePrisonerProbe.c": "e2d1ffe5d269add55124601ff0d1dc032a398c7d51010736e6f0e4cbeb38ae86",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeProgressionIdentityProbe.c": "1d3fe20bce761a1082964bca9bad9ce79d1fa8b04db9b5053bae98da380ae560",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeRadioCampProbe.c": "67f1a088f9b20e5f0f11ed3aa083ffa772bffd7c74d85b7a307344ac3d47e09a",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeRadioDefenceProbe.c": "ff1e27a0ce75b123a86e7df31354831880ca62ea90b6c5d7c60d3ba168e1fff0",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeRadioInteractionProbe.c": "7b27552d233813894f65c08eb9f04b547c4ca9ff96a2370a763cb94bd4a555c3",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeRecoveryProbe.c": "d6691f22432b3ce37d07d448aeb3ce7feb5cd09e852e0167b5e4676afd24bb21",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeResultProbe.c": "c9a89cae067f221b9f33965b4d3ab311b78ba79ea383ca65032c4001df44b472",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeSiteGarrisonsProbe.c": "1a5ff8747d7501862085b5e9162043fee3b05e82c73c516ad8093aaada53dc60",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeSiteSurvey.c": "ac0203753ade0cdff6d483132797a80e4520f14546c3f9dea288281cd4cd9c4f",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeStationTeardownDiagnostic.c": "172248540932174341882861bb78a9720a6cf89981fcdf9dffe63f7fd4023f2c",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeTimeProbe.c": "4a2c6ffd947334a0a71eac083d10c853c524b00042e9ea0987497c4cee60c3d5",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeTransportProbe.c": "7a3fe04aa1c5ed1061ff63d9d5180e8b925932b62d76c1ffb49bd3dc23530993",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeTransportSurvey.c": "816df9a2a9072f9f7db75e56168d8a8fa1e665ee8f7dfa79af011b354254909d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeVehicleSecurityProbe.c": "59bce863142e4fba4b6fb2f544bb8a58061f0e99b1a38e5ac291cea919563763",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ObjectiveDetails.c": "628ebd166dcb5544c2d18dce489619984887ee18296cf2446fc6d894f89dd5bf",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ObjectiveMapPresentation.c": "f189f8987244e10df61ac577bbbc952ed5c4e6c431a8e3cd192a10fe2e8c3bec",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ObjectiveText.c": "8d75b35ab977be0cb1a2e3d3d1cb8ef875cdbfba69c35784c3d195451ef944c6",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Objectives.c": "b9cd5bb3b193c20401175c4328405be1b121e8a60b7b5999910b6a71f834af8a",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Observer.c": "682aa5549470c69fc72d261fbfcf9f7a04a41a66e0101b269ccc00bc282ad05d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_OrdinaryGateObserver.c": "1e376ca83c0005cf532539e14d7f47363c47b7c5b03fe3d55405a59208705fd7",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_OrdinaryInputObserver.c": "808a46cc1e4b31b65dbbbcdd55493f594ebb3974bbec38b4a2402334c653c0ef",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_OrdinaryLookObserver.c": "d5a1b636938d65e9d11c78b31487f2924400c34d98e2ec812954a2a224da7dc0",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_OrdinaryScenarioLaunch.c": "a4e7e56d174ebd15b4730202dae4c8ed06144f3f27c23ed49c99e2d297dc421a",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerAdminCommands.c": "eca9baa3b07da48a740851583540840f8bf5f65f7be854902a3778f76967faad",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerEscapeResult.c": "3124ab4d2d6d471409a47aba0af528790734df53243c03fe0cdac3e407047c14",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerGuide.c": "e49bab76a015ab545088af7e5eaa3cc45811907db4e5b1c5fa8c18afef34b62f",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerMedical.c": "270454d50235bc28df9bba4fde2689934578874c4eca9560afb9f0f6324d7215",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerRoster.c": "c038dac0f749bd29ebc35a4e952904b41a34417ba738904d5efcd1833a263e0b",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PreparationStatus.c": "43a406822a0361f916abc363f27e0c578ee94855036981d876bf47c68233c71a",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonAI.c": "8709753e86dc2ca777183f08cb8fbb9851e0c0de495ca01520ebcb1b3dfa59b9",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonEscapeService.c": "535cf17e21fc8e62716c7d9da88d976ee2f526501c6a4752b822f1252e742bf4",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonPatrol.c": "284618391ee2da84dbcda4a99ca3c072eae3d67b8a9ef40a86827b9ea00810f9",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_RadioDefenceService.c": "f5f0bf1352141f933d0edb5630e30541e001dc07e1d2c8529b29cc159c126b13",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_RadioFeedback.c": "545262e65e9b3645d9e514a0521e442fe08f0c2e4e7c83ba638c5105d09818db",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_RecoveryService.c": "86f9a7769e3ccb19fc61127fe2fee2ad0dd825487a5cd59f334de8b9741c93cf",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Resources.c": "d0169aac6fd0c38928c47a9002ded0fd8ba558ea3314a600e792d307ac1ca3ee",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ScenarioComponent.c": "81bf30d358c7b100248be17cbc2e6beb2f107300c939aede8a92d273eb7dae1f",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ServerItemCatalog.c": "e306b9d179b97d0478f821be3ca606c71908a21a4f87085b37a5fd18c4e3575d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ServerItemsMenu.c": "c0c3d9d1cf4615f38c793f1250315bbdb9349f33afa0841851da89433a303c3e",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Settings.c": "1b466886e9f5fbde1de0be20395e3887046c6b5a9a239dae92cecbfb721714c2",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SiteDefinition.c": "2088c45798f0eced702e0abd97550b8d1fc97ebcc34c3d497978b7424f6c670d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SiteDiscoveryRules.c": "dcbce3b7aee89bfc47a50e9de89209758af1f1bb462b99af67a8ad7a26e9f229",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SiteService.c": "210646e679056f4a46ef454a5abe15bd42d48349aa376ccfbb6b3b2ebeac6812",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SiteSquads.c": "183883783a4e8399cf62851a4cc65a5d091d25131bc53b4323cf17286315b2e0",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnClientScene.c": "b56f99a91cdc53bdb93d320d10839339022d7e61e6b101eee8296271abd7d3cb",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnFinalization.c": "c949642366ad124dd2abc4111cd598eb94aa257fbae01b6fb3a0f1882a23e83e",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnLogic.c": "47a39c951be71bfcf1cc50526d507d0f9d8ef2fc09408697b6fe6b0dc5a529e2",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnPlacement.c": "270bf465808d23627a11e720c6632d4fea35d0c679e63aa64046ef8874d68ceb",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnSceneInventory.c": "76b79d5bd9d1f367e1ed19724302b7d49f8b0ede85cf19e89c452582ef651f8f",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnSceneLease.c": "20de7f96bacc9037580d88d4424664b4554b2c082d82e7d29913e9dfe390b594",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Supplies.c": "752e8a56b0b8cde33cf532032cb0a203553017b686faac2e19bee06f7a9c0713",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainCatalog.c": "ba2e68543a8c929492d06f8725a743d26849a630d6f8c09be0f23894f92d0990",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainMenu.c": "1da542ef60ff7c1897b1f12432c636ef6a08cc710bac520ef186589d506e9a54",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainPreference.c": "ec25e5c3a5b97527f9cd70341c10d69d7124048089d26883ac2f8c9b3fd2815d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainSelection.c": "ee75cac068b99e7403f5eaabe556152513cf5d973602cc6e6b8967d25402f6ad",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainSites.c": "63ad027dac5bafb9e93805c361cbb27bf82af0567ea181a760ddedea98204c06",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeover.c": "487f1d004aa4f7a5f58c12c37724b26fcd54fc62b4096d48f3a7436d9958274c",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeoverClient.c": "458b84b3fb31c5a2bd1b7c3d65f25e0aeab91f5505ef0813231435c8a3c7d2b7",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeoverManagers.c": "5b7661a5617b7124a10d3c18e087a4e2363a967eecc5c87ecc94573f2abc07f2",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeoverPresentation.c": "d66a29a44e999cc3f2e56ba9c3c6bc936c027747312e08778ce301c1837f2112",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeoverSettings.c": "da22775930b13e41d4a71409e37af3bb99e4cc1d94bdea0e3b59fbdcd4d40132",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TimeService.c": "63867760876d523a1794f619118a52c5cd387d5d92756cd286b2c16a348a6c7b",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_UnconsciousCameraProbe.c": "66b1c4591b0ecc67cb08418a115bb02ed2b0168b7ae970f1e0a1ea335c59dc5b",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_UnconsciousWeapon.c": "24d31bc857486638e55c605283c17cde0cdbd3c5c6021eac1ec93611387b10d1",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_VehicleSecurityActions.c": "bd7d0aeb4abcc9d8044e4888f9a92f9e5fc97c098bdfa3bbad57e1a29697a779",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_VehicleSecurityComponent.c": "2ffec4e646584ec546147fc4b08249825cb32b531aba26467b586d760485adc3",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ViewDistance.c": "8514f72f8207f12570d2317e64094a45507a1647dfd45a1501499ef81e90189f",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AirAmmoMission.c": "0a471a40c8f7dfb797d8d35e41c5b1ff91e8d2ab13b43cf866e46c0e4ab4ed9d",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AirAssaultLoad.c": "5554994115cd7d56152ac78ba53034bf934b71c5634b17d35e96884dbb3b8a24",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AirAssaultSystem.c": "2eaf9816eee3e1cd2ac70744a6ef7ea5a90d0a3eebdf925e384028a7edde6a42",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AirReconSystem.c": "f8a0e3cf4552d8133efd33c2126ea15a7694676773a7047c15e00021c1d9721e",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AirSupportPolicy.c": "b5dad011d5a0574a406d6469e0744a9d37700cb41930dada28c5143d556acf53",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftAmmo.c": "2be282406d0c45ab2e35b0ced791b5e494c662588f536701a4e82e6f5fb7c913",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftControlBridge.c": "b8f0141644d8f043c6db4c2d4bb93215c548e5c27ab5468c66e996d62bdf905a",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFieldEnvelope.c": "0f53c7d9ab167a804eb904d63725decebb53fd5796fdf27864a75abed5679838",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFieldFlight.c": "c04e264cff9963821852094c451502d31bf9c96d4deae2e8ff8a2373b53b5665",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFieldRules.c": "30be68f4ca2db7e169f6f0432815821179cddf9159f7b150341dc8eb479bbd17",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFlight.c": "aa25a8e67a30c48677bf528236402b7f8e5d815dc18df93b878520ad3d1fe8a7",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFlightEnvelope.c": "8125cef61fb283d0d7c4dd2df3c04b062b448f1101fd48dd53f4f4097df5fef3",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftRouteEnvelope.c": "e8fcef844239c47a1f2f36be420afe943bc450091b05859435406b46c87fa511",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftRouteFlight.c": "1d8d92bf6d97429d68a9f62018232e90cc124cc8d7445efeabe863706a31e2b9",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftService.c": "3f05209227986b5c6bfb193f8f53783cfd4ef083bce898e22257c3e63daed913",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AirfieldSupport.c": "c6d88ede0b1b6bac5a7075b6e2e783ccfa8850210aabd28bfa4bcdb698cc5f87",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AssaultParachute.c": "a93c996059e7166988e9d1b0b498cbfd36f19a1cf8520cb4e9215a8884752e18",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AutomaticEquipment.c": "5832cbd3a43748e77f4e7f1b59361801c6d0445e0e15165e97d7a897b338709e",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_BodyRecovery.c": "47d9374095d04f5f1339c220caf518a40938ffc20f891b1b51ae38579e7e1c25",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyBoardingProgress.c": "328f8a5eabb8174b7727eee1d675db83a2eb0be7b8e834db4e950a645ca5d7a3",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyBudget.c": "ca49c274146d56e30cc93fa1652cc34c0fe68ea95725b0b3e33ab3673a6463c4",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyCombat.c": "5c4b7576b28d51edea868cbb91a0ab31a40e6ddb558f1b8a38e07e20fdb2969d",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyMineStock.c": "4497d6b790a45df2b76d18541ddaf299b406def88b868caa29f096849026a42c",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyPlacement.c": "4d0e8b6e147486fb65db82a1060f0c5641c1319ba9e418bdec99cb5a422a7fbe",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyRoadPlan.c": "fae404f85cae63e63976938a5fdb73efc988ba25c5846564f12edca04fb88551",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyService.c": "b59016d83cb9d40136b98b4e0067ea490bc553574fc53603593efd5522dbed20",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyStartup.c": "360228fd45aa6ecd9426e36120b5e637d2feee1e3a4a89aac8207526b871c87e",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyEquipment.c": "c52d4a3cc0e71eb136487c42df2fcd5bd6da1c33d31dbd3d6429c237dcf4a8d9",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyGunnerSkill.c": "adf8bac5a6f7e40b2f9caff5fe9be590c4e4ce2b2b387ba39e741a3c4f4cc564",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyLoadout.c": "a48f32dbd7f209bf08fce2840aaffc1781c571fc679763be58987f6b082e776c",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyMapMarking.c": "0f161fd3e08a54e3e1063679127549e482c40253a022e9d06cd9ee4d740b8625",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyMedicine.c": "05d341a9a000bfa2084057bd67d476d6e35adca6c8518d74c27cd31b551bbb95",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyOptics.c": "759e0a88ff30cb781ee69b8a935865d63ede5b1d97f31d344018f650a967c37f",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyRadio.c": "3a97e5c3de9ff33873d97c6b2d84ae505cfc4f3146e047b928e76ec3b22c8789",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemySkillAwareness.c": "00c450d033e43fc45c9e2cb64a1d81161d123cc594a4292cfc5f68eb6c17ee60",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EngineerMine.c": "defb12924ea5dfe68f86c2bbb4b07362f016ffee810f720d13f01d81881b3cfc",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EngineerMinePosts.c": "bcddb72845189b52e5ed71c687d7dd4b0b40b91b7306c3f6edf84a631002fc5b",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EngineerMineSite.c": "d838f5693d4fa5d252d529e59777f560674c02532f1041a5598e938b3a850839",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_FiniteMagazineReservation.c": "8278590ced1936d618905b0cbd0b5aebddda238d426a6a2a52e455fc36bbb502",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotHQ.c": "8748325b0810ea053b28d0ed4c00a75fceae1c0d1cd3b30efb4dafdc397632ac",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotLoading.c": "36da884a833e7a29743308490a3ce5ae299f7a451d87205a227163892aca4ed0",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotTransfer.c": "1946db0615130b0039b42ec80db12d9cc89b1b3ca5a7eca7d9112eb69c3bdcea",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQ.c": "d873b5b689e918f8c907918d673304a184ac2e4a4cb6face527b37a67821ee9f",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQAdminProvider.c": "e9bb5f2f3ec270074964fc8607e5a07c23f224308a4446837598d93e201d7775",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQAmmoReporting.c": "95c024cbdd35c02d9b0c3d389d29bb042e5dda6ffd2f5f0d896078274b3adb35",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQAmmoSampler.c": "8bb0ec1422887feaa340307d3c60bae50fc82d424fce6390876e580ff8b75e8b",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQBodyObserver.c": "f59421c1e0c83f0f480d7dd4d048b4b0a41193ed8fe8f2f627d2b6a696420ea1",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQCoverage.c": "8d9668858c47b7e9fee2b12d3ebd4e7cb88146b817cf615c4b0dade26c81b2ec",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQDeliveredCasualties.c": "1f738127e55e843ee2705007cedb5c08741f52f63c75eca7c80242177af82273",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQDoctrine.c": "6335728e89ed40ce11b811f00b61bfea76e94dd3379e4357cbfc438b05522bb0",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQJournal.c": "53563ff54fc4e0656713d6eaec5e88ddf69fd4bfa8ef6a67cfa13380d24031e1",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQLocalAwareness.c": "124260280ac8eda0e920bfcfc86932c9b21df6b1f7a6aa8acfc43feea3da149f",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQLocalHandoff.c": "2dd700dae9d9b232d22ca63ff01af75a3f5cc213ac24b7c0a43ffa38bc0b9ffa",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQMemory.c": "ec2047a477fb4273e22ae6bb68e7365f321f55c583b5d2c48c4abf2ac38e3b7d",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQMineSampler.c": "2a0fdc4d27e947a1d77b02ae23f757c7fa074eb456f817b7df0766583d757f55",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQMountedAmmoSampler.c": "88ea0fc0e13d7e3c22c7ce8b652816d1d137e4e6e37a72f48f0bdf515b936ae7",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQMountedDispatch.c": "cee3ae301ac2f211c290450b644a7942c9786a2a40d06f16e2a47efa96fd15b6",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQMountedIntercept.c": "a37edcf66e43945f331db47fe81cb2e0e767a7aaf8115244dcf9e6295932be98",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQNetwork.c": "0b73be993628a55e3b21c8670d540e39c938093dd5cb4d586e800ac530509b25",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQObservation.c": "57ad3f0b68d150791e30a7e4bd7dfedfb1ddd78a1c76f228e67b33ea9cb7144e",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQPursuit.c": "ab6ca0e1a7f36c104e664db06a74c80a528cbfd1de599af42e2194ef0a4f4ca3",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQReport.c": "12ea8ba08753d1e6d38b237087c1209cd2f9574b53c3ff0f27c082bed029c9ea",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQRoadIntercept.c": "0897e82d7805ef56f05f2b9c23903280285ea6bfa51796a2df86bb564ece78f7",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQStatusSampler.c": "b937eaed913a5095afa8e678dc1c36b5c805541bf8cd5be927069533d6baed1c",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQTask.c": "1147904bae6d72e9de47ce17bdada3dab489de4ed6e781dbf15bdbb30599ff6e",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQWatch.c": "abe634cf6003ae920ec1ed18e305ed462920204960894520d3dd11f7e5ef1c33",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HelicopterAvailability.c": "60eaef2f6d4b2fd44861c5a4434ef97e732e40a5ff7401e2da451ed2dd9c2762",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HunterCombat.c": "df1c319d10efd07ed6f971cf0e41d8d7e377b04ea7f0fe143bf94df733fd1d9c",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HunterCrewRecovery.c": "e76af0fbf6f436a9c3c9d4c7b779bc08a78f6fe705c08bf6d9757bbeb65ee8eb",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HunterOpeningPlan.c": "0b6275221dab491f148426df05e132579f3acc20de5559226c3b38975618355c",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HunterService.c": "79369d5cc30cf628f02df0023157ab423e40497325dfd6a73b218757f2b689d4",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoAccess.c": "ab4262f78d54782c5ecbf5fff4ebe3da16d72329658d7e18c0c35387dc8b3c7d",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoTransfer.c": "99fa26beb0c0869d0cd694500f3bfc0705c2c1cf674dea90d98fb93a59570ef7",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryCombat.c": "5684fcbee128a35107312452297f7ae2bec28aaa1b63f619fa649f36df8ea476",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryMineTransfer.c": "02c399413f80879c22b4891e8ec807c67a6235677095fc4b98bafdc360d6944c",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c": "bf50a7a7d5cd182d29a02ea5de8d58b46979019158250c5ab589ed8ffe49b974",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantrySupplyPool.c": "c8e454573cf064ff392291d6feebf1f23be64390b5b8e944c03dd065f9f46b42",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarAimSolution.c": "59e8343d09f7a44871d8d3335d6ad1d02216abb5deed30d38b5ec9ba3f2c0649",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarBattery.c": "157024afc8fd3c1ffeea6ae923ff091e5773b9ffcf5f5864f8040d001e689110",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarCourierTransfer.c": "968e58ca700b4a11e5e04a5c159696f514a0b1bce531210172b913e495f7e2b7",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarFiring.c": "f2597d44c10d10de2462aa5e5450a22b8a5ad0eb99bd0cc09a8cf1ca2dd4a350",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarLogistics.c": "b3624e4a00a2bdef16f6c100bbd79910e3bb8c2ae8ec5fe2ad5aa70bffecd303",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarPrediction.c": "05863b2b4f9f70cdb288f91c722cbea163c13f2a2927dc485482e5bd4fa7d57f",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarReadiness.c": "4c3799b3f2681e977669de0cbfaeb307d9a682b04365bfc9f59079e762965758",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarRefresh.c": "52ae8d9d6cad92f42d68c634091b80a474d2666b6c06d63a8c30a3fab71494c4",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarReportLedger.c": "42a96040b63e56677353e55164ae23031c90f70b4d6673a9f412ad7b19e636ae",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSalvo.c": "c128850c7a78a4d8fee00ad38f48b265f1fbd1d9b24b092ddc5c205b0f0ad6da",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarStation.c": "cbbd7c86f722b664c85ab7c070ae1131d2ce5c41d1dacb4381bff9c1720a1866",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSupplyTransfer.c": "ad71084f507ad9c32d3055e7ec6844a1ec5ddf568c0216ab8391e902b56e417c",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSystem.c": "bc290ee8bed299d869598cbf41ec281653e0cc7f3c64c7214613df8a0fc83829",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MountedAmmoPickup.c": "5f7ca5b31f3b405c2a6ca32ff91042f5b4dac6ab9640ce67fb10d7a74236ba69",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MountedAmmoTransfer.c": "0b195784497672fdaf651f336c14f7be98c257f98c85cfbeb4f96fe1a401999b",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MountedMagazineSeed.c": "b42d0aac142907433df8bedc40de24c94813544016cf5f451846f1980250f995",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MountedResupply.c": "c26ad43705765be1c20eca37fbe2978b8c647151f6620ed37141657a4b7dc312",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirAssaultProbe.c": "c1d55b338b157b758e6ffb993d5f689029b28b13929797c91e5dcb15b5e561ea",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirLogisticsProbe.c": "58fe863775d0ad575cb566c78cef696c9826691cf49ef9adde76376be7316db1",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirReconProbe.c": "c1216e0512a0268e4dbb82429e228334401c0c3cac52ba4486ae6dc91e41576d",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAircraftControlProbe.c": "0cf3e72ccdc42e6ef20fb71d743f0e037a9e69b2e082c720fa705628cf790205",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAircraftFieldProbe.c": "b64907c7566a894ca2f3c49ede5d972d4087a938da1a0ca87bcbd7c2203b2c52",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAircraftRouteProbe.c": "8d0dca97e5106d1c84b64992c789e1af0689514beefc027e713ca6ab901fc470",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarCourierProbe.c": "740c8bebbd4128a9311b1167d1058549475d6b46f81c9b6c0d19650f4b50616f",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarFiringProbe.c": "ee570d21bede8baebefc799399712d9582b3e30ebda7299f6c941777f02ad2a2",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarSalvoProbe.c": "fb9ccc6b36247ab3ad828ffbb2556abf5c2838d93ea6cd1ad259c0a015142f5e",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarStationProbe.c": "a110f0abc753cb1d2f781e457e637dd5346ecd2e924eb5eb3a5c7dca3d1e2340",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarTransferProbe.c": "399c21940ef10777b46fdb3e905430ce43404ce1de2f4a6bb62f9c61c1a0689c",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativePatrolHQProbe.c": "a58f57530e333976dc96fc5a0f9cb6cf0cb069c55788824950c5fb2f965d8e26",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeScoutProbe.c": "41b39b1abe5e51a5b8a428d533cccbfb0dda9d7a570228dc3489408c60543f17",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeTownProbe.c": "ade130f49fc9d868281cee7fde383f084f70ed8d4b876dacebbaed8538e84999",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ObjectiveDefence.c": "83ef91c2118521aedb4c1838b2e47909c80e0950086449b98ced168f1fd87080",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ReconAirports.c": "7551347d776d6e0eec818d6468cacbca7ac53daee7317e0a1618ca3d39ebc762",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ReconCrewLocks.c": "684bc5b9858c7ed90ed2ca6d52fc0e731a7e37a116db776090257b72a63621ab",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ReconFlightComponent.c": "4966dad504b3f8f28a9ffc8ac17cc548b00066fe05213c49c662ea56de34c9d4",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ScoutSystem.c": "63287a252e4e7d5aefce840279f26ce3e1f286cb79cadb32596c37897cec7119",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_SettlementSafety.c": "e5c0ebc95521a9a33a3f7d9cca6c551dda862a08b7af20b017877aba9584795b",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoyColumn.c": "35678ec625fb0a3c0871e2c373fcff49816440a97a165ed25c8798dd72ef059f",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoyService.c": "5b1578afbf6da736453cc9d3872979eddd1649746aa32d3b0c7a9e3cab50057e",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoySystem.c": "f09aa817c27d6af0ccfb544f4ab1ae2afafb63d626641e03d87cfe159475d821",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoyTactics.c": "dc3acdffc8ca48f11b131f66d30d679ca68f3b3004344bdc78723bc9305915e0",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_SupportScenario.c": "a7b46253e1bb37cea7c29bb557fbf43ca207022d0f1cc927349441b2d1615279",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_TownGarrisons.c": "57f862476751087972fc78d0b27ab44e72361e27d32f15d55f9fe7fd7d6bd0e0",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_VehicleAlarmPerception.c": "45ac71d25e10a057a26a5b0fc7128935baaf47f4c0f87208a4420fa52086fd98",
|
||||
"source/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelAdminProvider.c": "d63ab5c547021aeb61d398b8a773afeedee4662d3ce15d9fd9d0e9e37262f8b7",
|
||||
"source/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelDiscoveryFeedback.c": "62f2c408383f410782d9d41fa50acd6bd8cf66eeb80d2b79f91852b9d2cf8d97",
|
||||
"source/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelEvidence.c": "6bbf8d3b83e2c09fd9a23a9a5e5e11d7c29af2e618116bee613562fc45af2b33",
|
||||
"source/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelReroll.c": "d8b04de9ea789732cc78ebce9aa60786c86fe46d05f671cf251eefa68a214b59",
|
||||
"source/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelService.c": "2911325c79a7a372628b18ffa0e110d11919ce2c2cd7b19277bfd608fdb03dfc",
|
||||
"source/addons/core/Scripts/Game/ERR/20_Intel/ERR_MineIntel.c": "3ce16cebaa9703b2f9803df7c11614f94de6460a9136dab8f80dcad41ae2b1c2",
|
||||
"source/addons/core/Scripts/Game/ERR/30_Map/ERRM_NativeMapOwnershipProbe.c": "32418602f085e3edba7343f42a6a691630b533be262002f29248e8ae87a38254",
|
||||
"source/addons/core/Scripts/Game/ERR/30_Map/ERRM_SharedMapComponent.c": "3a10f6ea25bf88a400bc3e6c339823433845c5db4f2f423835ccf99a1b1a843f",
|
||||
"source/addons/core/Scripts/Game/ERR/30_Map/ERR_ScenarioMap.c": "75fa1d742129ef7f33c005cd48f56db7f49ee7bde3c5428532b0b501b032b0a3",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_AdminCommands.c": "282fe1463add7af8771aa58507b254e69d2d06f50274d4c77321db073f8394f0",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeAlarmHearingProbe.c": "5dbb6a48909b76cd141e3a79ef01d2e68cafee55153821c4471f85c761fff94f",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeConvoyCoverProbe.c": "d2450140cf9bdf09210473234605b4c0d818ea5b91f9532209166a35c5d13701",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeConvoyProbe.c": "4bdc920e87fa768b0ef0ed893c70ddbbcc9255d74163d7b657fd2ec7c4f14c32",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeHQBodyProbe.c": "811244cc8297817efbfc3ee4edf01c868eae23c88127ba0c72e98ee7422da72f",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeHQMemoryProbe.c": "d8fec6c138bb0f5bdbf99ee82ffc3ac9b44d1045d8833da63f8aa5f39beeb7e5",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeHQResponseProof.c": "0f8b09fd8753234c91fd6baaca0e2f812e409ae1c4be8f340b648ae59b69c2f3",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeInfantryTransferProbe.c": "9b2de4dc22bdadd51b0271219a971dc8dc07f70ed3534f306acf03ed81b29424",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeLocalHandoffProbe.c": "0d4d61c424a16008595f86fa61f3b848caf9bd6e9ebbacea9c10254d88ba378e",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMaintenanceProbe.c": "852b9b397efc3f919c97fec63bc3df1a850cd7833421af8441994afd191951d4",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMortarProbe.c": "ddb892141500c192c0787b011d57dd8c07dd8c9a3ca5fdc407f6c271897bde0a",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedAmmoProbe.c": "8d197f7a1398625e5a19db3284b0bf72c6ee6e032843a3e4d9a4e58de42b6825",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedCourierProbe.c": "12710e9e5548fe8856f7a52f3566338369a8a1eedf0bd92af16229271872ada5",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedInterceptProbe.c": "34b0b1e38a59f14c4e83d93ec412779945388e6f4d697bda2f6cb90f519a6372",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedSwapProbe.c": "a6721fcaaccadf8eddb06687c7d587d0a3e377d5d1bb0b8e72e630fede8690ac",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeRadioProbe.c": "84524163c63402755b4f834f74dfe6d8e5c397dc26031f532593c6f79f5a93b1",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeRandomRadiusTrace.c": "7e946406067092e30b6b75cc6ef0c56db7f866249e02bd13648156933ee578d9",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c": "104c56794ffe90e61af6b35a4998d02fae7a68e2787092a88dbcedc3246d6ab6",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSupplyConvoyProbe.c": "701311de6a2c9fe8f0534a22056323c34072df26595dc70a7d4df45bc06e6c13",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSupplyTravelProbe.c": "32e6074e912491f2643a24cb44311b9fe5b069c76e4e94a45e7409ac82d36507",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_OrdinaryScenarioLaunchChat.c": "a747af09599ce4d0c52051f18f00c4624d24d137e328341b580b82e896c6bf65",
|
||||
"source/addons/core/Scripts/GameLib/ERR/00_Core/ERR_DiagnosticNoSplash.c": "0ea1b402f8927b6d68bf6f7e5caa2967f7e3a39147634faab147796b791933b5",
|
||||
"source/addons/core/Scripts/WorkbenchGame/ERR/00_Core/ERR_ValidateBaseWorldPlugin.c": "49a38c37b51e5318c7dcbcb01543dd9a6300d053f0d39808b3974f4edc45b871",
|
||||
"source/addons/core/Scripts/WorkbenchGame/ERR/40_Chat/ERR_ValidateWorldPlugin.c": "f567518b54f43b88747df2838cdfd6ebb34605c0919a3e7d271d28dd8b67a9b6",
|
||||
"source/addons/core/UI/layouts/ERR/AdminMenu.layout": "e8d570f7bf3b8c4067ad81d47bca7f35514b2f8c8748f5fa5f775fbe27debeac",
|
||||
"source/addons/core/UI/layouts/ERR/AdminMenu.layout.meta": "9deeece996f43b1f1fed6b5ec89279645c7b6424250200a42580cc088142e9bf",
|
||||
"source/addons/core/UI/layouts/ERR/AdminValue.layout": "cd811af6d2fb187f01c74e20ea07ad85669546b0ad70efae2ce52921ce26cbca",
|
||||
"source/addons/core/UI/layouts/ERR/AdminValue.layout.meta": "56b3d2335db400c1308e07c4a35d278b23ef32013dfd6dc82951866327428d08",
|
||||
"source/addons/core/UI/layouts/ERR/ContentRow.layout": "62d2c95814c99d906266fa96c6112e04a7fab1667e1a05e558d1d3974adc2d76",
|
||||
"source/addons/core/UI/layouts/ERR/ContentRow.layout.meta": "8c4bc13b41e7aee38e0ca640a97813ed1a6964a00e2cff9e1fe4ebd71fc2fdc6",
|
||||
"source/addons/core/UI/layouts/ERR/ItemRow.layout": "8ac6fbc7fe0ce0ffc3185516197303bb892a4415948f75ae06f3bc289fefcac6",
|
||||
"source/addons/core/UI/layouts/ERR/ItemRow.layout.meta": "33eaef9c403ea3a030e58ec17f78e46af457048243571ad5856fff04101fb60b",
|
||||
"source/addons/core/UI/layouts/ERR/PauseModsButton.layout": "d21d436291e2c1b262e33dc228b0d60a1d188dc9e85cfda6d2373f8281431b79",
|
||||
"source/addons/core/UI/layouts/ERR/PauseModsButton.layout.meta": "9ed6adabd8f53eb9a562d7186789876bba5c4202155ca894c1af866ca47354f3",
|
||||
"source/addons/core/UI/layouts/ERR/PreparationStatus.layout": "bd269cf8dc6f27735423743dd5b78242550518414448a0256e5e12fa6b92c459",
|
||||
"source/addons/core/UI/layouts/ERR/PreparationStatus.layout.meta": "75b12176a443bb911fc4ad446982d762201fda42ed38736b79bc5439fca31ccc",
|
||||
"source/addons/core/UI/layouts/ERRMap/ObjectiveMapElement.layout": "b364752c44896d67dad07e466a04f4504a50813fb36ee7c34c9189ea9677b4e9",
|
||||
"source/addons/core/UI/layouts/ERRMap/ObjectiveMapElement.layout.meta": "8691fe2eaf46568bca4a9f8128b247a8da810bb87a5546aa7ca3334e740270d6",
|
||||
"source/addons/core/UI/layouts/ERRMap/SharedMapRenderTarget.layout": "6e83a9c70282aff43b23a08b732739e7a241a31e8abf200498c90a745d3d60dd",
|
||||
"source/addons/core/UI/layouts/ERRMap/SharedMapRenderTarget.layout.meta": "5c846445cc089e2e08899ba703059d4adb805ff30ab5a16409a3cd59718cbd54",
|
||||
"source/addons/core/Worlds/ERR_Everon.ent": "22324bc7eb0d80dec8a1f3bd61a9df9201b72f749f4e751766b0c9d0b7d46b87",
|
||||
"source/addons/core/Worlds/ERR_Everon.ent.meta": "19d1903ca72baa326b4724a6791d0da1104a1e53f3f31dc1ca41a856efd68e83",
|
||||
"source/addons/core/Worlds/ERR_Everon_Layers/default.layer": "6bcb7fbb27b6282719dae8a37486e518d4cbaea385f2ea9af1918b36bb28b175",
|
||||
"source/addons/core/addon.gproj": "73e973a1f1c5910393e16f86a3a40d792031bb2fa3fc7f4dd87a06a16c3e34a4",
|
||||
"source.zip": "4f719fee7b4b1a7a9a1b4d26da133061ac908fc9a36da51fa723d3c0bd2bedfc"
|
||||
}
|
||||
+433
@@ -0,0 +1,433 @@
|
||||
{
|
||||
"README.md": "c338703bdd1b491304f659b2e9601020dfb00b95041a8b6ae90faa8921b5036f",
|
||||
"handoff.json": "900ec06fe305056b1e9250d03982fb6308520daec79d1c27b225c4f912a71b41",
|
||||
"packages/core/addon.gproj": "73e973a1f1c5910393e16f86a3a40d792031bb2fa3fc7f4dd87a06a16c3e34a4",
|
||||
"packages/core/data.pak": "3686bdf6a2601e08e140d372dc3d842ec68c78c9de25cb82172983f4e3984483",
|
||||
"packages/core/resourceDatabase.rdb": "68645b022df5e956092f038bd143c18beb99ff0a5efb014ce2eec5c19bcc7ca7",
|
||||
"source/BUNDLE-MANIFEST.json": "79431024ffdfa8f68ecef85d79340a1d01a2065748c68b16506ac49ed6570464",
|
||||
"source/BUNDLE-README.md": "c46c89a66c56aa6ba4349c50e66b8368bfe53914d1019912f961da83938ba4ad",
|
||||
"source/EXTERNAL-ADDONS.json": "172e62d5bb83a3423192205c2e002de0257170314d2fbca346cf8fd72a26ab1f",
|
||||
"source/addons/core/AI/BehaviorTrees/ERR/MortarRapidFire.bt": "16b263bcb2fb3ae361367a600753a829425620d2e6b350a891c51fba47437ab6",
|
||||
"source/addons/core/AI/BehaviorTrees/ERR/MortarRapidFire.bt.meta": "f2a44ece28891240e6bfa1d01af29428adcadbe82c80e287eb33cd5e58f1f90a",
|
||||
"source/addons/core/Configs/ERR/AdminMenus.conf": "a7f889f260e43656136fc159342129e5f48748d28c426f65f9faac37b624cf94",
|
||||
"source/addons/core/Configs/ERR/AdminMenus.conf.meta": "5faf5ddc0a51c1d0f82d60af00d91edc22fe9c39aac50d8d04b772a2c9271be1",
|
||||
"source/addons/core/Configs/ERR/Content/Registry.conf": "546a5a407c9e6c25c9157ae4392898fa3f40c04c7956649e62201f9ac0ba187c",
|
||||
"source/addons/core/Configs/ERR/Content/Registry.conf.meta": "046aa988bf8e972afcf7a60b6f2312f605f016f98625dbbd9cd75ebf9ea88800",
|
||||
"source/addons/core/Configs/ERR/EveronSites.conf": "b479000b36154a6a3af6b519b086251d981ef63cb86a973d00529499cfd4238c",
|
||||
"source/addons/core/Configs/ERR/EveronSites.conf.meta": "d5fe68025ef4e7c1e16082cf5873b7c7172eacbfaef4ab29b7e0e3c98f8dca56",
|
||||
"source/addons/core/Configs/ERR/Factions/MissionVehicles.conf": "5f74f4a7089c7e7b54ad62463159ce8f0bab25a6b85268dc3872ea6001e048fb",
|
||||
"source/addons/core/Configs/ERR/Factions/MissionVehicles.conf.meta": "00c368b6271d3440cc8bf627b03a384d247635723923fc5ad2104b8b4007b035",
|
||||
"source/addons/core/Configs/ERR/Factions/US.conf": "4c3da063abb6e3ee39a6e4e0c5a9ffd5eae9d209d58470ea18b45dba5528db1b",
|
||||
"source/addons/core/Configs/ERR/Factions/US.conf.meta": "a05469aef028e9e17eba545e81e2af2887b59f0fef17dac51a23c7b8155e381b",
|
||||
"source/addons/core/Configs/ERR/Factions/USSR.conf": "407ea27f80a64c5184c089d43cdd0bdabfc5974c84f1d2a245081fdf2afa3f30",
|
||||
"source/addons/core/Configs/ERR/Factions/USSR.conf.meta": "057397d97096346791b51b7b13fbe18af218bcf78e9984d9c01b49a2403de611",
|
||||
"source/addons/core/Configs/ERR/GameOverScreens.conf": "45231061911a1462d45fb6db0fecc2b0793f17b5ae71017174954ff4fbd20236",
|
||||
"source/addons/core/Configs/ERR/GameOverScreens.conf.meta": "eb654b745c0b97b41c991694569ef4877a3c2315e0826f9556337cd68690843e",
|
||||
"source/addons/core/Configs/ERR/ObserverInput.conf": "e898d645911e85b6ba902366cb23890d8bb14bbd2c485102e6d49ea728e9b054",
|
||||
"source/addons/core/Configs/ERR/ObserverInput.conf.meta": "9714dce6c38ee81bcc513c8ebef51d7af63fd15bcdda2e40946937c625dc3ba4",
|
||||
"source/addons/core/Configs/ERR/Tests/LegacySites.conf": "3864eb638d0ed4dd313013d2d787f975ae6ce4bbe238569919f76b73d5f7ca42",
|
||||
"source/addons/core/Configs/ERR/Tests/LegacySites.conf.meta": "097ac7daef4fc18344699a8471fdd77f9d158f8c70bab394068d7a08e4777ac0",
|
||||
"source/addons/core/Configs/ERR/VanillaFactions.conf": "db890b61b48ee15484041fd2245a862d9fa9e7ba21b1229c281ff37c448a35b1",
|
||||
"source/addons/core/Configs/ERR/VanillaFactions.conf.meta": "ac77725c0c21974991ef47a466b88122e939de8b46fd23e68889e7674cbb2bfd",
|
||||
"source/addons/core/Materials/ERRM_MapRenderTarget.emat": "9877c5b175c5f30dd80bea36c711b21ab38219aa7075adf9ae79932e1d4c76bc",
|
||||
"source/addons/core/Materials/ERRM_MapRenderTarget.emat.meta": "5ee1a705f8011a44020ca2691f5ccc17d44bf596fef9a36e98d1f267eb58fab0",
|
||||
"source/addons/core/Missions/ERR_Everon.conf": "936619df7789a6b4b80bd763f702526e1145ab4d5c300516c07e7e70dfe57d92",
|
||||
"source/addons/core/Missions/ERR_Everon.conf.meta": "0a23c98bf83873536c65fa17d38dea33a1d7b9e4ab210f90633ff688abcc551f",
|
||||
"source/addons/core/Missions/ERR_Everon_Base.conf": "b46e1f4aeef383a8dbe7ef2b5c12a55a8111856c52ba103a1e508c01b82dfc61",
|
||||
"source/addons/core/Missions/ERR_Everon_Base.conf.meta": "9b16267c644d815bcf98a3a3aaff30b93d7224fb24d3a2bac66730a28011f317",
|
||||
"source/addons/core/Prefabs/ERR/AssaultParachute.et": "b556997989605e2a05982418b7e9f26d12d427eb3ea6e3bc50e85c67ea7aa4b8",
|
||||
"source/addons/core/Prefabs/ERR/AssaultParachute.et.meta": "e9dea2d533ad1ce6ce689e0e2815c97a6382e1b90c35ce1efa88a885527e8e18",
|
||||
"source/addons/core/Prefabs/ERR/ConvoyCrew.et": "29a525a29605386dfcf292dc2316e9fc7650ce39db9fbaa4ce4372ad0de66db4",
|
||||
"source/addons/core/Prefabs/ERR/ConvoyCrew.et.meta": "0a909a15b7dcca34202ded136b3bdbbe8898153c9589e1cce1388433d362da02",
|
||||
"source/addons/core/Prefabs/ERR/Epinephrine.et": "e09c70b3d47a4dc5b92fd332c8222b99554b28a8a0c93cb5caac18eec4501571",
|
||||
"source/addons/core/Prefabs/ERR/Epinephrine.et.meta": "f1861f0b0ccace1b7b3d9c29768e37a83bf0c6fae5a411b1bd61d6b2eec7ed89",
|
||||
"source/addons/core/Prefabs/ERR/Extraction.et": "4d24c7811415c06386205e5bf5c132a23fcf21e96c75c7657ccd5f3ac914ac50",
|
||||
"source/addons/core/Prefabs/ERR/Extraction.et.meta": "c2a838633001e2e3a202d39cb33aa744ebcd996017ad032359069641b5d13853",
|
||||
"source/addons/core/Prefabs/ERR/FactionManager.et": "5a7b330f33956cc1781c8dc843e8186f2d37a98653ab36e7c42b9019df3c89f5",
|
||||
"source/addons/core/Prefabs/ERR/FactionManager.et.meta": "9bf53d5e4bcbe60dd1a4ece1409fc23c349055c860708620f5f6e9716290a97d",
|
||||
"source/addons/core/Prefabs/ERR/FieldCover.et": "e403d5cb3a5966f0cea81f15e0e825d482ba1a7a27b12498319ba45a414963b0",
|
||||
"source/addons/core/Prefabs/ERR/FieldCover.et.meta": "83461ffa76244e1d69f20b053a9741ccdf7d127009182bd540a7e5ba6150c3d9",
|
||||
"source/addons/core/Prefabs/ERR/GameMode.et": "4d3e5e2df28cbb8292c436ae05d4fc7e5ca789a123450a6968d9a718b6ecef20",
|
||||
"source/addons/core/Prefabs/ERR/GameMode.et.meta": "106769cd34525c9d440057072836cb7401a6752148c40edd7fe61c03bd58328c",
|
||||
"source/addons/core/Prefabs/ERR/Items/EmergencyRepairKit.et": "0157bc235eeb78a0e1373b561fd22a1dcb225c833ff7c2d4abae688bca0ec92a",
|
||||
"source/addons/core/Prefabs/ERR/Items/EmergencyRepairKit.et.meta": "da6f065cb2414b5a4cbe9ef0f0b1295b2466f26ad406c0bddb83845d4598efb3",
|
||||
"source/addons/core/Prefabs/ERR/MortarCrew.et": "21086e886fe3199624208c9a866f883ec109f7d08746c2b56b497e59857fb656",
|
||||
"source/addons/core/Prefabs/ERR/MortarCrew.et.meta": "fdfd4fcd21a67c3d698fa4aadc4e5c76e665cebf4be86013bc389e493fab63cc",
|
||||
"source/addons/core/Prefabs/ERR/ObjectiveDocument.et": "5118ecaf9d2038eea44a4b785f05d2e78781dc1387249aa58a6782c7e6752e14",
|
||||
"source/addons/core/Prefabs/ERR/ObjectiveDocument.et.meta": "eaba9903be147b98a1106e2273e2270773df73b9b22f2cd4e20136a8e281382e",
|
||||
"source/addons/core/Prefabs/ERR/Patrol.et": "d3eca8fe9197c57a27a285cdb3baf168b037b198d92b39df28a338ae2cfd0c74",
|
||||
"source/addons/core/Prefabs/ERR/Patrol.et.meta": "7c5da568fa2fcf0709ee2959253cb068d7c7ed7c2467af3b247a7e70efd96b69",
|
||||
"source/addons/core/Prefabs/ERR/Prison.et": "c0ca5219aa2d6322ba7d094b92000640b259112ff6611a745c0713c8875d09d4",
|
||||
"source/addons/core/Prefabs/ERR/Prison.et.meta": "2e426ef3de68f4107907854b51e818bc11d84649a01c538e3f18dd9ebec766bb",
|
||||
"source/addons/core/Prefabs/ERR/PrisonBackpack.et": "ae750f08fc9af645561f59d7e5809bd22f4cec26ca8fa6409d09730765958c91",
|
||||
"source/addons/core/Prefabs/ERR/PrisonBackpack.et.meta": "7da6aa45467250edc910ad7230dc244d1b041e8a6f55881eb3747ce51f9212ba",
|
||||
"source/addons/core/Prefabs/ERR/PrisonDoor.et": "b0ff94443fe334032113a663917de23f920a8b73ffadc9c8e9f11b545022b3d2",
|
||||
"source/addons/core/Prefabs/ERR/PrisonDoor.et.meta": "b8f3db52bf186426026668fbb9d633c3cbd4d438ab301fba880398f6a0e781c2",
|
||||
"source/addons/core/Prefabs/ERR/PrisonPatrol.et": "dc88c31cf5c415573a874f74e13572f0add9e6122c8fcad507fe82860d789c47",
|
||||
"source/addons/core/Prefabs/ERR/PrisonPatrol.et.meta": "5528e0d778dce5ed39c3e504c6427625527127b23269d20fbf12ca2bffe52ffe",
|
||||
"source/addons/core/Prefabs/ERR/PrisonWall.et": "9b410b7c85bb001be4601ad93f750e17b8318b850306d84f29c4dc1b02723d7c",
|
||||
"source/addons/core/Prefabs/ERR/PrisonWall.et.meta": "0294bc5dbb56f90f8153d62459bb0a6ad91d76a479812bbec9c7db182fdb58d6",
|
||||
"source/addons/core/Prefabs/ERR/Prisoner.et": "e6d345ac98ad9ec742bf6c3b8686839c3256df9833d31bb4bdf605cd41d0ba5c",
|
||||
"source/addons/core/Prefabs/ERR/Prisoner.et.meta": "974278ba49fafeed70b619a0067bbc70ae4d534be441c812ce2bef4a5fb3c022",
|
||||
"source/addons/core/Prefabs/ERR/Radio.et": "99b1d80b49d1e7f9d30aa4283772a36fd66e962369f288f5fe329c7fc911bb1b",
|
||||
"source/addons/core/Prefabs/ERR/Radio.et.meta": "bc91137b68ba550217914fb8892bb44d7e1920e4a1086f3e506623832a44212f",
|
||||
"source/addons/core/Prefabs/ERR/RadioCamp.et": "5e6216bf8e6e160da5d9f966c8f7c2081bf6dd16dfac1b89d682a14b3b8a6716",
|
||||
"source/addons/core/Prefabs/ERR/RadioCamp.et.meta": "3cb8d3d553ab6d8d111a74f721cf4e69ee1011cbb90248b83cdc7275697276bd",
|
||||
"source/addons/core/Prefabs/ERR/ReconCrew.et": "33953379ceb725bcd0cbe505cd643c94adaed17dbbfa95dadd404d6b8e345715",
|
||||
"source/addons/core/Prefabs/ERR/ReconCrew.et.meta": "2653e8c5b1cdb857de5badd5959ddd9826a6a298ab3c166628dbb835d7104d90",
|
||||
"source/addons/core/Prefabs/ERR/ReconHelicopter.et": "c609ee59ab145e0a1936f95726b86df643f5cc425c43924029e9c1abc69ebbd0",
|
||||
"source/addons/core/Prefabs/ERR/ReconHelicopter.et.meta": "d80f1c3d6a6f9104562b89729996c1c92ad240f08cdcf48d4c390a09d2047c08",
|
||||
"source/addons/core/Prefabs/ERR/ReconPilotEast.et": "d961f329823b991eafed80d085de1bd89b44a4575be98d8dac385d6b77741ba2",
|
||||
"source/addons/core/Prefabs/ERR/ReconPilotEast.et.meta": "d73df3c896359a54514d2efcd851f579feca7a2619b76c2a38f607649a31a4f1",
|
||||
"source/addons/core/Prefabs/ERR/ReconPilotWest.et": "8f8221927269352e55c8026ee5b00e026c281c79af6684b386f24e7dc4675fb8",
|
||||
"source/addons/core/Prefabs/ERR/ReconPilotWest.et.meta": "4785f23bb492c6af420ee7896ddbfc9767e0db1e06de95207df2dc949a1b1814",
|
||||
"source/addons/core/Prefabs/ERR/ScoutEast.et": "b4593aab494c4f21637757b3daff4f349da77b4c48ec5e8a4a2917a6a12cf811",
|
||||
"source/addons/core/Prefabs/ERR/ScoutEast.et.meta": "7c72af632537f687e92f30b52d97fc7d70dadd39d33f37e0b1004f9596f55012",
|
||||
"source/addons/core/Prefabs/ERR/ScoutGroup.et": "8dc0fce8ee3decc1c367411b00b6d8518df9d8458281cec0881464a2ce906af0",
|
||||
"source/addons/core/Prefabs/ERR/ScoutGroup.et.meta": "62e43fd152ce57aa4ceb2187a49e4aecdeb9f428b3a1e8318f86bb83dbf8a259",
|
||||
"source/addons/core/Prefabs/ERR/ScoutRadioPack.et": "f1c4911e2556c0e0caa8b896982190c5e7d0433e850b4610e19442caf9117607",
|
||||
"source/addons/core/Prefabs/ERR/ScoutRadioPack.et.meta": "825506e3d814d30a52d5dbf64124470641c07a0453543ba71426841e6c783635",
|
||||
"source/addons/core/Prefabs/ERR/ScoutWest.et": "2681b5a3f8621adb44195f0dbca6f3e79ef7decad8f9d0dd0e1a801ec2549627",
|
||||
"source/addons/core/Prefabs/ERR/ScoutWest.et.meta": "22a6607b4b8fe606ca75a634a0b2ac3178e7bedae7f9ff01e7a4989f3b39a3da",
|
||||
"source/addons/core/Prefabs/ERR/SpectatorCamera.et": "cd2dcaca0df4c39816e582c594591a535525ed77827ffa3de24d27b79996544d",
|
||||
"source/addons/core/Prefabs/ERR/SpectatorCamera.et.meta": "2a16558f93915e31908a674509e9c89976470f78a84a1174a64b94b68b8f77ad",
|
||||
"source/addons/core/Prefabs/ERR/SupplyCache.et": "4c97b0514fe7e723046f40f0b396f6573b12eb9981ca5df70b9e8aa3cf29323e",
|
||||
"source/addons/core/Prefabs/ERR/SupplyCache.et.meta": "2f5de3a4aab1e9d0e35521f48dc57b95bd6e449c383dec4f1c258e10295904cb",
|
||||
"source/addons/core/Prefabs/ERR/SupplySite.et": "f33681281d26676fac88736091834d5a7b87fe0fa01883582542df964dcfc694",
|
||||
"source/addons/core/Prefabs/ERR/SupplySite.et.meta": "b41944b12eb3528ff7a3ac94258b18c66ef161aa6a38894aee300a1ac4798630",
|
||||
"source/addons/core/Prefabs/ERR/TerrainConnector.et": "cf9cb28f5a3f41931380864a29ac979aa1d5e843456f564ac7a7de78f88e1aa8",
|
||||
"source/addons/core/Prefabs/ERR/TerrainConnector.et.meta": "9f37c979ae282aabca29ce84beb0db851ee8b9a19f7f3a64d387c175616127f3",
|
||||
"source/addons/core/Prefabs/ERR/TerrainTakeover.et": "6206fe2eb4e2c6c1a9e3ddf2898535ae08981c115adc6ddd926017ac20d4b535",
|
||||
"source/addons/core/Prefabs/ERR/TerrainTakeover.et.meta": "64e953e378ab1d2a75ee7246f876f4ef93ae8a4e3fddb5002d7ba37268cb959d",
|
||||
"source/addons/core/Prefabs/ERR/Vehicles/SupplyUAZ.et": "29f157849f413261494a63d4d5b0a97e8bbe61cb076efcd59d6c940653f23352",
|
||||
"source/addons/core/Prefabs/ERR/Vehicles/SupplyUAZ.et.meta": "544c94cf1c26757a10654de7856cd6cc48b821ce3bdc02add13cfe6514269915",
|
||||
"source/addons/core/Prefabs/ERR/Vehicles/SupplyUAZRearSeats.et": "cd4acdcecad299445952aea0adefc85f2b9e9b43f8186f100e0505c5621b3656",
|
||||
"source/addons/core/Prefabs/ERR/Vehicles/SupplyUAZRearSeats.et.meta": "123955da03462befb90e293b3bb856d49cc761166611b38ff47cb48ec2fbe95c",
|
||||
"source/addons/core/Prefabs/Items/Equipment/ERRM_SharedFieldMap.et": "30dee8e9eab459ea32a7d835a9fb89d43df47708057cab829f067b25a24cd581",
|
||||
"source/addons/core/Prefabs/Items/Equipment/ERRM_SharedFieldMap.et.meta": "59093e9072c50d99c86da7609c87541016da5bcf92b98d99db4c524e1c8e0e8d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Actions.c": "cabb21413c90b252d29708b62228d0679c51c76e39ee0e483953ad7061b2b9d6",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Actors.c": "980d30964845600a261693cc5c5553e1472e8e54867bdc06133ff5c7b36c9128",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminMenu.c": "3b96a99832ed40002598a186dd8de1d21410c2e690df37a6319fdbeeeb4eeab0",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminPlayerTools.c": "56780d78bf423f54f482d8620f821b8d3eb0199194482b4f12e37f5ec3f55ef5",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminProvider.c": "62e05aceb49da07fed7aa89fb6b2f8eb3efc373ac09eff286fba983c3ad570eb",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminService.c": "c3e008c8bbf538c5bca3a82a975decc7a283a38543a9d2639d90a81ce592c51e",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminSession.c": "89d92f138a201ad7e752e027ba3930a2e0bf647d7b3a2c576346c1467f8bea3a",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_AirfieldPlacement.c": "0c2f4d31a2abc8f3f90bda20546543f2a1cf9306e9bf93351dda1883b990770e",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyGroundSupport.c": "26f0c7ebe8563bb022f7c383674e7d8997b0cc35c7ea321d39d74f2493c1ed9d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyLoadingFeedback.c": "e46988b92243df19a5400eca7406d6969b8b1174d8e3efad48fa0a936cbfdd07",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyLoadingGameMode.c": "f4cf19440583ac24346831a2d5f1d7f734c031e46dc266c499972329dd0533cf",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyLoadingOwner.c": "6346a05ddda030f7d9b6f026f977d5f018ee16002fa519e8c49dcd700c323dc7",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyLoadingService.c": "e6f22813f7a04e2c0ea000d054407191f2be8badfa6c51e062e9dbf84b95c67b",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ChatClient.c": "4bf937ff74e0483c17fa0103f73bfee3afd8f67a37c0c248b08772a17bfcc349",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ContentDefinition.c": "bc1dd4ed27ec894cf4bd617fb226cb8140b544aaa9ef6d8654e815d81e7f6fd0",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ContentMenu.c": "c82b173496e7524b4570b2afc5493cb970252a19aed740a53011988db7700a01",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ContentPolicy.c": "3a4987345d5a7159234a7e1a08bf5ac40dd5a23031e9b1953fc43a0501d9924b",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ContentSettings.c": "572cc36f88255a37e8f0e9f284fb96e07c6c4032506b34b8c77d688f02785400",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_DebugAI.c": "bc5529c60591a6c36c39cdb753b1af948690fc3c3c725f38a8d595b41a499235",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_DebugIntel.c": "a9f6e7e42a3214879a21052e897f9afc0653c12ff15d5bee7766e26a1af6ab17",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_DiscoveryMap.c": "dd350bdda1bdf427ab8cefab623fe60cce5332b062d1a29686fe52f73e9e83f1",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_DiscoveryService.c": "34458b3a4f7062375c9c5b5599308e9cea67fc4a316420836f6694ca2c646ffc",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_DocumentComponent.c": "885c8ab4fc9e64c3f8b40056536096c8c32b011cb340b25ca00353a96da15c69",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_EnvironmentService.c": "c0fae5bf51ccf507bc84d44adc2d1dff021cd83653c0468b7645a4f343e3fc8d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Epinephrine.c": "e04c53c2f665997023b2daee744265cd22f4f0101444e4d9b0efbd114f74fa9a",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_EscapeGameOverScreenInfo.c": "6e3c65e55b05cf205040c310b9086faa41b88582c7f9faf49c010afd59da5b07",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ExtractionPlacement.c": "6d388fe21f08b25cbdb5dfa4e198d94a4c80c5092f8d17630a4654e18bf8b3f5",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ExtractionService.c": "91357099b4e0401196b67d48963be54be30e56bdba57cdac67dc20b8ebb883e9",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_FactionCatalog.c": "a5a8c53acf21259e14f59cb919535910f30dabff5a9179c664bc6a7a4d744d6e",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_FactionMenu.c": "3549339d7796e67fc646680493c226e545b6fb95daa0270af9901795bdf8ed50",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_FactionSelection.c": "077c09491f4444fc58f093975fe9b3c294ea1fc966abef847ee5f13aa795ee29",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ForceLedger.c": "0ecaf1c5a52568e751678b0b1236e91e6adb538f8fbf010d38b61a312d1bf253",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ForceSimulation.c": "2bbb8888c752a3ffc042f3059937526d25ae288af5b4db024cc683025a2605ce",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_GameMode.c": "89a29c03ba225acbbb9fa3c58a721aced91a77bc0c77046d697005a6d7c48bb9",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_GeneratedSites.c": "4a23058f27e3ab074df6f8f7bb6f08a8fd26fbadb8943c6fb8d64dcc9c221751",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_InitialGuardRules.c": "8c9d6b1dc4c2af96284e34f487eebb5a221091016ef108006dec60b4e3836558",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Inventory.c": "b63e679d5b650b63a7a91dfc3f42a62f4be58b0338f6df3313e66d29a93bebf6",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_InventoryLayout.c": "1af5df45a0f06d19a017954e9bf4b2d722e2d2389f8ffdeb1d024435b9a08be8",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ItemPreferences.c": "1c4bc25a6ce9b5ee10f82592f955b0019d13ddb4084a783fadb98d267bd0f4fc",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ItemStationTeardown.c": "102e61216e86e47ad243cc19f6f66da1fcd8cc77f8799354ceaeb4a6dc74622e",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_JournalText.c": "87a6c19429f12c5630ed73170ca9a8a6d2255d6cd38b130166a78aacd15f2de0",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_LoadCasualtyAction.c": "1521af55a34110ce1c971b5226a618a9c6d931622abaae4946d9c0d27c05a273",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_LocalAdmission.c": "a076922d1ae966cf5cc67b198166ca6b1288358fb7f641207a4681e6a610a2ae",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Location.c": "5b0b058130ccac02bdc1dcd6474d51a6f45da4dd52ed6c37906692fca3f194b1",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_MissionRules.c": "f7abc38ad8fdc375ce7fa63a65f0bade027d22b37e09de5e3f94ba8c3c63cc41",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAdminMenuProbe.c": "ec8d04b6550b39b9688ef67b40cb2f14a9d98c8fff62b6dfb8d4a43e19b4e4c6",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAdminSettingsProbe.c": "73e58561e08e50008d33f81eed606dd4e8109fb69a627e892d28ca468d641f7d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAggressionProbe.c": "85a34cf60018e90d974cb67ab0f358f3073b6b9f02c563ec200e062f1d249e3b",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAirfieldMarkersProbe.c": "593e59664dbd7330b52674e5d4cc7b70db588cb75a1259ed808b74602501d541",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeBaseSmoke.c": "e811e985048e07365569acde6b5f045d57e9bbf13927f85b74e6e347fd2ef571",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeCasualtyGroundProbe.c": "41f40db3735f8aa535c0061458d9892dcfe972222b8a17238e67b65633c46bc3",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeCasualtyLoadProbe.c": "94c533deea654ec546df3f1ebb7cd213e6cd79b1125d99bab5303ef8e87b018b",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeCasualtyRemoveProbe.c": "4cfc06f6d43b709b63caae714155ffc562502e884f49a9825623c6f46972ad36",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeCasualtyServiceProbe.c": "02a9d70d1f4ba20326df199ba41489cfbae12b7bb0aab441361421cee38ad9ea",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeContentProbe.c": "cb0ccfe1e1575f9ed80a8054058b471f3543378db059e6af2fed8eb42a262638",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeContractsProbe.c": "421e4b901afe6118b6bf44e8f678db8ccdf1c83b39da0cf816baa36f7275ccdd",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeDefinitionProbe.c": "904d8d4c3e7b91d49dadfe495fc7b4f02f300e4aaf7efa348df5ca17ec4a6e8a",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeDiscoveryMapProbe.c": "9ed32d391d08d937ff4f9f33bd11c3a204ce9a2230c2d72b6761e0320b31f24f",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeEndProbe.c": "2dec80c7e247ec5c257407f95d9d5edd42fe0cc44d6af9f724f6ebd10d8a355f",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeEnemyLoadoutProbe.c": "0885ca69f6fa7f53414ce1792cfc3c49916886b8173783c634135c13c5d37429",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeEnvironmentProbe.c": "9e2e66ac5d9778a1c65445348e3300cbb90b68b3f669f3ddf1d2b78a858430eb",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeEnvironmentRestartProbe.c": "7a836a206381b8e8de24c92baf141beb30575723675dd6948d738169ed26b507",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeExtractionProbe.c": "4b09385f73206de004f4f3c38a6192fd658a0d2012482dc5a84dff1599ceb972",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFactionCatalogProbe.c": "e3011fa47b67122d7b2c23af8f91b7a217599d6cc114c4f9de628744b9c948d3",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFactionSelectionProbe.c": "946879d822e7be2d48e03a3140aa1aad3e3d44dd18507fa3cdedb4c6d7dd81b9",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFlightFootprint.c": "a8862a04ac784426f431e2e9cd3f1f19f820b38a081674d29549b8b00277c72d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFlightInputDiagnostics.c": "e231dcbdaefe81beb3bd587cb73be8fb3d3184bc86d18dbaa30a43ca4ba5dcc4",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeGeneratedSitesProbe.c": "83ab84ca4de7b545963896ed9d14e6545c23a2b940515730d74acc2f6b3dd18d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeGuardCancelProbe.c": "bfa1c65cb039e19c3d1891e4a3fd33469e974c97cc7f42128efc31a8f587d514",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeInfantryCombatProbe.c": "3e4c4382ab91f470357268927b954fd101685df6b2244df483f0422d6c0d7da2",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeItemStationTeardownProbe.c": "028588a49fa9207087cd27ec9396979cd932daa071e2490bd0262cd71dae30d9",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeLifecycleProbe.c": "b613a5dbe81c2032fd02d31070ae5631166d14d0b02cdbec3b63b782f0bbc115",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeLocalAdmissionProbe.c": "29c860ca3e51cdaa463f3c23a98ff45ee0499ce9bbc322046e0efbed587f1e09",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeMedicalCombatProbe.c": "3b9c557b249728c518f9d6b5cb24b725ecc32a69ae12df069cdfb0da70a80b95",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeMedicalProbe.c": "4b73e7cf35e9c8fddb089678a320ea58272e1b6611318d0a762754c171eff785",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeObjectiveLossProbe.c": "6b80fd317a8c6e8583bd4337870838a86251e3b8a681d0aa07e8b52e22abfc48",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeObjectiveMapProbe.c": "2d07b895cb74af58454605fb1c536a566733e3001a9375dd0677d5f274bf2a46",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeObjectiveProbe.c": "71fbd2479a70048f83d8b262ad1452f427be2c0afc8b071ef13bff477b9dc29b",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeOpeningToolsProbe.c": "0c5d6b96ed5a7cb1cf0d098d534dc7190449ed09339062e6b584729d53a61b4c",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeOptionalSiteProbe.c": "19fc19e22348e6213827f620f4fdb5dc26144ea2ce0032de773e79c1fb155a26",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativePatrolProbe.c": "5a2af71cc4cfccc7dd7c23584398a38290eba1a8894cd46f6967252ff3a7087c",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativePoweredFlightProbe.c": "7ae5d6f85bbbebec214c66bfdf6f53b93c802f109fcd5bcfbad82c5d61d6cb9f",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativePreparationStatusProbe.c": "456f4d7c3272b89d5f4c6713617baa5596d846994152356fee9a659839bcd8b5",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativePrisonBreachProbe.c": "4889e0d3799a6a21b9f84bcb2f2ae78dce16269cccd1329f8d1fcc1a23e7c22c",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativePrisonerProbe.c": "e2d1ffe5d269add55124601ff0d1dc032a398c7d51010736e6f0e4cbeb38ae86",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeProgressionIdentityProbe.c": "1d3fe20bce761a1082964bca9bad9ce79d1fa8b04db9b5053bae98da380ae560",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeRadioCampProbe.c": "67f1a088f9b20e5f0f11ed3aa083ffa772bffd7c74d85b7a307344ac3d47e09a",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeRadioDefenceProbe.c": "ff1e27a0ce75b123a86e7df31354831880ca62ea90b6c5d7c60d3ba168e1fff0",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeRadioInteractionProbe.c": "7b27552d233813894f65c08eb9f04b547c4ca9ff96a2370a763cb94bd4a555c3",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeRecoveryProbe.c": "d6691f22432b3ce37d07d448aeb3ce7feb5cd09e852e0167b5e4676afd24bb21",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeResultProbe.c": "c9a89cae067f221b9f33965b4d3ab311b78ba79ea383ca65032c4001df44b472",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeSiteGarrisonsProbe.c": "1a5ff8747d7501862085b5e9162043fee3b05e82c73c516ad8093aaada53dc60",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeSiteSurvey.c": "ac0203753ade0cdff6d483132797a80e4520f14546c3f9dea288281cd4cd9c4f",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeStationTeardownDiagnostic.c": "172248540932174341882861bb78a9720a6cf89981fcdf9dffe63f7fd4023f2c",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeTimeProbe.c": "4a2c6ffd947334a0a71eac083d10c853c524b00042e9ea0987497c4cee60c3d5",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeTransportProbe.c": "7a3fe04aa1c5ed1061ff63d9d5180e8b925932b62d76c1ffb49bd3dc23530993",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeTransportSurvey.c": "816df9a2a9072f9f7db75e56168d8a8fa1e665ee8f7dfa79af011b354254909d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeVehicleSecurityProbe.c": "59bce863142e4fba4b6fb2f544bb8a58061f0e99b1a38e5ac291cea919563763",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ObjectiveDetails.c": "628ebd166dcb5544c2d18dce489619984887ee18296cf2446fc6d894f89dd5bf",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ObjectiveMapPresentation.c": "f189f8987244e10df61ac577bbbc952ed5c4e6c431a8e3cd192a10fe2e8c3bec",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ObjectiveText.c": "8d75b35ab977be0cb1a2e3d3d1cb8ef875cdbfba69c35784c3d195451ef944c6",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Objectives.c": "b9cd5bb3b193c20401175c4328405be1b121e8a60b7b5999910b6a71f834af8a",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Observer.c": "682aa5549470c69fc72d261fbfcf9f7a04a41a66e0101b269ccc00bc282ad05d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_OrdinaryGateObserver.c": "1e376ca83c0005cf532539e14d7f47363c47b7c5b03fe3d55405a59208705fd7",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_OrdinaryInputObserver.c": "808a46cc1e4b31b65dbbbcdd55493f594ebb3974bbec38b4a2402334c653c0ef",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_OrdinaryLookObserver.c": "d5a1b636938d65e9d11c78b31487f2924400c34d98e2ec812954a2a224da7dc0",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_OrdinaryScenarioLaunch.c": "a4e7e56d174ebd15b4730202dae4c8ed06144f3f27c23ed49c99e2d297dc421a",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerAdminCommands.c": "eca9baa3b07da48a740851583540840f8bf5f65f7be854902a3778f76967faad",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerEscapeResult.c": "3124ab4d2d6d471409a47aba0af528790734df53243c03fe0cdac3e407047c14",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerGuide.c": "e49bab76a015ab545088af7e5eaa3cc45811907db4e5b1c5fa8c18afef34b62f",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerMedical.c": "270454d50235bc28df9bba4fde2689934578874c4eca9560afb9f0f6324d7215",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerRoster.c": "c038dac0f749bd29ebc35a4e952904b41a34417ba738904d5efcd1833a263e0b",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PreparationStatus.c": "43a406822a0361f916abc363f27e0c578ee94855036981d876bf47c68233c71a",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonAI.c": "8709753e86dc2ca777183f08cb8fbb9851e0c0de495ca01520ebcb1b3dfa59b9",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonEscapeService.c": "535cf17e21fc8e62716c7d9da88d976ee2f526501c6a4752b822f1252e742bf4",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonPatrol.c": "284618391ee2da84dbcda4a99ca3c072eae3d67b8a9ef40a86827b9ea00810f9",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_RadioDefenceService.c": "f5f0bf1352141f933d0edb5630e30541e001dc07e1d2c8529b29cc159c126b13",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_RadioFeedback.c": "545262e65e9b3645d9e514a0521e442fe08f0c2e4e7c83ba638c5105d09818db",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_RecoveryService.c": "86f9a7769e3ccb19fc61127fe2fee2ad0dd825487a5cd59f334de8b9741c93cf",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Resources.c": "d0169aac6fd0c38928c47a9002ded0fd8ba558ea3314a600e792d307ac1ca3ee",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ScenarioComponent.c": "81bf30d358c7b100248be17cbc2e6beb2f107300c939aede8a92d273eb7dae1f",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ServerItemCatalog.c": "e306b9d179b97d0478f821be3ca606c71908a21a4f87085b37a5fd18c4e3575d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ServerItemsMenu.c": "c0c3d9d1cf4615f38c793f1250315bbdb9349f33afa0841851da89433a303c3e",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Settings.c": "1b466886e9f5fbde1de0be20395e3887046c6b5a9a239dae92cecbfb721714c2",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SiteDefinition.c": "2088c45798f0eced702e0abd97550b8d1fc97ebcc34c3d497978b7424f6c670d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SiteDiscoveryRules.c": "dcbce3b7aee89bfc47a50e9de89209758af1f1bb462b99af67a8ad7a26e9f229",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SiteService.c": "210646e679056f4a46ef454a5abe15bd42d48349aa376ccfbb6b3b2ebeac6812",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SiteSquads.c": "183883783a4e8399cf62851a4cc65a5d091d25131bc53b4323cf17286315b2e0",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnClientScene.c": "b56f99a91cdc53bdb93d320d10839339022d7e61e6b101eee8296271abd7d3cb",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnFinalization.c": "c949642366ad124dd2abc4111cd598eb94aa257fbae01b6fb3a0f1882a23e83e",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnLogic.c": "47a39c951be71bfcf1cc50526d507d0f9d8ef2fc09408697b6fe6b0dc5a529e2",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnPlacement.c": "270bf465808d23627a11e720c6632d4fea35d0c679e63aa64046ef8874d68ceb",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnSceneInventory.c": "76b79d5bd9d1f367e1ed19724302b7d49f8b0ede85cf19e89c452582ef651f8f",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnSceneLease.c": "20de7f96bacc9037580d88d4424664b4554b2c082d82e7d29913e9dfe390b594",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Supplies.c": "752e8a56b0b8cde33cf532032cb0a203553017b686faac2e19bee06f7a9c0713",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainCatalog.c": "ba2e68543a8c929492d06f8725a743d26849a630d6f8c09be0f23894f92d0990",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainMenu.c": "1da542ef60ff7c1897b1f12432c636ef6a08cc710bac520ef186589d506e9a54",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainPreference.c": "ec25e5c3a5b97527f9cd70341c10d69d7124048089d26883ac2f8c9b3fd2815d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainSelection.c": "ee75cac068b99e7403f5eaabe556152513cf5d973602cc6e6b8967d25402f6ad",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainSites.c": "63ad027dac5bafb9e93805c361cbb27bf82af0567ea181a760ddedea98204c06",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeover.c": "487f1d004aa4f7a5f58c12c37724b26fcd54fc62b4096d48f3a7436d9958274c",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeoverClient.c": "458b84b3fb31c5a2bd1b7c3d65f25e0aeab91f5505ef0813231435c8a3c7d2b7",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeoverManagers.c": "5b7661a5617b7124a10d3c18e087a4e2363a967eecc5c87ecc94573f2abc07f2",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeoverPresentation.c": "d66a29a44e999cc3f2e56ba9c3c6bc936c027747312e08778ce301c1837f2112",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeoverSettings.c": "da22775930b13e41d4a71409e37af3bb99e4cc1d94bdea0e3b59fbdcd4d40132",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TimeService.c": "63867760876d523a1794f619118a52c5cd387d5d92756cd286b2c16a348a6c7b",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_UnconsciousCameraProbe.c": "66b1c4591b0ecc67cb08418a115bb02ed2b0168b7ae970f1e0a1ea335c59dc5b",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_UnconsciousWeapon.c": "24d31bc857486638e55c605283c17cde0cdbd3c5c6021eac1ec93611387b10d1",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_VehicleSecurityActions.c": "bd7d0aeb4abcc9d8044e4888f9a92f9e5fc97c098bdfa3bbad57e1a29697a779",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_VehicleSecurityComponent.c": "2ffec4e646584ec546147fc4b08249825cb32b531aba26467b586d760485adc3",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ViewDistance.c": "8514f72f8207f12570d2317e64094a45507a1647dfd45a1501499ef81e90189f",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AirAmmoMission.c": "0a471a40c8f7dfb797d8d35e41c5b1ff91e8d2ab13b43cf866e46c0e4ab4ed9d",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AirAssaultLoad.c": "5554994115cd7d56152ac78ba53034bf934b71c5634b17d35e96884dbb3b8a24",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AirAssaultSystem.c": "2eaf9816eee3e1cd2ac70744a6ef7ea5a90d0a3eebdf925e384028a7edde6a42",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AirReconSystem.c": "f8a0e3cf4552d8133efd33c2126ea15a7694676773a7047c15e00021c1d9721e",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AirSupportPolicy.c": "b5dad011d5a0574a406d6469e0744a9d37700cb41930dada28c5143d556acf53",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftAmmo.c": "2be282406d0c45ab2e35b0ced791b5e494c662588f536701a4e82e6f5fb7c913",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftControlBridge.c": "b8f0141644d8f043c6db4c2d4bb93215c548e5c27ab5468c66e996d62bdf905a",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFieldEnvelope.c": "0f53c7d9ab167a804eb904d63725decebb53fd5796fdf27864a75abed5679838",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFieldFlight.c": "c04e264cff9963821852094c451502d31bf9c96d4deae2e8ff8a2373b53b5665",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFieldRules.c": "30be68f4ca2db7e169f6f0432815821179cddf9159f7b150341dc8eb479bbd17",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFlight.c": "aa25a8e67a30c48677bf528236402b7f8e5d815dc18df93b878520ad3d1fe8a7",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFlightEnvelope.c": "8125cef61fb283d0d7c4dd2df3c04b062b448f1101fd48dd53f4f4097df5fef3",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftRouteEnvelope.c": "e8fcef844239c47a1f2f36be420afe943bc450091b05859435406b46c87fa511",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftRouteFlight.c": "1d8d92bf6d97429d68a9f62018232e90cc124cc8d7445efeabe863706a31e2b9",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftService.c": "3f05209227986b5c6bfb193f8f53783cfd4ef083bce898e22257c3e63daed913",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AirfieldSupport.c": "c6d88ede0b1b6bac5a7075b6e2e783ccfa8850210aabd28bfa4bcdb698cc5f87",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AssaultParachute.c": "a93c996059e7166988e9d1b0b498cbfd36f19a1cf8520cb4e9215a8884752e18",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AutomaticEquipment.c": "5832cbd3a43748e77f4e7f1b59361801c6d0445e0e15165e97d7a897b338709e",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_BodyRecovery.c": "47d9374095d04f5f1339c220caf518a40938ffc20f891b1b51ae38579e7e1c25",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyBoardingProgress.c": "328f8a5eabb8174b7727eee1d675db83a2eb0be7b8e834db4e950a645ca5d7a3",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyBudget.c": "ca49c274146d56e30cc93fa1652cc34c0fe68ea95725b0b3e33ab3673a6463c4",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyCombat.c": "5c4b7576b28d51edea868cbb91a0ab31a40e6ddb558f1b8a38e07e20fdb2969d",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyMineStock.c": "4497d6b790a45df2b76d18541ddaf299b406def88b868caa29f096849026a42c",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyPlacement.c": "4d0e8b6e147486fb65db82a1060f0c5641c1319ba9e418bdec99cb5a422a7fbe",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyRoadPlan.c": "fae404f85cae63e63976938a5fdb73efc988ba25c5846564f12edca04fb88551",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyService.c": "b59016d83cb9d40136b98b4e0067ea490bc553574fc53603593efd5522dbed20",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyStartup.c": "360228fd45aa6ecd9426e36120b5e637d2feee1e3a4a89aac8207526b871c87e",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyEquipment.c": "c52d4a3cc0e71eb136487c42df2fcd5bd6da1c33d31dbd3d6429c237dcf4a8d9",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyGunnerSkill.c": "adf8bac5a6f7e40b2f9caff5fe9be590c4e4ce2b2b387ba39e741a3c4f4cc564",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyLoadout.c": "a48f32dbd7f209bf08fce2840aaffc1781c571fc679763be58987f6b082e776c",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyMapMarking.c": "0f161fd3e08a54e3e1063679127549e482c40253a022e9d06cd9ee4d740b8625",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyMedicine.c": "05d341a9a000bfa2084057bd67d476d6e35adca6c8518d74c27cd31b551bbb95",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyOptics.c": "759e0a88ff30cb781ee69b8a935865d63ede5b1d97f31d344018f650a967c37f",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyRadio.c": "3a97e5c3de9ff33873d97c6b2d84ae505cfc4f3146e047b928e76ec3b22c8789",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemySkillAwareness.c": "00c450d033e43fc45c9e2cb64a1d81161d123cc594a4292cfc5f68eb6c17ee60",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EngineerMine.c": "fe05cb6e813155d76fd497788aa92c9dd8c7cf4ec43e017172a8a70e16c00b80",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EngineerMineSite.c": "d838f5693d4fa5d252d529e59777f560674c02532f1041a5598e938b3a850839",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_FiniteMagazineReservation.c": "8278590ced1936d618905b0cbd0b5aebddda238d426a6a2a52e455fc36bbb502",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotHQ.c": "8748325b0810ea053b28d0ed4c00a75fceae1c0d1cd3b30efb4dafdc397632ac",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotLoading.c": "36da884a833e7a29743308490a3ce5ae299f7a451d87205a227163892aca4ed0",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotTransfer.c": "1946db0615130b0039b42ec80db12d9cc89b1b3ca5a7eca7d9112eb69c3bdcea",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQ.c": "5d66c53baf8762e76ae59e28721edaa348014af6d988d42891d9a84a6cf44969",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQAdminProvider.c": "e9bb5f2f3ec270074964fc8607e5a07c23f224308a4446837598d93e201d7775",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQAmmoReporting.c": "95c024cbdd35c02d9b0c3d389d29bb042e5dda6ffd2f5f0d896078274b3adb35",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQAmmoSampler.c": "8bb0ec1422887feaa340307d3c60bae50fc82d424fce6390876e580ff8b75e8b",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQBodyObserver.c": "f59421c1e0c83f0f480d7dd4d048b4b0a41193ed8fe8f2f627d2b6a696420ea1",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQCoverage.c": "8d9668858c47b7e9fee2b12d3ebd4e7cb88146b817cf615c4b0dade26c81b2ec",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQDeliveredCasualties.c": "1f738127e55e843ee2705007cedb5c08741f52f63c75eca7c80242177af82273",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQDoctrine.c": "6335728e89ed40ce11b811f00b61bfea76e94dd3379e4357cbfc438b05522bb0",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQJournal.c": "53563ff54fc4e0656713d6eaec5e88ddf69fd4bfa8ef6a67cfa13380d24031e1",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQLocalAwareness.c": "124260280ac8eda0e920bfcfc86932c9b21df6b1f7a6aa8acfc43feea3da149f",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQLocalHandoff.c": "2dd700dae9d9b232d22ca63ff01af75a3f5cc213ac24b7c0a43ffa38bc0b9ffa",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQMemory.c": "ec2047a477fb4273e22ae6bb68e7365f321f55c583b5d2c48c4abf2ac38e3b7d",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQMineSampler.c": "2a0fdc4d27e947a1d77b02ae23f757c7fa074eb456f817b7df0766583d757f55",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQMountedAmmoSampler.c": "88ea0fc0e13d7e3c22c7ce8b652816d1d137e4e6e37a72f48f0bdf515b936ae7",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQMountedDispatch.c": "cee3ae301ac2f211c290450b644a7942c9786a2a40d06f16e2a47efa96fd15b6",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQMountedIntercept.c": "a37edcf66e43945f331db47fe81cb2e0e767a7aaf8115244dcf9e6295932be98",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQNetwork.c": "0b73be993628a55e3b21c8670d540e39c938093dd5cb4d586e800ac530509b25",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQObservation.c": "57ad3f0b68d150791e30a7e4bd7dfedfb1ddd78a1c76f228e67b33ea9cb7144e",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQPursuit.c": "ab6ca0e1a7f36c104e664db06a74c80a528cbfd1de599af42e2194ef0a4f4ca3",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQReport.c": "12ea8ba08753d1e6d38b237087c1209cd2f9574b53c3ff0f27c082bed029c9ea",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQRoadIntercept.c": "0897e82d7805ef56f05f2b9c23903280285ea6bfa51796a2df86bb564ece78f7",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQStatusSampler.c": "b937eaed913a5095afa8e678dc1c36b5c805541bf8cd5be927069533d6baed1c",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQTask.c": "1147904bae6d72e9de47ce17bdada3dab489de4ed6e781dbf15bdbb30599ff6e",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQWatch.c": "abe634cf6003ae920ec1ed18e305ed462920204960894520d3dd11f7e5ef1c33",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HelicopterAvailability.c": "60eaef2f6d4b2fd44861c5a4434ef97e732e40a5ff7401e2da451ed2dd9c2762",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HunterCombat.c": "df1c319d10efd07ed6f971cf0e41d8d7e377b04ea7f0fe143bf94df733fd1d9c",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HunterCrewRecovery.c": "e76af0fbf6f436a9c3c9d4c7b779bc08a78f6fe705c08bf6d9757bbeb65ee8eb",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HunterOpeningPlan.c": "0b6275221dab491f148426df05e132579f3acc20de5559226c3b38975618355c",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HunterService.c": "79369d5cc30cf628f02df0023157ab423e40497325dfd6a73b218757f2b689d4",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoAccess.c": "ab4262f78d54782c5ecbf5fff4ebe3da16d72329658d7e18c0c35387dc8b3c7d",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoTransfer.c": "99fa26beb0c0869d0cd694500f3bfc0705c2c1cf674dea90d98fb93a59570ef7",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryCombat.c": "5684fcbee128a35107312452297f7ae2bec28aaa1b63f619fa649f36df8ea476",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryMineTransfer.c": "02c399413f80879c22b4891e8ec807c67a6235677095fc4b98bafdc360d6944c",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c": "b01fa948f204d49acbfbdfc5fa641b1d914e0eb91081e92a93816ae52ae88b1e",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantrySupplyPool.c": "c8e454573cf064ff392291d6feebf1f23be64390b5b8e944c03dd065f9f46b42",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarAimSolution.c": "59e8343d09f7a44871d8d3335d6ad1d02216abb5deed30d38b5ec9ba3f2c0649",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarBattery.c": "157024afc8fd3c1ffeea6ae923ff091e5773b9ffcf5f5864f8040d001e689110",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarCourierTransfer.c": "968e58ca700b4a11e5e04a5c159696f514a0b1bce531210172b913e495f7e2b7",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarFiring.c": "f2597d44c10d10de2462aa5e5450a22b8a5ad0eb99bd0cc09a8cf1ca2dd4a350",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarLogistics.c": "b3624e4a00a2bdef16f6c100bbd79910e3bb8c2ae8ec5fe2ad5aa70bffecd303",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarPrediction.c": "05863b2b4f9f70cdb288f91c722cbea163c13f2a2927dc485482e5bd4fa7d57f",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarReadiness.c": "4c3799b3f2681e977669de0cbfaeb307d9a682b04365bfc9f59079e762965758",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarRefresh.c": "52ae8d9d6cad92f42d68c634091b80a474d2666b6c06d63a8c30a3fab71494c4",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarReportLedger.c": "42a96040b63e56677353e55164ae23031c90f70b4d6673a9f412ad7b19e636ae",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSalvo.c": "c128850c7a78a4d8fee00ad38f48b265f1fbd1d9b24b092ddc5c205b0f0ad6da",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarStation.c": "cbbd7c86f722b664c85ab7c070ae1131d2ce5c41d1dacb4381bff9c1720a1866",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSupplyTransfer.c": "ad71084f507ad9c32d3055e7ec6844a1ec5ddf568c0216ab8391e902b56e417c",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSystem.c": "bc290ee8bed299d869598cbf41ec281653e0cc7f3c64c7214613df8a0fc83829",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MountedAmmoPickup.c": "5f7ca5b31f3b405c2a6ca32ff91042f5b4dac6ab9640ce67fb10d7a74236ba69",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MountedAmmoTransfer.c": "0b195784497672fdaf651f336c14f7be98c257f98c85cfbeb4f96fe1a401999b",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MountedMagazineSeed.c": "b42d0aac142907433df8bedc40de24c94813544016cf5f451846f1980250f995",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MountedResupply.c": "c26ad43705765be1c20eca37fbe2978b8c647151f6620ed37141657a4b7dc312",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirAssaultProbe.c": "c1d55b338b157b758e6ffb993d5f689029b28b13929797c91e5dcb15b5e561ea",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirLogisticsProbe.c": "58fe863775d0ad575cb566c78cef696c9826691cf49ef9adde76376be7316db1",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirReconProbe.c": "c1216e0512a0268e4dbb82429e228334401c0c3cac52ba4486ae6dc91e41576d",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAircraftControlProbe.c": "0cf3e72ccdc42e6ef20fb71d743f0e037a9e69b2e082c720fa705628cf790205",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAircraftFieldProbe.c": "b64907c7566a894ca2f3c49ede5d972d4087a938da1a0ca87bcbd7c2203b2c52",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAircraftRouteProbe.c": "8d0dca97e5106d1c84b64992c789e1af0689514beefc027e713ca6ab901fc470",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarCourierProbe.c": "740c8bebbd4128a9311b1167d1058549475d6b46f81c9b6c0d19650f4b50616f",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarFiringProbe.c": "ee570d21bede8baebefc799399712d9582b3e30ebda7299f6c941777f02ad2a2",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarSalvoProbe.c": "fb9ccc6b36247ab3ad828ffbb2556abf5c2838d93ea6cd1ad259c0a015142f5e",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarStationProbe.c": "a110f0abc753cb1d2f781e457e637dd5346ecd2e924eb5eb3a5c7dca3d1e2340",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarTransferProbe.c": "399c21940ef10777b46fdb3e905430ce43404ce1de2f4a6bb62f9c61c1a0689c",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativePatrolHQProbe.c": "a58f57530e333976dc96fc5a0f9cb6cf0cb069c55788824950c5fb2f965d8e26",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeScoutProbe.c": "41b39b1abe5e51a5b8a428d533cccbfb0dda9d7a570228dc3489408c60543f17",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeTownProbe.c": "ade130f49fc9d868281cee7fde383f084f70ed8d4b876dacebbaed8538e84999",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ObjectiveDefence.c": "83ef91c2118521aedb4c1838b2e47909c80e0950086449b98ced168f1fd87080",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ReconAirports.c": "7551347d776d6e0eec818d6468cacbca7ac53daee7317e0a1618ca3d39ebc762",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ReconCrewLocks.c": "684bc5b9858c7ed90ed2ca6d52fc0e731a7e37a116db776090257b72a63621ab",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ReconFlightComponent.c": "4966dad504b3f8f28a9ffc8ac17cc548b00066fe05213c49c662ea56de34c9d4",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ScoutSystem.c": "63287a252e4e7d5aefce840279f26ce3e1f286cb79cadb32596c37897cec7119",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_SettlementSafety.c": "e5c0ebc95521a9a33a3f7d9cca6c551dda862a08b7af20b017877aba9584795b",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoyColumn.c": "35678ec625fb0a3c0871e2c373fcff49816440a97a165ed25c8798dd72ef059f",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoyService.c": "5b1578afbf6da736453cc9d3872979eddd1649746aa32d3b0c7a9e3cab50057e",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoySystem.c": "f09aa817c27d6af0ccfb544f4ab1ae2afafb63d626641e03d87cfe159475d821",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoyTactics.c": "dc3acdffc8ca48f11b131f66d30d679ca68f3b3004344bdc78723bc9305915e0",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_SupportScenario.c": "a7b46253e1bb37cea7c29bb557fbf43ca207022d0f1cc927349441b2d1615279",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_TownGarrisons.c": "57f862476751087972fc78d0b27ab44e72361e27d32f15d55f9fe7fd7d6bd0e0",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_VehicleAlarmPerception.c": "45ac71d25e10a057a26a5b0fc7128935baaf47f4c0f87208a4420fa52086fd98",
|
||||
"source/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelAdminProvider.c": "d63ab5c547021aeb61d398b8a773afeedee4662d3ce15d9fd9d0e9e37262f8b7",
|
||||
"source/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelDiscoveryFeedback.c": "62f2c408383f410782d9d41fa50acd6bd8cf66eeb80d2b79f91852b9d2cf8d97",
|
||||
"source/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelEvidence.c": "6bbf8d3b83e2c09fd9a23a9a5e5e11d7c29af2e618116bee613562fc45af2b33",
|
||||
"source/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelReroll.c": "d8b04de9ea789732cc78ebce9aa60786c86fe46d05f671cf251eefa68a214b59",
|
||||
"source/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelService.c": "2911325c79a7a372628b18ffa0e110d11919ce2c2cd7b19277bfd608fdb03dfc",
|
||||
"source/addons/core/Scripts/Game/ERR/20_Intel/ERR_MineIntel.c": "3ce16cebaa9703b2f9803df7c11614f94de6460a9136dab8f80dcad41ae2b1c2",
|
||||
"source/addons/core/Scripts/Game/ERR/30_Map/ERRM_NativeMapOwnershipProbe.c": "32418602f085e3edba7343f42a6a691630b533be262002f29248e8ae87a38254",
|
||||
"source/addons/core/Scripts/Game/ERR/30_Map/ERRM_SharedMapComponent.c": "3a10f6ea25bf88a400bc3e6c339823433845c5db4f2f423835ccf99a1b1a843f",
|
||||
"source/addons/core/Scripts/Game/ERR/30_Map/ERR_ScenarioMap.c": "75fa1d742129ef7f33c005cd48f56db7f49ee7bde3c5428532b0b501b032b0a3",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_AdminCommands.c": "282fe1463add7af8771aa58507b254e69d2d06f50274d4c77321db073f8394f0",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeAlarmHearingProbe.c": "5dbb6a48909b76cd141e3a79ef01d2e68cafee55153821c4471f85c761fff94f",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeConvoyCoverProbe.c": "d2450140cf9bdf09210473234605b4c0d818ea5b91f9532209166a35c5d13701",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeConvoyProbe.c": "4bdc920e87fa768b0ef0ed893c70ddbbcc9255d74163d7b657fd2ec7c4f14c32",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeHQBodyProbe.c": "811244cc8297817efbfc3ee4edf01c868eae23c88127ba0c72e98ee7422da72f",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeHQMemoryProbe.c": "d8fec6c138bb0f5bdbf99ee82ffc3ac9b44d1045d8833da63f8aa5f39beeb7e5",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeHQResponseProof.c": "0f8b09fd8753234c91fd6baaca0e2f812e409ae1c4be8f340b648ae59b69c2f3",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeInfantryTransferProbe.c": "9b2de4dc22bdadd51b0271219a971dc8dc07f70ed3534f306acf03ed81b29424",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeLocalHandoffProbe.c": "0d4d61c424a16008595f86fa61f3b848caf9bd6e9ebbacea9c10254d88ba378e",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMaintenanceProbe.c": "852b9b397efc3f919c97fec63bc3df1a850cd7833421af8441994afd191951d4",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMortarProbe.c": "ddb892141500c192c0787b011d57dd8c07dd8c9a3ca5fdc407f6c271897bde0a",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedAmmoProbe.c": "8d197f7a1398625e5a19db3284b0bf72c6ee6e032843a3e4d9a4e58de42b6825",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedCourierProbe.c": "12710e9e5548fe8856f7a52f3566338369a8a1eedf0bd92af16229271872ada5",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedInterceptProbe.c": "34b0b1e38a59f14c4e83d93ec412779945388e6f4d697bda2f6cb90f519a6372",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedSwapProbe.c": "a6721fcaaccadf8eddb06687c7d587d0a3e377d5d1bb0b8e72e630fede8690ac",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeRadioProbe.c": "84524163c63402755b4f834f74dfe6d8e5c397dc26031f532593c6f79f5a93b1",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeRandomRadiusTrace.c": "7e946406067092e30b6b75cc6ef0c56db7f866249e02bd13648156933ee578d9",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c": "104c56794ffe90e61af6b35a4998d02fae7a68e2787092a88dbcedc3246d6ab6",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSupplyConvoyProbe.c": "701311de6a2c9fe8f0534a22056323c34072df26595dc70a7d4df45bc06e6c13",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSupplyTravelProbe.c": "32e6074e912491f2643a24cb44311b9fe5b069c76e4e94a45e7409ac82d36507",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_OrdinaryScenarioLaunchChat.c": "a747af09599ce4d0c52051f18f00c4624d24d137e328341b580b82e896c6bf65",
|
||||
"source/addons/core/Scripts/GameLib/ERR/00_Core/ERR_DiagnosticNoSplash.c": "0ea1b402f8927b6d68bf6f7e5caa2967f7e3a39147634faab147796b791933b5",
|
||||
"source/addons/core/Scripts/WorkbenchGame/ERR/00_Core/ERR_ValidateBaseWorldPlugin.c": "49a38c37b51e5318c7dcbcb01543dd9a6300d053f0d39808b3974f4edc45b871",
|
||||
"source/addons/core/Scripts/WorkbenchGame/ERR/40_Chat/ERR_ValidateWorldPlugin.c": "f567518b54f43b88747df2838cdfd6ebb34605c0919a3e7d271d28dd8b67a9b6",
|
||||
"source/addons/core/UI/layouts/ERR/AdminMenu.layout": "e8d570f7bf3b8c4067ad81d47bca7f35514b2f8c8748f5fa5f775fbe27debeac",
|
||||
"source/addons/core/UI/layouts/ERR/AdminMenu.layout.meta": "9deeece996f43b1f1fed6b5ec89279645c7b6424250200a42580cc088142e9bf",
|
||||
"source/addons/core/UI/layouts/ERR/AdminValue.layout": "cd811af6d2fb187f01c74e20ea07ad85669546b0ad70efae2ce52921ce26cbca",
|
||||
"source/addons/core/UI/layouts/ERR/AdminValue.layout.meta": "56b3d2335db400c1308e07c4a35d278b23ef32013dfd6dc82951866327428d08",
|
||||
"source/addons/core/UI/layouts/ERR/ContentRow.layout": "62d2c95814c99d906266fa96c6112e04a7fab1667e1a05e558d1d3974adc2d76",
|
||||
"source/addons/core/UI/layouts/ERR/ContentRow.layout.meta": "8c4bc13b41e7aee38e0ca640a97813ed1a6964a00e2cff9e1fe4ebd71fc2fdc6",
|
||||
"source/addons/core/UI/layouts/ERR/ItemRow.layout": "8ac6fbc7fe0ce0ffc3185516197303bb892a4415948f75ae06f3bc289fefcac6",
|
||||
"source/addons/core/UI/layouts/ERR/ItemRow.layout.meta": "33eaef9c403ea3a030e58ec17f78e46af457048243571ad5856fff04101fb60b",
|
||||
"source/addons/core/UI/layouts/ERR/PauseModsButton.layout": "d21d436291e2c1b262e33dc228b0d60a1d188dc9e85cfda6d2373f8281431b79",
|
||||
"source/addons/core/UI/layouts/ERR/PauseModsButton.layout.meta": "9ed6adabd8f53eb9a562d7186789876bba5c4202155ca894c1af866ca47354f3",
|
||||
"source/addons/core/UI/layouts/ERR/PreparationStatus.layout": "bd269cf8dc6f27735423743dd5b78242550518414448a0256e5e12fa6b92c459",
|
||||
"source/addons/core/UI/layouts/ERR/PreparationStatus.layout.meta": "75b12176a443bb911fc4ad446982d762201fda42ed38736b79bc5439fca31ccc",
|
||||
"source/addons/core/UI/layouts/ERRMap/ObjectiveMapElement.layout": "b364752c44896d67dad07e466a04f4504a50813fb36ee7c34c9189ea9677b4e9",
|
||||
"source/addons/core/UI/layouts/ERRMap/ObjectiveMapElement.layout.meta": "8691fe2eaf46568bca4a9f8128b247a8da810bb87a5546aa7ca3334e740270d6",
|
||||
"source/addons/core/UI/layouts/ERRMap/SharedMapRenderTarget.layout": "6e83a9c70282aff43b23a08b732739e7a241a31e8abf200498c90a745d3d60dd",
|
||||
"source/addons/core/UI/layouts/ERRMap/SharedMapRenderTarget.layout.meta": "5c846445cc089e2e08899ba703059d4adb805ff30ab5a16409a3cd59718cbd54",
|
||||
"source/addons/core/Worlds/ERR_Everon.ent": "22324bc7eb0d80dec8a1f3bd61a9df9201b72f749f4e751766b0c9d0b7d46b87",
|
||||
"source/addons/core/Worlds/ERR_Everon.ent.meta": "19d1903ca72baa326b4724a6791d0da1104a1e53f3f31dc1ca41a856efd68e83",
|
||||
"source/addons/core/Worlds/ERR_Everon_Layers/default.layer": "6bcb7fbb27b6282719dae8a37486e518d4cbaea385f2ea9af1918b36bb28b175",
|
||||
"source/addons/core/addon.gproj": "73e973a1f1c5910393e16f86a3a40d792031bb2fa3fc7f4dd87a06a16c3e34a4",
|
||||
"source.zip": "3a1147bb32a6c7128212e167279f7ffdcf9bc08ada2a4d9def51313f98ac5445"
|
||||
}
|
||||
+431
@@ -0,0 +1,431 @@
|
||||
{
|
||||
"README.md": "43b9108309161b6c9ee71b413da36bd5e3b907c406a09d35d339d087c11b895d",
|
||||
"handoff.json": "a084632e1bdcaea4f3437a581dda95422df63b1350703f1abd196a062ee6b20a",
|
||||
"packages/core/addon.gproj": "73e973a1f1c5910393e16f86a3a40d792031bb2fa3fc7f4dd87a06a16c3e34a4",
|
||||
"packages/core/data.pak": "6a4f40f7ce28d423bb7d51cedd2f2322246459cf4b5b79418613f2172a65f032",
|
||||
"packages/core/resourceDatabase.rdb": "8c4519cfcdd821fc84177f232d5cd910c4dd92d9a04245bb4ebf711371c0327d",
|
||||
"source/BUNDLE-MANIFEST.json": "7e2ce6bd191a166dfe96c7e20de316bf93f295f91e71977fb9a500a580895e0e",
|
||||
"source/BUNDLE-README.md": "c46c89a66c56aa6ba4349c50e66b8368bfe53914d1019912f961da83938ba4ad",
|
||||
"source/EXTERNAL-ADDONS.json": "172e62d5bb83a3423192205c2e002de0257170314d2fbca346cf8fd72a26ab1f",
|
||||
"source/addons/core/AI/BehaviorTrees/ERR/MortarRapidFire.bt": "16b263bcb2fb3ae361367a600753a829425620d2e6b350a891c51fba47437ab6",
|
||||
"source/addons/core/AI/BehaviorTrees/ERR/MortarRapidFire.bt.meta": "f2a44ece28891240e6bfa1d01af29428adcadbe82c80e287eb33cd5e58f1f90a",
|
||||
"source/addons/core/Configs/ERR/AdminMenus.conf": "a7f889f260e43656136fc159342129e5f48748d28c426f65f9faac37b624cf94",
|
||||
"source/addons/core/Configs/ERR/AdminMenus.conf.meta": "5faf5ddc0a51c1d0f82d60af00d91edc22fe9c39aac50d8d04b772a2c9271be1",
|
||||
"source/addons/core/Configs/ERR/Content/Registry.conf": "546a5a407c9e6c25c9157ae4392898fa3f40c04c7956649e62201f9ac0ba187c",
|
||||
"source/addons/core/Configs/ERR/Content/Registry.conf.meta": "046aa988bf8e972afcf7a60b6f2312f605f016f98625dbbd9cd75ebf9ea88800",
|
||||
"source/addons/core/Configs/ERR/EveronSites.conf": "b479000b36154a6a3af6b519b086251d981ef63cb86a973d00529499cfd4238c",
|
||||
"source/addons/core/Configs/ERR/EveronSites.conf.meta": "d5fe68025ef4e7c1e16082cf5873b7c7172eacbfaef4ab29b7e0e3c98f8dca56",
|
||||
"source/addons/core/Configs/ERR/Factions/MissionVehicles.conf": "5f74f4a7089c7e7b54ad62463159ce8f0bab25a6b85268dc3872ea6001e048fb",
|
||||
"source/addons/core/Configs/ERR/Factions/MissionVehicles.conf.meta": "00c368b6271d3440cc8bf627b03a384d247635723923fc5ad2104b8b4007b035",
|
||||
"source/addons/core/Configs/ERR/Factions/US.conf": "4c3da063abb6e3ee39a6e4e0c5a9ffd5eae9d209d58470ea18b45dba5528db1b",
|
||||
"source/addons/core/Configs/ERR/Factions/US.conf.meta": "a05469aef028e9e17eba545e81e2af2887b59f0fef17dac51a23c7b8155e381b",
|
||||
"source/addons/core/Configs/ERR/Factions/USSR.conf": "407ea27f80a64c5184c089d43cdd0bdabfc5974c84f1d2a245081fdf2afa3f30",
|
||||
"source/addons/core/Configs/ERR/Factions/USSR.conf.meta": "057397d97096346791b51b7b13fbe18af218bcf78e9984d9c01b49a2403de611",
|
||||
"source/addons/core/Configs/ERR/GameOverScreens.conf": "45231061911a1462d45fb6db0fecc2b0793f17b5ae71017174954ff4fbd20236",
|
||||
"source/addons/core/Configs/ERR/GameOverScreens.conf.meta": "eb654b745c0b97b41c991694569ef4877a3c2315e0826f9556337cd68690843e",
|
||||
"source/addons/core/Configs/ERR/ObserverInput.conf": "e898d645911e85b6ba902366cb23890d8bb14bbd2c485102e6d49ea728e9b054",
|
||||
"source/addons/core/Configs/ERR/ObserverInput.conf.meta": "9714dce6c38ee81bcc513c8ebef51d7af63fd15bcdda2e40946937c625dc3ba4",
|
||||
"source/addons/core/Configs/ERR/Tests/LegacySites.conf": "3864eb638d0ed4dd313013d2d787f975ae6ce4bbe238569919f76b73d5f7ca42",
|
||||
"source/addons/core/Configs/ERR/Tests/LegacySites.conf.meta": "097ac7daef4fc18344699a8471fdd77f9d158f8c70bab394068d7a08e4777ac0",
|
||||
"source/addons/core/Configs/ERR/VanillaFactions.conf": "db890b61b48ee15484041fd2245a862d9fa9e7ba21b1229c281ff37c448a35b1",
|
||||
"source/addons/core/Configs/ERR/VanillaFactions.conf.meta": "ac77725c0c21974991ef47a466b88122e939de8b46fd23e68889e7674cbb2bfd",
|
||||
"source/addons/core/Materials/ERRM_MapRenderTarget.emat": "9877c5b175c5f30dd80bea36c711b21ab38219aa7075adf9ae79932e1d4c76bc",
|
||||
"source/addons/core/Materials/ERRM_MapRenderTarget.emat.meta": "5ee1a705f8011a44020ca2691f5ccc17d44bf596fef9a36e98d1f267eb58fab0",
|
||||
"source/addons/core/Missions/ERR_Everon.conf": "936619df7789a6b4b80bd763f702526e1145ab4d5c300516c07e7e70dfe57d92",
|
||||
"source/addons/core/Missions/ERR_Everon.conf.meta": "0a23c98bf83873536c65fa17d38dea33a1d7b9e4ab210f90633ff688abcc551f",
|
||||
"source/addons/core/Missions/ERR_Everon_Base.conf": "b46e1f4aeef383a8dbe7ef2b5c12a55a8111856c52ba103a1e508c01b82dfc61",
|
||||
"source/addons/core/Missions/ERR_Everon_Base.conf.meta": "9b16267c644d815bcf98a3a3aaff30b93d7224fb24d3a2bac66730a28011f317",
|
||||
"source/addons/core/Prefabs/ERR/AssaultParachute.et": "b556997989605e2a05982418b7e9f26d12d427eb3ea6e3bc50e85c67ea7aa4b8",
|
||||
"source/addons/core/Prefabs/ERR/AssaultParachute.et.meta": "e9dea2d533ad1ce6ce689e0e2815c97a6382e1b90c35ce1efa88a885527e8e18",
|
||||
"source/addons/core/Prefabs/ERR/ConvoyCrew.et": "29a525a29605386dfcf292dc2316e9fc7650ce39db9fbaa4ce4372ad0de66db4",
|
||||
"source/addons/core/Prefabs/ERR/ConvoyCrew.et.meta": "0a909a15b7dcca34202ded136b3bdbbe8898153c9589e1cce1388433d362da02",
|
||||
"source/addons/core/Prefabs/ERR/Epinephrine.et": "e09c70b3d47a4dc5b92fd332c8222b99554b28a8a0c93cb5caac18eec4501571",
|
||||
"source/addons/core/Prefabs/ERR/Epinephrine.et.meta": "f1861f0b0ccace1b7b3d9c29768e37a83bf0c6fae5a411b1bd61d6b2eec7ed89",
|
||||
"source/addons/core/Prefabs/ERR/Extraction.et": "4d24c7811415c06386205e5bf5c132a23fcf21e96c75c7657ccd5f3ac914ac50",
|
||||
"source/addons/core/Prefabs/ERR/Extraction.et.meta": "c2a838633001e2e3a202d39cb33aa744ebcd996017ad032359069641b5d13853",
|
||||
"source/addons/core/Prefabs/ERR/FactionManager.et": "5a7b330f33956cc1781c8dc843e8186f2d37a98653ab36e7c42b9019df3c89f5",
|
||||
"source/addons/core/Prefabs/ERR/FactionManager.et.meta": "9bf53d5e4bcbe60dd1a4ece1409fc23c349055c860708620f5f6e9716290a97d",
|
||||
"source/addons/core/Prefabs/ERR/FieldCover.et": "e403d5cb3a5966f0cea81f15e0e825d482ba1a7a27b12498319ba45a414963b0",
|
||||
"source/addons/core/Prefabs/ERR/FieldCover.et.meta": "83461ffa76244e1d69f20b053a9741ccdf7d127009182bd540a7e5ba6150c3d9",
|
||||
"source/addons/core/Prefabs/ERR/GameMode.et": "4d3e5e2df28cbb8292c436ae05d4fc7e5ca789a123450a6968d9a718b6ecef20",
|
||||
"source/addons/core/Prefabs/ERR/GameMode.et.meta": "106769cd34525c9d440057072836cb7401a6752148c40edd7fe61c03bd58328c",
|
||||
"source/addons/core/Prefabs/ERR/Items/EmergencyRepairKit.et": "0157bc235eeb78a0e1373b561fd22a1dcb225c833ff7c2d4abae688bca0ec92a",
|
||||
"source/addons/core/Prefabs/ERR/Items/EmergencyRepairKit.et.meta": "da6f065cb2414b5a4cbe9ef0f0b1295b2466f26ad406c0bddb83845d4598efb3",
|
||||
"source/addons/core/Prefabs/ERR/MortarCrew.et": "21086e886fe3199624208c9a866f883ec109f7d08746c2b56b497e59857fb656",
|
||||
"source/addons/core/Prefabs/ERR/MortarCrew.et.meta": "fdfd4fcd21a67c3d698fa4aadc4e5c76e665cebf4be86013bc389e493fab63cc",
|
||||
"source/addons/core/Prefabs/ERR/ObjectiveDocument.et": "5118ecaf9d2038eea44a4b785f05d2e78781dc1387249aa58a6782c7e6752e14",
|
||||
"source/addons/core/Prefabs/ERR/ObjectiveDocument.et.meta": "eaba9903be147b98a1106e2273e2270773df73b9b22f2cd4e20136a8e281382e",
|
||||
"source/addons/core/Prefabs/ERR/Patrol.et": "d3eca8fe9197c57a27a285cdb3baf168b037b198d92b39df28a338ae2cfd0c74",
|
||||
"source/addons/core/Prefabs/ERR/Patrol.et.meta": "7c5da568fa2fcf0709ee2959253cb068d7c7ed7c2467af3b247a7e70efd96b69",
|
||||
"source/addons/core/Prefabs/ERR/Prison.et": "c0ca5219aa2d6322ba7d094b92000640b259112ff6611a745c0713c8875d09d4",
|
||||
"source/addons/core/Prefabs/ERR/Prison.et.meta": "2e426ef3de68f4107907854b51e818bc11d84649a01c538e3f18dd9ebec766bb",
|
||||
"source/addons/core/Prefabs/ERR/PrisonBackpack.et": "ae750f08fc9af645561f59d7e5809bd22f4cec26ca8fa6409d09730765958c91",
|
||||
"source/addons/core/Prefabs/ERR/PrisonBackpack.et.meta": "7da6aa45467250edc910ad7230dc244d1b041e8a6f55881eb3747ce51f9212ba",
|
||||
"source/addons/core/Prefabs/ERR/PrisonDoor.et": "b0ff94443fe334032113a663917de23f920a8b73ffadc9c8e9f11b545022b3d2",
|
||||
"source/addons/core/Prefabs/ERR/PrisonDoor.et.meta": "b8f3db52bf186426026668fbb9d633c3cbd4d438ab301fba880398f6a0e781c2",
|
||||
"source/addons/core/Prefabs/ERR/PrisonPatrol.et": "dc88c31cf5c415573a874f74e13572f0add9e6122c8fcad507fe82860d789c47",
|
||||
"source/addons/core/Prefabs/ERR/PrisonPatrol.et.meta": "5528e0d778dce5ed39c3e504c6427625527127b23269d20fbf12ca2bffe52ffe",
|
||||
"source/addons/core/Prefabs/ERR/PrisonWall.et": "9b410b7c85bb001be4601ad93f750e17b8318b850306d84f29c4dc1b02723d7c",
|
||||
"source/addons/core/Prefabs/ERR/PrisonWall.et.meta": "0294bc5dbb56f90f8153d62459bb0a6ad91d76a479812bbec9c7db182fdb58d6",
|
||||
"source/addons/core/Prefabs/ERR/Prisoner.et": "e6d345ac98ad9ec742bf6c3b8686839c3256df9833d31bb4bdf605cd41d0ba5c",
|
||||
"source/addons/core/Prefabs/ERR/Prisoner.et.meta": "974278ba49fafeed70b619a0067bbc70ae4d534be441c812ce2bef4a5fb3c022",
|
||||
"source/addons/core/Prefabs/ERR/Radio.et": "99b1d80b49d1e7f9d30aa4283772a36fd66e962369f288f5fe329c7fc911bb1b",
|
||||
"source/addons/core/Prefabs/ERR/Radio.et.meta": "bc91137b68ba550217914fb8892bb44d7e1920e4a1086f3e506623832a44212f",
|
||||
"source/addons/core/Prefabs/ERR/RadioCamp.et": "5e6216bf8e6e160da5d9f966c8f7c2081bf6dd16dfac1b89d682a14b3b8a6716",
|
||||
"source/addons/core/Prefabs/ERR/RadioCamp.et.meta": "3cb8d3d553ab6d8d111a74f721cf4e69ee1011cbb90248b83cdc7275697276bd",
|
||||
"source/addons/core/Prefabs/ERR/ReconCrew.et": "33953379ceb725bcd0cbe505cd643c94adaed17dbbfa95dadd404d6b8e345715",
|
||||
"source/addons/core/Prefabs/ERR/ReconCrew.et.meta": "2653e8c5b1cdb857de5badd5959ddd9826a6a298ab3c166628dbb835d7104d90",
|
||||
"source/addons/core/Prefabs/ERR/ReconHelicopter.et": "c609ee59ab145e0a1936f95726b86df643f5cc425c43924029e9c1abc69ebbd0",
|
||||
"source/addons/core/Prefabs/ERR/ReconHelicopter.et.meta": "d80f1c3d6a6f9104562b89729996c1c92ad240f08cdcf48d4c390a09d2047c08",
|
||||
"source/addons/core/Prefabs/ERR/ReconPilotEast.et": "d961f329823b991eafed80d085de1bd89b44a4575be98d8dac385d6b77741ba2",
|
||||
"source/addons/core/Prefabs/ERR/ReconPilotEast.et.meta": "d73df3c896359a54514d2efcd851f579feca7a2619b76c2a38f607649a31a4f1",
|
||||
"source/addons/core/Prefabs/ERR/ReconPilotWest.et": "8f8221927269352e55c8026ee5b00e026c281c79af6684b386f24e7dc4675fb8",
|
||||
"source/addons/core/Prefabs/ERR/ReconPilotWest.et.meta": "4785f23bb492c6af420ee7896ddbfc9767e0db1e06de95207df2dc949a1b1814",
|
||||
"source/addons/core/Prefabs/ERR/ScoutEast.et": "b4593aab494c4f21637757b3daff4f349da77b4c48ec5e8a4a2917a6a12cf811",
|
||||
"source/addons/core/Prefabs/ERR/ScoutEast.et.meta": "7c72af632537f687e92f30b52d97fc7d70dadd39d33f37e0b1004f9596f55012",
|
||||
"source/addons/core/Prefabs/ERR/ScoutGroup.et": "8dc0fce8ee3decc1c367411b00b6d8518df9d8458281cec0881464a2ce906af0",
|
||||
"source/addons/core/Prefabs/ERR/ScoutGroup.et.meta": "62e43fd152ce57aa4ceb2187a49e4aecdeb9f428b3a1e8318f86bb83dbf8a259",
|
||||
"source/addons/core/Prefabs/ERR/ScoutRadioPack.et": "f1c4911e2556c0e0caa8b896982190c5e7d0433e850b4610e19442caf9117607",
|
||||
"source/addons/core/Prefabs/ERR/ScoutRadioPack.et.meta": "825506e3d814d30a52d5dbf64124470641c07a0453543ba71426841e6c783635",
|
||||
"source/addons/core/Prefabs/ERR/ScoutWest.et": "2681b5a3f8621adb44195f0dbca6f3e79ef7decad8f9d0dd0e1a801ec2549627",
|
||||
"source/addons/core/Prefabs/ERR/ScoutWest.et.meta": "22a6607b4b8fe606ca75a634a0b2ac3178e7bedae7f9ff01e7a4989f3b39a3da",
|
||||
"source/addons/core/Prefabs/ERR/SpectatorCamera.et": "cd2dcaca0df4c39816e582c594591a535525ed77827ffa3de24d27b79996544d",
|
||||
"source/addons/core/Prefabs/ERR/SpectatorCamera.et.meta": "2a16558f93915e31908a674509e9c89976470f78a84a1174a64b94b68b8f77ad",
|
||||
"source/addons/core/Prefabs/ERR/SupplyCache.et": "4c97b0514fe7e723046f40f0b396f6573b12eb9981ca5df70b9e8aa3cf29323e",
|
||||
"source/addons/core/Prefabs/ERR/SupplyCache.et.meta": "2f5de3a4aab1e9d0e35521f48dc57b95bd6e449c383dec4f1c258e10295904cb",
|
||||
"source/addons/core/Prefabs/ERR/SupplySite.et": "f33681281d26676fac88736091834d5a7b87fe0fa01883582542df964dcfc694",
|
||||
"source/addons/core/Prefabs/ERR/SupplySite.et.meta": "b41944b12eb3528ff7a3ac94258b18c66ef161aa6a38894aee300a1ac4798630",
|
||||
"source/addons/core/Prefabs/ERR/TerrainConnector.et": "cf9cb28f5a3f41931380864a29ac979aa1d5e843456f564ac7a7de78f88e1aa8",
|
||||
"source/addons/core/Prefabs/ERR/TerrainConnector.et.meta": "9f37c979ae282aabca29ce84beb0db851ee8b9a19f7f3a64d387c175616127f3",
|
||||
"source/addons/core/Prefabs/ERR/TerrainTakeover.et": "6206fe2eb4e2c6c1a9e3ddf2898535ae08981c115adc6ddd926017ac20d4b535",
|
||||
"source/addons/core/Prefabs/ERR/TerrainTakeover.et.meta": "64e953e378ab1d2a75ee7246f876f4ef93ae8a4e3fddb5002d7ba37268cb959d",
|
||||
"source/addons/core/Prefabs/ERR/Vehicles/SupplyUAZ.et": "29f157849f413261494a63d4d5b0a97e8bbe61cb076efcd59d6c940653f23352",
|
||||
"source/addons/core/Prefabs/ERR/Vehicles/SupplyUAZ.et.meta": "544c94cf1c26757a10654de7856cd6cc48b821ce3bdc02add13cfe6514269915",
|
||||
"source/addons/core/Prefabs/ERR/Vehicles/SupplyUAZRearSeats.et": "cd4acdcecad299445952aea0adefc85f2b9e9b43f8186f100e0505c5621b3656",
|
||||
"source/addons/core/Prefabs/ERR/Vehicles/SupplyUAZRearSeats.et.meta": "123955da03462befb90e293b3bb856d49cc761166611b38ff47cb48ec2fbe95c",
|
||||
"source/addons/core/Prefabs/Items/Equipment/ERRM_SharedFieldMap.et": "30dee8e9eab459ea32a7d835a9fb89d43df47708057cab829f067b25a24cd581",
|
||||
"source/addons/core/Prefabs/Items/Equipment/ERRM_SharedFieldMap.et.meta": "59093e9072c50d99c86da7609c87541016da5bcf92b98d99db4c524e1c8e0e8d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Actions.c": "cabb21413c90b252d29708b62228d0679c51c76e39ee0e483953ad7061b2b9d6",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Actors.c": "980d30964845600a261693cc5c5553e1472e8e54867bdc06133ff5c7b36c9128",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminMenu.c": "3b96a99832ed40002598a186dd8de1d21410c2e690df37a6319fdbeeeb4eeab0",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminPlayerTools.c": "56780d78bf423f54f482d8620f821b8d3eb0199194482b4f12e37f5ec3f55ef5",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminProvider.c": "62e05aceb49da07fed7aa89fb6b2f8eb3efc373ac09eff286fba983c3ad570eb",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminService.c": "c3e008c8bbf538c5bca3a82a975decc7a283a38543a9d2639d90a81ce592c51e",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminSession.c": "89d92f138a201ad7e752e027ba3930a2e0bf647d7b3a2c576346c1467f8bea3a",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_AirfieldPlacement.c": "0c2f4d31a2abc8f3f90bda20546543f2a1cf9306e9bf93351dda1883b990770e",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyGroundSupport.c": "26f0c7ebe8563bb022f7c383674e7d8997b0cc35c7ea321d39d74f2493c1ed9d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyLoadingFeedback.c": "e46988b92243df19a5400eca7406d6969b8b1174d8e3efad48fa0a936cbfdd07",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyLoadingGameMode.c": "f4cf19440583ac24346831a2d5f1d7f734c031e46dc266c499972329dd0533cf",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyLoadingOwner.c": "6346a05ddda030f7d9b6f026f977d5f018ee16002fa519e8c49dcd700c323dc7",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_CasualtyLoadingService.c": "e6f22813f7a04e2c0ea000d054407191f2be8badfa6c51e062e9dbf84b95c67b",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ChatClient.c": "4bf937ff74e0483c17fa0103f73bfee3afd8f67a37c0c248b08772a17bfcc349",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ContentDefinition.c": "bc1dd4ed27ec894cf4bd617fb226cb8140b544aaa9ef6d8654e815d81e7f6fd0",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ContentMenu.c": "c82b173496e7524b4570b2afc5493cb970252a19aed740a53011988db7700a01",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ContentPolicy.c": "3a4987345d5a7159234a7e1a08bf5ac40dd5a23031e9b1953fc43a0501d9924b",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ContentSettings.c": "572cc36f88255a37e8f0e9f284fb96e07c6c4032506b34b8c77d688f02785400",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_DebugAI.c": "bc5529c60591a6c36c39cdb753b1af948690fc3c3c725f38a8d595b41a499235",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_DebugIntel.c": "a9f6e7e42a3214879a21052e897f9afc0653c12ff15d5bee7766e26a1af6ab17",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_DiscoveryMap.c": "dd350bdda1bdf427ab8cefab623fe60cce5332b062d1a29686fe52f73e9e83f1",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_DiscoveryService.c": "34458b3a4f7062375c9c5b5599308e9cea67fc4a316420836f6694ca2c646ffc",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_DocumentComponent.c": "885c8ab4fc9e64c3f8b40056536096c8c32b011cb340b25ca00353a96da15c69",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_EnvironmentService.c": "c0fae5bf51ccf507bc84d44adc2d1dff021cd83653c0468b7645a4f343e3fc8d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Epinephrine.c": "e04c53c2f665997023b2daee744265cd22f4f0101444e4d9b0efbd114f74fa9a",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_EscapeGameOverScreenInfo.c": "6e3c65e55b05cf205040c310b9086faa41b88582c7f9faf49c010afd59da5b07",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ExtractionPlacement.c": "6d388fe21f08b25cbdb5dfa4e198d94a4c80c5092f8d17630a4654e18bf8b3f5",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ExtractionService.c": "91357099b4e0401196b67d48963be54be30e56bdba57cdac67dc20b8ebb883e9",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_FactionCatalog.c": "a5a8c53acf21259e14f59cb919535910f30dabff5a9179c664bc6a7a4d744d6e",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_FactionMenu.c": "3549339d7796e67fc646680493c226e545b6fb95daa0270af9901795bdf8ed50",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_FactionSelection.c": "077c09491f4444fc58f093975fe9b3c294ea1fc966abef847ee5f13aa795ee29",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ForceLedger.c": "0ecaf1c5a52568e751678b0b1236e91e6adb538f8fbf010d38b61a312d1bf253",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ForceSimulation.c": "2bbb8888c752a3ffc042f3059937526d25ae288af5b4db024cc683025a2605ce",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_GameMode.c": "89a29c03ba225acbbb9fa3c58a721aced91a77bc0c77046d697005a6d7c48bb9",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_GeneratedSites.c": "4a23058f27e3ab074df6f8f7bb6f08a8fd26fbadb8943c6fb8d64dcc9c221751",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_InitialGuardRules.c": "8c9d6b1dc4c2af96284e34f487eebb5a221091016ef108006dec60b4e3836558",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Inventory.c": "b63e679d5b650b63a7a91dfc3f42a62f4be58b0338f6df3313e66d29a93bebf6",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_InventoryLayout.c": "1af5df45a0f06d19a017954e9bf4b2d722e2d2389f8ffdeb1d024435b9a08be8",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ItemPreferences.c": "1c4bc25a6ce9b5ee10f82592f955b0019d13ddb4084a783fadb98d267bd0f4fc",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ItemStationTeardown.c": "102e61216e86e47ad243cc19f6f66da1fcd8cc77f8799354ceaeb4a6dc74622e",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_JournalText.c": "87a6c19429f12c5630ed73170ca9a8a6d2255d6cd38b130166a78aacd15f2de0",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_LoadCasualtyAction.c": "1521af55a34110ce1c971b5226a618a9c6d931622abaae4946d9c0d27c05a273",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_LocalAdmission.c": "a076922d1ae966cf5cc67b198166ca6b1288358fb7f641207a4681e6a610a2ae",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Location.c": "5b0b058130ccac02bdc1dcd6474d51a6f45da4dd52ed6c37906692fca3f194b1",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_MissionRules.c": "f7abc38ad8fdc375ce7fa63a65f0bade027d22b37e09de5e3f94ba8c3c63cc41",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAdminMenuProbe.c": "ec8d04b6550b39b9688ef67b40cb2f14a9d98c8fff62b6dfb8d4a43e19b4e4c6",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAdminSettingsProbe.c": "73e58561e08e50008d33f81eed606dd4e8109fb69a627e892d28ca468d641f7d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAggressionProbe.c": "85a34cf60018e90d974cb67ab0f358f3073b6b9f02c563ec200e062f1d249e3b",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAirfieldMarkersProbe.c": "593e59664dbd7330b52674e5d4cc7b70db588cb75a1259ed808b74602501d541",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeBaseSmoke.c": "e811e985048e07365569acde6b5f045d57e9bbf13927f85b74e6e347fd2ef571",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeCasualtyGroundProbe.c": "41f40db3735f8aa535c0061458d9892dcfe972222b8a17238e67b65633c46bc3",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeCasualtyLoadProbe.c": "94c533deea654ec546df3f1ebb7cd213e6cd79b1125d99bab5303ef8e87b018b",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeCasualtyRemoveProbe.c": "4cfc06f6d43b709b63caae714155ffc562502e884f49a9825623c6f46972ad36",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeCasualtyServiceProbe.c": "02a9d70d1f4ba20326df199ba41489cfbae12b7bb0aab441361421cee38ad9ea",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeContentProbe.c": "cb0ccfe1e1575f9ed80a8054058b471f3543378db059e6af2fed8eb42a262638",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeContractsProbe.c": "421e4b901afe6118b6bf44e8f678db8ccdf1c83b39da0cf816baa36f7275ccdd",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeDefinitionProbe.c": "904d8d4c3e7b91d49dadfe495fc7b4f02f300e4aaf7efa348df5ca17ec4a6e8a",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeDiscoveryMapProbe.c": "9ed32d391d08d937ff4f9f33bd11c3a204ce9a2230c2d72b6761e0320b31f24f",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeEndProbe.c": "2dec80c7e247ec5c257407f95d9d5edd42fe0cc44d6af9f724f6ebd10d8a355f",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeEnemyLoadoutProbe.c": "0885ca69f6fa7f53414ce1792cfc3c49916886b8173783c634135c13c5d37429",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeEnvironmentProbe.c": "9e2e66ac5d9778a1c65445348e3300cbb90b68b3f669f3ddf1d2b78a858430eb",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeEnvironmentRestartProbe.c": "7a836a206381b8e8de24c92baf141beb30575723675dd6948d738169ed26b507",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeExtractionProbe.c": "4b09385f73206de004f4f3c38a6192fd658a0d2012482dc5a84dff1599ceb972",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFactionCatalogProbe.c": "e3011fa47b67122d7b2c23af8f91b7a217599d6cc114c4f9de628744b9c948d3",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFactionSelectionProbe.c": "946879d822e7be2d48e03a3140aa1aad3e3d44dd18507fa3cdedb4c6d7dd81b9",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFlightFootprint.c": "a8862a04ac784426f431e2e9cd3f1f19f820b38a081674d29549b8b00277c72d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFlightInputDiagnostics.c": "e231dcbdaefe81beb3bd587cb73be8fb3d3184bc86d18dbaa30a43ca4ba5dcc4",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeGeneratedSitesProbe.c": "83ab84ca4de7b545963896ed9d14e6545c23a2b940515730d74acc2f6b3dd18d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeGuardCancelProbe.c": "bfa1c65cb039e19c3d1891e4a3fd33469e974c97cc7f42128efc31a8f587d514",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeInfantryCombatProbe.c": "3e4c4382ab91f470357268927b954fd101685df6b2244df483f0422d6c0d7da2",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeItemStationTeardownProbe.c": "028588a49fa9207087cd27ec9396979cd932daa071e2490bd0262cd71dae30d9",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeLifecycleProbe.c": "b613a5dbe81c2032fd02d31070ae5631166d14d0b02cdbec3b63b782f0bbc115",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeLocalAdmissionProbe.c": "29c860ca3e51cdaa463f3c23a98ff45ee0499ce9bbc322046e0efbed587f1e09",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeMedicalCombatProbe.c": "3b9c557b249728c518f9d6b5cb24b725ecc32a69ae12df069cdfb0da70a80b95",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeMedicalProbe.c": "4b73e7cf35e9c8fddb089678a320ea58272e1b6611318d0a762754c171eff785",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeObjectiveLossProbe.c": "6b80fd317a8c6e8583bd4337870838a86251e3b8a681d0aa07e8b52e22abfc48",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeObjectiveMapProbe.c": "2d07b895cb74af58454605fb1c536a566733e3001a9375dd0677d5f274bf2a46",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeObjectiveProbe.c": "71fbd2479a70048f83d8b262ad1452f427be2c0afc8b071ef13bff477b9dc29b",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeOpeningToolsProbe.c": "0c5d6b96ed5a7cb1cf0d098d534dc7190449ed09339062e6b584729d53a61b4c",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeOptionalSiteProbe.c": "19fc19e22348e6213827f620f4fdb5dc26144ea2ce0032de773e79c1fb155a26",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativePatrolProbe.c": "5a2af71cc4cfccc7dd7c23584398a38290eba1a8894cd46f6967252ff3a7087c",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativePoweredFlightProbe.c": "7ae5d6f85bbbebec214c66bfdf6f53b93c802f109fcd5bcfbad82c5d61d6cb9f",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativePreparationStatusProbe.c": "456f4d7c3272b89d5f4c6713617baa5596d846994152356fee9a659839bcd8b5",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativePrisonBreachProbe.c": "4889e0d3799a6a21b9f84bcb2f2ae78dce16269cccd1329f8d1fcc1a23e7c22c",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativePrisonerProbe.c": "e2d1ffe5d269add55124601ff0d1dc032a398c7d51010736e6f0e4cbeb38ae86",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeProgressionIdentityProbe.c": "1d3fe20bce761a1082964bca9bad9ce79d1fa8b04db9b5053bae98da380ae560",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeRadioCampProbe.c": "67f1a088f9b20e5f0f11ed3aa083ffa772bffd7c74d85b7a307344ac3d47e09a",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeRadioDefenceProbe.c": "ff1e27a0ce75b123a86e7df31354831880ca62ea90b6c5d7c60d3ba168e1fff0",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeRadioInteractionProbe.c": "7b27552d233813894f65c08eb9f04b547c4ca9ff96a2370a763cb94bd4a555c3",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeRecoveryProbe.c": "d6691f22432b3ce37d07d448aeb3ce7feb5cd09e852e0167b5e4676afd24bb21",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeResultProbe.c": "c9a89cae067f221b9f33965b4d3ab311b78ba79ea383ca65032c4001df44b472",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeSiteGarrisonsProbe.c": "1a5ff8747d7501862085b5e9162043fee3b05e82c73c516ad8093aaada53dc60",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeSiteSurvey.c": "ac0203753ade0cdff6d483132797a80e4520f14546c3f9dea288281cd4cd9c4f",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeStationTeardownDiagnostic.c": "172248540932174341882861bb78a9720a6cf89981fcdf9dffe63f7fd4023f2c",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeTimeProbe.c": "4a2c6ffd947334a0a71eac083d10c853c524b00042e9ea0987497c4cee60c3d5",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeTransportProbe.c": "7a3fe04aa1c5ed1061ff63d9d5180e8b925932b62d76c1ffb49bd3dc23530993",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeTransportSurvey.c": "816df9a2a9072f9f7db75e56168d8a8fa1e665ee8f7dfa79af011b354254909d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeVehicleSecurityProbe.c": "59bce863142e4fba4b6fb2f544bb8a58061f0e99b1a38e5ac291cea919563763",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ObjectiveDetails.c": "628ebd166dcb5544c2d18dce489619984887ee18296cf2446fc6d894f89dd5bf",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ObjectiveMapPresentation.c": "f189f8987244e10df61ac577bbbc952ed5c4e6c431a8e3cd192a10fe2e8c3bec",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ObjectiveText.c": "8d75b35ab977be0cb1a2e3d3d1cb8ef875cdbfba69c35784c3d195451ef944c6",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Objectives.c": "b9cd5bb3b193c20401175c4328405be1b121e8a60b7b5999910b6a71f834af8a",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Observer.c": "682aa5549470c69fc72d261fbfcf9f7a04a41a66e0101b269ccc00bc282ad05d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_OrdinaryGateObserver.c": "1e376ca83c0005cf532539e14d7f47363c47b7c5b03fe3d55405a59208705fd7",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_OrdinaryInputObserver.c": "808a46cc1e4b31b65dbbbcdd55493f594ebb3974bbec38b4a2402334c653c0ef",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_OrdinaryLookObserver.c": "d5a1b636938d65e9d11c78b31487f2924400c34d98e2ec812954a2a224da7dc0",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_OrdinaryScenarioLaunch.c": "a4e7e56d174ebd15b4730202dae4c8ed06144f3f27c23ed49c99e2d297dc421a",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerAdminCommands.c": "eca9baa3b07da48a740851583540840f8bf5f65f7be854902a3778f76967faad",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerEscapeResult.c": "3124ab4d2d6d471409a47aba0af528790734df53243c03fe0cdac3e407047c14",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerGuide.c": "e49bab76a015ab545088af7e5eaa3cc45811907db4e5b1c5fa8c18afef34b62f",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerMedical.c": "270454d50235bc28df9bba4fde2689934578874c4eca9560afb9f0f6324d7215",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PlayerRoster.c": "c038dac0f749bd29ebc35a4e952904b41a34417ba738904d5efcd1833a263e0b",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PreparationStatus.c": "43a406822a0361f916abc363f27e0c578ee94855036981d876bf47c68233c71a",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonAI.c": "8709753e86dc2ca777183f08cb8fbb9851e0c0de495ca01520ebcb1b3dfa59b9",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonEscapeService.c": "535cf17e21fc8e62716c7d9da88d976ee2f526501c6a4752b822f1252e742bf4",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonPatrol.c": "284618391ee2da84dbcda4a99ca3c072eae3d67b8a9ef40a86827b9ea00810f9",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_RadioDefenceService.c": "f5f0bf1352141f933d0edb5630e30541e001dc07e1d2c8529b29cc159c126b13",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_RadioFeedback.c": "545262e65e9b3645d9e514a0521e442fe08f0c2e4e7c83ba638c5105d09818db",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_RecoveryService.c": "86f9a7769e3ccb19fc61127fe2fee2ad0dd825487a5cd59f334de8b9741c93cf",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Resources.c": "d0169aac6fd0c38928c47a9002ded0fd8ba558ea3314a600e792d307ac1ca3ee",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ScenarioComponent.c": "81bf30d358c7b100248be17cbc2e6beb2f107300c939aede8a92d273eb7dae1f",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ServerItemCatalog.c": "e306b9d179b97d0478f821be3ca606c71908a21a4f87085b37a5fd18c4e3575d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ServerItemsMenu.c": "c0c3d9d1cf4615f38c793f1250315bbdb9349f33afa0841851da89433a303c3e",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Settings.c": "1b466886e9f5fbde1de0be20395e3887046c6b5a9a239dae92cecbfb721714c2",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SiteDefinition.c": "2088c45798f0eced702e0abd97550b8d1fc97ebcc34c3d497978b7424f6c670d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SiteDiscoveryRules.c": "dcbce3b7aee89bfc47a50e9de89209758af1f1bb462b99af67a8ad7a26e9f229",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SiteService.c": "210646e679056f4a46ef454a5abe15bd42d48349aa376ccfbb6b3b2ebeac6812",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SiteSquads.c": "183883783a4e8399cf62851a4cc65a5d091d25131bc53b4323cf17286315b2e0",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnClientScene.c": "b56f99a91cdc53bdb93d320d10839339022d7e61e6b101eee8296271abd7d3cb",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnFinalization.c": "c949642366ad124dd2abc4111cd598eb94aa257fbae01b6fb3a0f1882a23e83e",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnLogic.c": "47a39c951be71bfcf1cc50526d507d0f9d8ef2fc09408697b6fe6b0dc5a529e2",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnPlacement.c": "270bf465808d23627a11e720c6632d4fea35d0c679e63aa64046ef8874d68ceb",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnSceneInventory.c": "76b79d5bd9d1f367e1ed19724302b7d49f8b0ede85cf19e89c452582ef651f8f",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnSceneLease.c": "20de7f96bacc9037580d88d4424664b4554b2c082d82e7d29913e9dfe390b594",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_Supplies.c": "752e8a56b0b8cde33cf532032cb0a203553017b686faac2e19bee06f7a9c0713",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainCatalog.c": "ba2e68543a8c929492d06f8725a743d26849a630d6f8c09be0f23894f92d0990",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainMenu.c": "1da542ef60ff7c1897b1f12432c636ef6a08cc710bac520ef186589d506e9a54",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainPreference.c": "ec25e5c3a5b97527f9cd70341c10d69d7124048089d26883ac2f8c9b3fd2815d",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainSelection.c": "ee75cac068b99e7403f5eaabe556152513cf5d973602cc6e6b8967d25402f6ad",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainSites.c": "63ad027dac5bafb9e93805c361cbb27bf82af0567ea181a760ddedea98204c06",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeover.c": "487f1d004aa4f7a5f58c12c37724b26fcd54fc62b4096d48f3a7436d9958274c",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeoverClient.c": "458b84b3fb31c5a2bd1b7c3d65f25e0aeab91f5505ef0813231435c8a3c7d2b7",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeoverManagers.c": "5b7661a5617b7124a10d3c18e087a4e2363a967eecc5c87ecc94573f2abc07f2",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeoverPresentation.c": "d66a29a44e999cc3f2e56ba9c3c6bc936c027747312e08778ce301c1837f2112",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TerrainTakeoverSettings.c": "da22775930b13e41d4a71409e37af3bb99e4cc1d94bdea0e3b59fbdcd4d40132",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_TimeService.c": "63867760876d523a1794f619118a52c5cd387d5d92756cd286b2c16a348a6c7b",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_UnconsciousCameraProbe.c": "66b1c4591b0ecc67cb08418a115bb02ed2b0168b7ae970f1e0a1ea335c59dc5b",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_UnconsciousWeapon.c": "24d31bc857486638e55c605283c17cde0cdbd3c5c6021eac1ec93611387b10d1",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_VehicleSecurityActions.c": "bd7d0aeb4abcc9d8044e4888f9a92f9e5fc97c098bdfa3bbad57e1a29697a779",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_VehicleSecurityComponent.c": "2ffec4e646584ec546147fc4b08249825cb32b531aba26467b586d760485adc3",
|
||||
"source/addons/core/Scripts/Game/ERR/00_Core/ERR_ViewDistance.c": "8514f72f8207f12570d2317e64094a45507a1647dfd45a1501499ef81e90189f",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AirAmmoMission.c": "0a471a40c8f7dfb797d8d35e41c5b1ff91e8d2ab13b43cf866e46c0e4ab4ed9d",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AirAssaultLoad.c": "5554994115cd7d56152ac78ba53034bf934b71c5634b17d35e96884dbb3b8a24",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AirAssaultSystem.c": "2eaf9816eee3e1cd2ac70744a6ef7ea5a90d0a3eebdf925e384028a7edde6a42",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AirReconSystem.c": "f8a0e3cf4552d8133efd33c2126ea15a7694676773a7047c15e00021c1d9721e",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AirSupportPolicy.c": "b5dad011d5a0574a406d6469e0744a9d37700cb41930dada28c5143d556acf53",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftAmmo.c": "2be282406d0c45ab2e35b0ced791b5e494c662588f536701a4e82e6f5fb7c913",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftControlBridge.c": "b8f0141644d8f043c6db4c2d4bb93215c548e5c27ab5468c66e996d62bdf905a",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFieldEnvelope.c": "0f53c7d9ab167a804eb904d63725decebb53fd5796fdf27864a75abed5679838",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFieldFlight.c": "c04e264cff9963821852094c451502d31bf9c96d4deae2e8ff8a2373b53b5665",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFieldRules.c": "30be68f4ca2db7e169f6f0432815821179cddf9159f7b150341dc8eb479bbd17",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFlight.c": "aa25a8e67a30c48677bf528236402b7f8e5d815dc18df93b878520ad3d1fe8a7",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFlightEnvelope.c": "8125cef61fb283d0d7c4dd2df3c04b062b448f1101fd48dd53f4f4097df5fef3",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftRouteEnvelope.c": "e8fcef844239c47a1f2f36be420afe943bc450091b05859435406b46c87fa511",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftRouteFlight.c": "1d8d92bf6d97429d68a9f62018232e90cc124cc8d7445efeabe863706a31e2b9",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftService.c": "3f05209227986b5c6bfb193f8f53783cfd4ef083bce898e22257c3e63daed913",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AirfieldSupport.c": "c6d88ede0b1b6bac5a7075b6e2e783ccfa8850210aabd28bfa4bcdb698cc5f87",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AssaultParachute.c": "a93c996059e7166988e9d1b0b498cbfd36f19a1cf8520cb4e9215a8884752e18",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_AutomaticEquipment.c": "5832cbd3a43748e77f4e7f1b59361801c6d0445e0e15165e97d7a897b338709e",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_BodyRecovery.c": "47d9374095d04f5f1339c220caf518a40938ffc20f891b1b51ae38579e7e1c25",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyBoardingProgress.c": "328f8a5eabb8174b7727eee1d675db83a2eb0be7b8e834db4e950a645ca5d7a3",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyBudget.c": "ca49c274146d56e30cc93fa1652cc34c0fe68ea95725b0b3e33ab3673a6463c4",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyCombat.c": "5c4b7576b28d51edea868cbb91a0ab31a40e6ddb558f1b8a38e07e20fdb2969d",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyMineStock.c": "4497d6b790a45df2b76d18541ddaf299b406def88b868caa29f096849026a42c",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyPlacement.c": "4d0e8b6e147486fb65db82a1060f0c5641c1319ba9e418bdec99cb5a422a7fbe",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyRoadPlan.c": "fae404f85cae63e63976938a5fdb73efc988ba25c5846564f12edca04fb88551",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyService.c": "b59016d83cb9d40136b98b4e0067ea490bc553574fc53603593efd5522dbed20",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyStartup.c": "360228fd45aa6ecd9426e36120b5e637d2feee1e3a4a89aac8207526b871c87e",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyEquipment.c": "c52d4a3cc0e71eb136487c42df2fcd5bd6da1c33d31dbd3d6429c237dcf4a8d9",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyGunnerSkill.c": "adf8bac5a6f7e40b2f9caff5fe9be590c4e4ce2b2b387ba39e741a3c4f4cc564",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyLoadout.c": "a48f32dbd7f209bf08fce2840aaffc1781c571fc679763be58987f6b082e776c",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyMapMarking.c": "0f161fd3e08a54e3e1063679127549e482c40253a022e9d06cd9ee4d740b8625",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyMedicine.c": "05d341a9a000bfa2084057bd67d476d6e35adca6c8518d74c27cd31b551bbb95",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyOptics.c": "759e0a88ff30cb781ee69b8a935865d63ede5b1d97f31d344018f650a967c37f",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyRadio.c": "3a97e5c3de9ff33873d97c6b2d84ae505cfc4f3146e047b928e76ec3b22c8789",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemySkillAwareness.c": "00c450d033e43fc45c9e2cb64a1d81161d123cc594a4292cfc5f68eb6c17ee60",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EngineerMine.c": "e0098577626e719283cf4b40936e7ec038076c4bab9269fbad0b5ad3292e01e3",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_EngineerMineSite.c": "b629fecc29711e57f364f2a9c4c3e884b0978d9674311678f2e78b561683681a",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_FiniteMagazineReservation.c": "8278590ced1936d618905b0cbd0b5aebddda238d426a6a2a52e455fc36bbb502",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotHQ.c": "8748325b0810ea053b28d0ed4c00a75fceae1c0d1cd3b30efb4dafdc397632ac",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotLoading.c": "36da884a833e7a29743308490a3ce5ae299f7a451d87205a227163892aca4ed0",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_GroundDepotTransfer.c": "1946db0615130b0039b42ec80db12d9cc89b1b3ca5a7eca7d9112eb69c3bdcea",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQ.c": "5d66c53baf8762e76ae59e28721edaa348014af6d988d42891d9a84a6cf44969",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQAdminProvider.c": "e9bb5f2f3ec270074964fc8607e5a07c23f224308a4446837598d93e201d7775",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQAmmoReporting.c": "95c024cbdd35c02d9b0c3d389d29bb042e5dda6ffd2f5f0d896078274b3adb35",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQAmmoSampler.c": "8bb0ec1422887feaa340307d3c60bae50fc82d424fce6390876e580ff8b75e8b",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQBodyObserver.c": "f59421c1e0c83f0f480d7dd4d048b4b0a41193ed8fe8f2f627d2b6a696420ea1",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQCoverage.c": "8d9668858c47b7e9fee2b12d3ebd4e7cb88146b817cf615c4b0dade26c81b2ec",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQDeliveredCasualties.c": "1f738127e55e843ee2705007cedb5c08741f52f63c75eca7c80242177af82273",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQDoctrine.c": "6335728e89ed40ce11b811f00b61bfea76e94dd3379e4357cbfc438b05522bb0",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQJournal.c": "53563ff54fc4e0656713d6eaec5e88ddf69fd4bfa8ef6a67cfa13380d24031e1",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQLocalAwareness.c": "124260280ac8eda0e920bfcfc86932c9b21df6b1f7a6aa8acfc43feea3da149f",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQLocalHandoff.c": "2dd700dae9d9b232d22ca63ff01af75a3f5cc213ac24b7c0a43ffa38bc0b9ffa",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQMemory.c": "ec2047a477fb4273e22ae6bb68e7365f321f55c583b5d2c48c4abf2ac38e3b7d",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQMineSampler.c": "2a0fdc4d27e947a1d77b02ae23f757c7fa074eb456f817b7df0766583d757f55",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQMountedAmmoSampler.c": "88ea0fc0e13d7e3c22c7ce8b652816d1d137e4e6e37a72f48f0bdf515b936ae7",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQMountedDispatch.c": "cee3ae301ac2f211c290450b644a7942c9786a2a40d06f16e2a47efa96fd15b6",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQMountedIntercept.c": "a37edcf66e43945f331db47fe81cb2e0e767a7aaf8115244dcf9e6295932be98",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQNetwork.c": "0b73be993628a55e3b21c8670d540e39c938093dd5cb4d586e800ac530509b25",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQObservation.c": "57ad3f0b68d150791e30a7e4bd7dfedfb1ddd78a1c76f228e67b33ea9cb7144e",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQPursuit.c": "ab6ca0e1a7f36c104e664db06a74c80a528cbfd1de599af42e2194ef0a4f4ca3",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQReport.c": "12ea8ba08753d1e6d38b237087c1209cd2f9574b53c3ff0f27c082bed029c9ea",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQRoadIntercept.c": "0897e82d7805ef56f05f2b9c23903280285ea6bfa51796a2df86bb564ece78f7",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQStatusSampler.c": "b937eaed913a5095afa8e678dc1c36b5c805541bf8cd5be927069533d6baed1c",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQTask.c": "1147904bae6d72e9de47ce17bdada3dab489de4ed6e781dbf15bdbb30599ff6e",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HQWatch.c": "abe634cf6003ae920ec1ed18e305ed462920204960894520d3dd11f7e5ef1c33",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HelicopterAvailability.c": "60eaef2f6d4b2fd44861c5a4434ef97e732e40a5ff7401e2da451ed2dd9c2762",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HunterCombat.c": "df1c319d10efd07ed6f971cf0e41d8d7e377b04ea7f0fe143bf94df733fd1d9c",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HunterCrewRecovery.c": "e76af0fbf6f436a9c3c9d4c7b779bc08a78f6fe705c08bf6d9757bbeb65ee8eb",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HunterOpeningPlan.c": "0b6275221dab491f148426df05e132579f3acc20de5559226c3b38975618355c",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_HunterService.c": "79369d5cc30cf628f02df0023157ab423e40497325dfd6a73b218757f2b689d4",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoAccess.c": "ab4262f78d54782c5ecbf5fff4ebe3da16d72329658d7e18c0c35387dc8b3c7d",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoTransfer.c": "99fa26beb0c0869d0cd694500f3bfc0705c2c1cf674dea90d98fb93a59570ef7",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryCombat.c": "5684fcbee128a35107312452297f7ae2bec28aaa1b63f619fa649f36df8ea476",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryMineTransfer.c": "02c399413f80879c22b4891e8ec807c67a6235677095fc4b98bafdc360d6944c",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c": "b01fa948f204d49acbfbdfc5fa641b1d914e0eb91081e92a93816ae52ae88b1e",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantrySupplyPool.c": "c8e454573cf064ff392291d6feebf1f23be64390b5b8e944c03dd065f9f46b42",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarAimSolution.c": "59e8343d09f7a44871d8d3335d6ad1d02216abb5deed30d38b5ec9ba3f2c0649",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarBattery.c": "157024afc8fd3c1ffeea6ae923ff091e5773b9ffcf5f5864f8040d001e689110",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarCourierTransfer.c": "968e58ca700b4a11e5e04a5c159696f514a0b1bce531210172b913e495f7e2b7",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarFiring.c": "f2597d44c10d10de2462aa5e5450a22b8a5ad0eb99bd0cc09a8cf1ca2dd4a350",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarLogistics.c": "b3624e4a00a2bdef16f6c100bbd79910e3bb8c2ae8ec5fe2ad5aa70bffecd303",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarPrediction.c": "05863b2b4f9f70cdb288f91c722cbea163c13f2a2927dc485482e5bd4fa7d57f",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarReadiness.c": "4c3799b3f2681e977669de0cbfaeb307d9a682b04365bfc9f59079e762965758",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarRefresh.c": "52ae8d9d6cad92f42d68c634091b80a474d2666b6c06d63a8c30a3fab71494c4",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarReportLedger.c": "42a96040b63e56677353e55164ae23031c90f70b4d6673a9f412ad7b19e636ae",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSalvo.c": "c128850c7a78a4d8fee00ad38f48b265f1fbd1d9b24b092ddc5c205b0f0ad6da",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarStation.c": "cbbd7c86f722b664c85ab7c070ae1131d2ce5c41d1dacb4381bff9c1720a1866",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSupplyTransfer.c": "ad71084f507ad9c32d3055e7ec6844a1ec5ddf568c0216ab8391e902b56e417c",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSystem.c": "bc290ee8bed299d869598cbf41ec281653e0cc7f3c64c7214613df8a0fc83829",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MountedAmmoPickup.c": "5f7ca5b31f3b405c2a6ca32ff91042f5b4dac6ab9640ce67fb10d7a74236ba69",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MountedAmmoTransfer.c": "0b195784497672fdaf651f336c14f7be98c257f98c85cfbeb4f96fe1a401999b",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MountedMagazineSeed.c": "b42d0aac142907433df8bedc40de24c94813544016cf5f451846f1980250f995",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_MountedResupply.c": "c26ad43705765be1c20eca37fbe2978b8c647151f6620ed37141657a4b7dc312",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirAssaultProbe.c": "c1d55b338b157b758e6ffb993d5f689029b28b13929797c91e5dcb15b5e561ea",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirLogisticsProbe.c": "58fe863775d0ad575cb566c78cef696c9826691cf49ef9adde76376be7316db1",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirReconProbe.c": "c1216e0512a0268e4dbb82429e228334401c0c3cac52ba4486ae6dc91e41576d",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAircraftControlProbe.c": "0cf3e72ccdc42e6ef20fb71d743f0e037a9e69b2e082c720fa705628cf790205",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAircraftFieldProbe.c": "b64907c7566a894ca2f3c49ede5d972d4087a938da1a0ca87bcbd7c2203b2c52",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAircraftRouteProbe.c": "8d0dca97e5106d1c84b64992c789e1af0689514beefc027e713ca6ab901fc470",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarCourierProbe.c": "740c8bebbd4128a9311b1167d1058549475d6b46f81c9b6c0d19650f4b50616f",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarFiringProbe.c": "ee570d21bede8baebefc799399712d9582b3e30ebda7299f6c941777f02ad2a2",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarSalvoProbe.c": "fb9ccc6b36247ab3ad828ffbb2556abf5c2838d93ea6cd1ad259c0a015142f5e",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarStationProbe.c": "a110f0abc753cb1d2f781e457e637dd5346ecd2e924eb5eb3a5c7dca3d1e2340",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarTransferProbe.c": "399c21940ef10777b46fdb3e905430ce43404ce1de2f4a6bb62f9c61c1a0689c",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativePatrolHQProbe.c": "a58f57530e333976dc96fc5a0f9cb6cf0cb069c55788824950c5fb2f965d8e26",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeScoutProbe.c": "41b39b1abe5e51a5b8a428d533cccbfb0dda9d7a570228dc3489408c60543f17",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeTownProbe.c": "ade130f49fc9d868281cee7fde383f084f70ed8d4b876dacebbaed8538e84999",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ObjectiveDefence.c": "83ef91c2118521aedb4c1838b2e47909c80e0950086449b98ced168f1fd87080",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ReconAirports.c": "7551347d776d6e0eec818d6468cacbca7ac53daee7317e0a1618ca3d39ebc762",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ReconCrewLocks.c": "684bc5b9858c7ed90ed2ca6d52fc0e731a7e37a116db776090257b72a63621ab",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ReconFlightComponent.c": "4966dad504b3f8f28a9ffc8ac17cc548b00066fe05213c49c662ea56de34c9d4",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_ScoutSystem.c": "63287a252e4e7d5aefce840279f26ce3e1f286cb79cadb32596c37897cec7119",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_SettlementSafety.c": "e5c0ebc95521a9a33a3f7d9cca6c551dda862a08b7af20b017877aba9584795b",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoyColumn.c": "35678ec625fb0a3c0871e2c373fcff49816440a97a165ed25c8798dd72ef059f",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoyService.c": "5b1578afbf6da736453cc9d3872979eddd1649746aa32d3b0c7a9e3cab50057e",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoySystem.c": "f09aa817c27d6af0ccfb544f4ab1ae2afafb63d626641e03d87cfe159475d821",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoyTactics.c": "dc3acdffc8ca48f11b131f66d30d679ca68f3b3004344bdc78723bc9305915e0",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_SupportScenario.c": "a7b46253e1bb37cea7c29bb557fbf43ca207022d0f1cc927349441b2d1615279",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_TownGarrisons.c": "57f862476751087972fc78d0b27ab44e72361e27d32f15d55f9fe7fd7d6bd0e0",
|
||||
"source/addons/core/Scripts/Game/ERR/10_AI/ERR_VehicleAlarmPerception.c": "45ac71d25e10a057a26a5b0fc7128935baaf47f4c0f87208a4420fa52086fd98",
|
||||
"source/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelAdminProvider.c": "d63ab5c547021aeb61d398b8a773afeedee4662d3ce15d9fd9d0e9e37262f8b7",
|
||||
"source/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelDiscoveryFeedback.c": "62f2c408383f410782d9d41fa50acd6bd8cf66eeb80d2b79f91852b9d2cf8d97",
|
||||
"source/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelEvidence.c": "6bbf8d3b83e2c09fd9a23a9a5e5e11d7c29af2e618116bee613562fc45af2b33",
|
||||
"source/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelReroll.c": "d8b04de9ea789732cc78ebce9aa60786c86fe46d05f671cf251eefa68a214b59",
|
||||
"source/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelService.c": "2911325c79a7a372628b18ffa0e110d11919ce2c2cd7b19277bfd608fdb03dfc",
|
||||
"source/addons/core/Scripts/Game/ERR/20_Intel/ERR_MineIntel.c": "3ce16cebaa9703b2f9803df7c11614f94de6460a9136dab8f80dcad41ae2b1c2",
|
||||
"source/addons/core/Scripts/Game/ERR/30_Map/ERRM_NativeMapOwnershipProbe.c": "32418602f085e3edba7343f42a6a691630b533be262002f29248e8ae87a38254",
|
||||
"source/addons/core/Scripts/Game/ERR/30_Map/ERRM_SharedMapComponent.c": "3a10f6ea25bf88a400bc3e6c339823433845c5db4f2f423835ccf99a1b1a843f",
|
||||
"source/addons/core/Scripts/Game/ERR/30_Map/ERR_ScenarioMap.c": "75fa1d742129ef7f33c005cd48f56db7f49ee7bde3c5428532b0b501b032b0a3",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_AdminCommands.c": "282fe1463add7af8771aa58507b254e69d2d06f50274d4c77321db073f8394f0",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeAlarmHearingProbe.c": "5dbb6a48909b76cd141e3a79ef01d2e68cafee55153821c4471f85c761fff94f",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeConvoyCoverProbe.c": "d2450140cf9bdf09210473234605b4c0d818ea5b91f9532209166a35c5d13701",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeConvoyProbe.c": "4bdc920e87fa768b0ef0ed893c70ddbbcc9255d74163d7b657fd2ec7c4f14c32",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeHQBodyProbe.c": "811244cc8297817efbfc3ee4edf01c868eae23c88127ba0c72e98ee7422da72f",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeHQMemoryProbe.c": "d8fec6c138bb0f5bdbf99ee82ffc3ac9b44d1045d8833da63f8aa5f39beeb7e5",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeHQResponseProof.c": "0f8b09fd8753234c91fd6baaca0e2f812e409ae1c4be8f340b648ae59b69c2f3",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeInfantryTransferProbe.c": "9b2de4dc22bdadd51b0271219a971dc8dc07f70ed3534f306acf03ed81b29424",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeLocalHandoffProbe.c": "0d4d61c424a16008595f86fa61f3b848caf9bd6e9ebbacea9c10254d88ba378e",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMaintenanceProbe.c": "852b9b397efc3f919c97fec63bc3df1a850cd7833421af8441994afd191951d4",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMortarProbe.c": "ddb892141500c192c0787b011d57dd8c07dd8c9a3ca5fdc407f6c271897bde0a",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedAmmoProbe.c": "8d197f7a1398625e5a19db3284b0bf72c6ee6e032843a3e4d9a4e58de42b6825",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedCourierProbe.c": "12710e9e5548fe8856f7a52f3566338369a8a1eedf0bd92af16229271872ada5",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedInterceptProbe.c": "34b0b1e38a59f14c4e83d93ec412779945388e6f4d697bda2f6cb90f519a6372",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeMountedSwapProbe.c": "a6721fcaaccadf8eddb06687c7d587d0a3e377d5d1bb0b8e72e630fede8690ac",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeRadioProbe.c": "84524163c63402755b4f834f74dfe6d8e5c397dc26031f532593c6f79f5a93b1",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c": "254d1192138dd9864048693dd02d78b317e874cef57fc0b13226768e024d58be",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSupplyConvoyProbe.c": "701311de6a2c9fe8f0534a22056323c34072df26595dc70a7d4df45bc06e6c13",
|
||||
"source/addons/core/Scripts/Game/ERR/40_Chat/ERR_OrdinaryScenarioLaunchChat.c": "a747af09599ce4d0c52051f18f00c4624d24d137e328341b580b82e896c6bf65",
|
||||
"source/addons/core/Scripts/GameLib/ERR/00_Core/ERR_DiagnosticNoSplash.c": "0ea1b402f8927b6d68bf6f7e5caa2967f7e3a39147634faab147796b791933b5",
|
||||
"source/addons/core/Scripts/WorkbenchGame/ERR/00_Core/ERR_ValidateBaseWorldPlugin.c": "49a38c37b51e5318c7dcbcb01543dd9a6300d053f0d39808b3974f4edc45b871",
|
||||
"source/addons/core/Scripts/WorkbenchGame/ERR/40_Chat/ERR_ValidateWorldPlugin.c": "f567518b54f43b88747df2838cdfd6ebb34605c0919a3e7d271d28dd8b67a9b6",
|
||||
"source/addons/core/UI/layouts/ERR/AdminMenu.layout": "e8d570f7bf3b8c4067ad81d47bca7f35514b2f8c8748f5fa5f775fbe27debeac",
|
||||
"source/addons/core/UI/layouts/ERR/AdminMenu.layout.meta": "9deeece996f43b1f1fed6b5ec89279645c7b6424250200a42580cc088142e9bf",
|
||||
"source/addons/core/UI/layouts/ERR/AdminValue.layout": "cd811af6d2fb187f01c74e20ea07ad85669546b0ad70efae2ce52921ce26cbca",
|
||||
"source/addons/core/UI/layouts/ERR/AdminValue.layout.meta": "56b3d2335db400c1308e07c4a35d278b23ef32013dfd6dc82951866327428d08",
|
||||
"source/addons/core/UI/layouts/ERR/ContentRow.layout": "62d2c95814c99d906266fa96c6112e04a7fab1667e1a05e558d1d3974adc2d76",
|
||||
"source/addons/core/UI/layouts/ERR/ContentRow.layout.meta": "8c4bc13b41e7aee38e0ca640a97813ed1a6964a00e2cff9e1fe4ebd71fc2fdc6",
|
||||
"source/addons/core/UI/layouts/ERR/ItemRow.layout": "8ac6fbc7fe0ce0ffc3185516197303bb892a4415948f75ae06f3bc289fefcac6",
|
||||
"source/addons/core/UI/layouts/ERR/ItemRow.layout.meta": "33eaef9c403ea3a030e58ec17f78e46af457048243571ad5856fff04101fb60b",
|
||||
"source/addons/core/UI/layouts/ERR/PauseModsButton.layout": "d21d436291e2c1b262e33dc228b0d60a1d188dc9e85cfda6d2373f8281431b79",
|
||||
"source/addons/core/UI/layouts/ERR/PauseModsButton.layout.meta": "9ed6adabd8f53eb9a562d7186789876bba5c4202155ca894c1af866ca47354f3",
|
||||
"source/addons/core/UI/layouts/ERR/PreparationStatus.layout": "bd269cf8dc6f27735423743dd5b78242550518414448a0256e5e12fa6b92c459",
|
||||
"source/addons/core/UI/layouts/ERR/PreparationStatus.layout.meta": "75b12176a443bb911fc4ad446982d762201fda42ed38736b79bc5439fca31ccc",
|
||||
"source/addons/core/UI/layouts/ERRMap/ObjectiveMapElement.layout": "b364752c44896d67dad07e466a04f4504a50813fb36ee7c34c9189ea9677b4e9",
|
||||
"source/addons/core/UI/layouts/ERRMap/ObjectiveMapElement.layout.meta": "8691fe2eaf46568bca4a9f8128b247a8da810bb87a5546aa7ca3334e740270d6",
|
||||
"source/addons/core/UI/layouts/ERRMap/SharedMapRenderTarget.layout": "6e83a9c70282aff43b23a08b732739e7a241a31e8abf200498c90a745d3d60dd",
|
||||
"source/addons/core/UI/layouts/ERRMap/SharedMapRenderTarget.layout.meta": "5c846445cc089e2e08899ba703059d4adb805ff30ab5a16409a3cd59718cbd54",
|
||||
"source/addons/core/Worlds/ERR_Everon.ent": "22324bc7eb0d80dec8a1f3bd61a9df9201b72f749f4e751766b0c9d0b7d46b87",
|
||||
"source/addons/core/Worlds/ERR_Everon.ent.meta": "19d1903ca72baa326b4724a6791d0da1104a1e53f3f31dc1ca41a856efd68e83",
|
||||
"source/addons/core/Worlds/ERR_Everon_Layers/default.layer": "6bcb7fbb27b6282719dae8a37486e518d4cbaea385f2ea9af1918b36bb28b175",
|
||||
"source/addons/core/addon.gproj": "73e973a1f1c5910393e16f86a3a40d792031bb2fa3fc7f4dd87a06a16c3e34a4",
|
||||
"source.zip": "576d7c7c4c65f2f5a181afe5f4262d2ece6ef03b90fd1b62a8339aee301c9d9f"
|
||||
}
|
||||
@@ -0,0 +1,535 @@
|
||||
{
|
||||
"CONTRIBUTING.md": "bdf661d603de4bfbade978052d93e5a1db6ebdb99c5b1f9b1a575935eccb3eba",
|
||||
"README.md": "4a4e2e57cfcdb7fa560b9204b73a4864bbc3b3bace7cf3f022f470fcb705dd57",
|
||||
"escapists-ai/Prefabs/Logistics/EAI_DepotStock.et": "87f76285abe1d14206fd2eff904cb6e0d4375083d46a007244c1b13a5821af74",
|
||||
"escapists-ai/Prefabs/Logistics/EAI_DepotStock.et.meta": "c51cca4cefb69e5fef27dbe05e32fb6edd29cc423db6e76aeb19c0c9d2fc999f",
|
||||
"escapists-ai/Prefabs/StartAreas/EAI_ImprovisedPrison.et": "0204b836cda9729ae219747cb994d438cfddf41fa625377b5c89c49d50b27686",
|
||||
"escapists-ai/Prefabs/StartAreas/EAI_ImprovisedPrison.et.meta": "58b6929ecc44886111c928981ac1442c05941d8838cd6295bb46b17662ade8a6",
|
||||
"escapists-ai/Prefabs/StartAreas/EAI_PrisonBackpack.et": "21ec7e0ea4b7b0493d899e0fec525fbc7d302a2473aedafbd4efcab3599022a1",
|
||||
"escapists-ai/Prefabs/StartAreas/EAI_PrisonBackpack.et.meta": "2accace9ab6effa571e93ce841fa379139268ba09f25fb62448129c220a3084b",
|
||||
"escapists-ai/Prefabs/StartAreas/EAI_PrisonGate.et": "b958e2250e047c95bce5176b9c291dd3ad430d7734891e65a2d9bbdf0f924dc2",
|
||||
"escapists-ai/Prefabs/StartAreas/EAI_PrisonGate.et.meta": "cd3cd4a36f11eb443b8f711b98d7470bb71b3bbd9f4f9a5715bcb96e2cafdaa0",
|
||||
"escapists-ai/Prefabs/StartAreas/EAI_PrisonWall.et": "d3009ecd7c3b977ae34a523c1926c13c9e9cc9ff8e531f83e861467a26ff3e98",
|
||||
"escapists-ai/Prefabs/StartAreas/EAI_PrisonWall.et.meta": "e686e8001f68d15c3e8dec35c7e46a44122414fb7ba1d81d443d85186e32192e",
|
||||
"escapists-ai/Prefabs/Vehicles/Helicopters/EAI_AmmoMi8.et": "77a0bba1123c8313619db85358bb575fc9bd5cd4be9b6cb545c2ec82cd54dc16",
|
||||
"escapists-ai/Prefabs/Vehicles/Helicopters/EAI_AmmoMi8.et.meta": "e1a7ebd382bf60ee22bd6405f795e6d81aced7b6f62de9b0ce216f012fcfee1a",
|
||||
"escapists-ai/Prefabs/Vehicles/Helicopters/EAI_ReconMi8.et": "a37e137b48c8ca08891eb173e46181ee9fe840dd505ee42450cb901ba19431be",
|
||||
"escapists-ai/Prefabs/Vehicles/Helicopters/EAI_ReconMi8.et.meta": "1e3f4ec9b3e6ac1e0717a14f497c015b3ad6b53694ad6588208f4cb007e6f72d",
|
||||
"escapists-ai/Prefabs/Vehicles/Parachutes/EAI_AssaultParachute.et": "e7bded543194e9de132c0b9972948141da1fcfa56c7b663cc333c9caa2e73e85",
|
||||
"escapists-ai/Prefabs/Vehicles/Parachutes/EAI_AssaultParachute.et.meta": "7123819a9c0912a7e286343c96ed07bc9ef9010395e38b627048080ba2be1adb",
|
||||
"escapists-ai/Prefabs/Weapons/Attachments/Optics/1p78/Optic_1P78.et": "95bda46853d6b8653060e4ea9fcc91bbe4efd7aa69fa039c8c42ad0a5b60873d",
|
||||
"escapists-ai/Prefabs/Weapons/Attachments/Optics/1p78/Optic_1P78.et.meta": "88e2f5660d0485258464fc847bd4f976238dee802e5d7db09c0a562de8296b0c",
|
||||
"escapists-ai/Prefabs/Weapons/Attachments/Optics/Optic_PSO1/Optic_PSO1M2.et": "cdc52ec5931731474cec99acc391446bce6b1b230ddf7e91ea2348f84dc58acf",
|
||||
"escapists-ai/Prefabs/Weapons/Attachments/Optics/Optic_PSO1/Optic_PSO1M2.et.meta": "5e68c998c7d36d8aa0474fe4a718aa6225d53d17ee584c94f7755ed915065603",
|
||||
"escapists-ai/Prefabs/Weapons/Attachments/Optics/Optic_SPP/Optic_SPP.et": "06e593c1677954e0f7a05b0b040ccca8f7a987961f8bfbe90e0582a07b151953",
|
||||
"escapists-ai/Prefabs/Weapons/Attachments/Optics/Optic_SPP/Optic_SPP.et.meta": "390d06cda3bbd58095e9fc84cec957db357aae22e1f689cbf78ed7b398082552",
|
||||
"escapists-ai/Prefabs/Weapons/Core/WeaponSight_Base.et": "0183016add1789e87f07783211168680de5caa9ecbf803d61b52e3d762013593",
|
||||
"escapists-ai/Prefabs/Weapons/Core/WeaponSight_Base.et.meta": "23301df84b1ebc22a1f789b04b00faae6a48b2d9d6888e26038bfbce019f9e74",
|
||||
"escapists-ai/README.md": "2a12575092e55d79cdda0d7ff40dcc33b01bb558dfd1b6aa2fc8813bfc4dbd65",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_AIConfig.c": "8c320d3163d443b43e50547734702484c8ad51f2cffe88cf6dfd33aaf339ec01",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_AIResponseSystem.c": "b3e1263e986837744a70fbaedaa6e57afae7f2981a21211d3a2066e2c63ac84d",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_AirAssault.c": "a9c0c2bf59fb4f9b351913708cee54a302a9e447d30c2766faa91c7573af1b6d",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_AirRecon.c": "7e72c9eac0fce21865f09a923cbfd638c25939c8492b3e1e5dfdda1f1394f51e",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_AirSupportPolicy.c": "51605d83624073a30f672881d46c652bd03a7e040ccc4d812c9e8d0c456be87f",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_AircraftAmmo.c": "52bed2b0008762f221bed4f139cfe0a34e69e0ee455ef3dc47276d3dc3373c45",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_AmmoSupply.c": "97587483227699b78e78f1223f46ebf286d458ffcf06b79f458807b6e95f969e",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_AssaultParachute.c": "b2d2be240d184c436a5b2fd1a03d446763a1c27b6b5c825a988b05feaec7a346",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_ConvoySettings.c": "6ceb44226c2608ef09bb246af1238679030c04a6dab5351e97e3dfe955b446c7",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_DependencyGuards.c": "094744d77c5c99f7a46e6b3a0aba071f34b4b34cb467eea30264d5f63151a7d9",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_DepotLoading.c": "5b608f36621c9d744bdc55829b1000af70ba9d8853b8a90828d774557a204375",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_DisableAmbientEvents.c": "8e9d6b5abb4aaa3e83654abf5aeda429093b3bd6cb03f7f9b3953dc028d4023f",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_FactionRelations.c": "1595926655f3597cbe3c648cd52a0372bc24346eefd99802a3dafe853f935651",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_GroupLookup.c": "0cf7ed906afca4ac5f31175b0daef394056b05f89cf00baa0d2de0d0986f388b",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_GroupTactics.c": "226eb3981765284afa0cead84411244806a84440003fe4af69f2208028cef23d",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_HQ.c": "4898ac471fb16433fc5d98244a8cec89c5e8e006af2c94bbcd89113a2b7107c8",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_HQBodySearch.c": "c46e318d4331bedefbefad19f735dc45752ed21d0a2c232880673c1cbe2c686c",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_HQJournal.c": "0d714bc60940898dac560ee0902997ca82e324395dc2696c6424909a0a587c81",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_HQNetwork.c": "1a7e279b050514bad86f18fdd233b7eb5728e99bab3daae3aedb31ceb571c271",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_HQObservation.c": "735611603dbfa80218a42c6722dda09a3de8c7369aa5689cb8cb711851ede6dd",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_HQRoadblocks.c": "128776f0b448162ee36cfc71b2a38d2cd06d6d6e4679253f215896aa3fcabb98",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_HQSettings.c": "82f2a9b7f2a60d499ce4155c3584ccf42121ebf16b944392bc5a7fe1bef25df7",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_HQStatus.c": "7127dcf23be7bcbb9415d8ef6c8f1da5bec551fbf16fc1054487dcd7a877d885",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_HQWatch.c": "7807aa97c4625a82841b6992416a9d0c8836f987767a99264934c1f79320f64a",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_HelicopterAvailability.c": "bb565c5c5f7d4e671a295ae7e951f9ebdde626ffdecc4ae7d92e0e776e1730e0",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_HelicopterRecovery.c": "3ab340e7790ca0536b97a809daf00a155cc972b557297a03532fe622ac0db87c",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_ImprovisedPrisons.c": "e1b7dd3b7b45bc803e61e2031030d873101947def8b6a41fe450555e90d000b9",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_Landing.c": "7d335cd93e9141b779c90fd0e4962af290e2b6c0ec4c6e9501ded3e2fd165f09",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_LogisticsVehicle.c": "8e109e6f010f1af1a4d8ec9ad01d0f683dad014c76c9a763b091bba8a320de9b",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_MineTask.c": "d5a06b646b0d789832badacb75e7a10a5097c4a4ac32dffd72aca3390b5d9e60",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_Mines.c": "108cbe8175e339db88f2c0f36ef3c22d29805cf7794b63cb4edc171e29f92ef3",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_MortarEngagement.c": "853bea893bd39d90621a7e391e98931d7518ec07b61da921204dfd9e50c82f27",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_MortarFiring.c": "aadd057a1f3f4326bd41500be7a12051a16de9d5925fca2452a46cdfbf0d6d12",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_MortarPrediction.c": "b58d9ea6e211fc479a1674c380be4979ebacf46d14facae74257aa0937b6cd49",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_MortarSalvo.c": "f0235c4516eebd03e5721d259dabcb516a4e457e9909a1b8bb08553a0f7bc652",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_MortarSystem.c": "b355227b2b221147d35e1dacbc07cf650838229b9a6d22cd30cc1e304112b33f",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_NativeRadioCall.c": "ed9ad2a8137395e25363f94e81d4854e159136a53a67e2be4b89fdcb08d712d6",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_Performance.c": "f9ea5747e4ca16d88dfe56d796268d7d3cf01efe037e37ba7798835f2b17813d",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_ResponseSafety.c": "b3dcbe8f3dd840791e91e9ec202cd392ebc4895714816cdcedcdc591baa62b05",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_Resupply.c": "dfa28d0741c5515c85a6e62bc6d1a104f5474ddc22a6e58931be1583133f3586",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_RuntimeGuards.c": "d843e7807501eb94f31a4c7628e8357e2404c2e598c5c3c697b091b1ab266edb",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_SettlementSafety.c": "6961ad593d20f86c30b557542b4f67fd44d9579037776b07cd95616927eda83d",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_SniperOptics.c": "96a302da44fdb9207c12cc1c9c93aad38eb510cb0cf9befd800f60a2945b08e8",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_StartSelection.c": "5dae5de5efe59cf2b40a289becafb6ef1aed00271cc561769cdb1f570174ee7b",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_StartingOutfit.c": "54308138b73e23b5dcc47b5111d55f843a6d7bb7f39fe8466571e54a73246db6",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_StingerEquipment.c": "b8ce09f2d3ed61e58beadc1f158daed6eceb17b08243f7979b46d8c27e917695",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/EAI_SupplyConvoys.c": "a896fdacfd9c0f2db52e588642623545a3a5d6e8041fb72000a68e720fc2b7a5",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/Simulation/EAI_Simulation.c": "4688fd4eccb490ae416707400ae889aae6bf3794402d5e68da0d03efddf01ab1",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/Simulation/EAI_SimulationBot.c": "9d9e809a6f39623bda49749304bbffb89c19b9e83e4f30f1ac2a9780d4526397",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/Simulation/EAI_SimulationIntel.c": "d53fcb1933bc563aa0d72bc4093bfec68da69241abe6639f5e030422457d1cf1",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/Simulation/EAI_SimulationLifecycle.c": "c375a4ad7c7af621f89c16150f42262ff6501fb92e2a96ab85f28f879cb0ac39",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/Simulation/EAI_SimulationMedical.c": "a9da70fdecd20d8fd9e23f45fcb2b070916b76f0ee0418f72f18805f2d2149f0",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/Simulation/EAI_SimulationPrison.c": "f9098c2f312e202130b3789eb2b67ca38ed3c44a859be24543816a028a552644",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/Simulation/EAI_SimulationSpectators.c": "0e3b911914cf06e31c836323cba170782ef994338d75cd8202b5ab7c4e9285f4",
|
||||
"escapists-ai/Scripts/Game/EscapistsAI/Simulation/README.md": "c2d906809974228b16871f11a396a38ef71b4f72beabcc8add7aaae89409d539",
|
||||
"escapists-ai/TESTING.md": "59149450f8abadfed968525a28888bf2053e2f5ad974422a46bf8019902d9d25",
|
||||
"escapists-ai/addon.gproj": "c61e9df6e62d3c6f9aa7aec797981c9e4b20f45dac1fabf87b77d6f10346818f",
|
||||
"escapists-ai/diagnostics/2026-09-11-server-performance.md": "a6e2fa75ab529d1a2e23eab80958f991e8d77d4c4814eea436def95f60607bd4",
|
||||
"escapists-ai/diagnostics/2026-09-12-captured-uaz-defeat.md": "10a3b15214126e540ad44dd923240fabf8e04896f413c0caff0e45e631c38912",
|
||||
"escapists-ai/diagnostics/2026-09-12-hq-nato-reporting.md": "3ae76c1ae837812f8637f7cb8c0a9456bef07332a8d795a0fc949e8706bf8fa8",
|
||||
"escapists-ai/diagnostics/2026-09-13-hellsos-session-audit.md": "7fbae760c1495dd9199e43fcf490ec4d8e44be2c370f98ffa11c16b104203865",
|
||||
"escapists-ai/diagnostics/2026-09-13-session-fixes.md": "0bd9d29286e66b04cdd6d4942782ff5e4c8fd4370e428c7ce8157c0d5baa8c23",
|
||||
"escapists-ai/tests/ai_chat_config_regression.py": "b4b0dc6a74a4a5beda787fb676a378316bfb9c9589bd6365ded0ae3da44d91df",
|
||||
"escapists-ai/tests/ai_config_regression.py": "7dec0063274ec84a861f11b4df15b75c68dc88fa132f1ce9762063ef05bdd504",
|
||||
"escapists-ai/tests/air_assault_regression.py": "f27ea28bf4c6e52ecaf9ce45fa3bfab1bce7b6e07cd8eac377f465a7d4d6bad2",
|
||||
"escapists-ai/tests/air_support_regression.py": "b0c0cbf9d2918b03b37297575cbd678a633296939cf6c64095769fac4ddb7074",
|
||||
"escapists-ai/tests/airport_reload_regression.py": "9ef8ab9ab33d02899636859ae3c65919726b92c0c7a9604af704bac2c1a78b85",
|
||||
"escapists-ai/tests/convoy_stop_regression.py": "245dd69dcd300a49fe743875280321165d1da15c0cdbe23188631eec3e418c54",
|
||||
"escapists-ai/tests/depot_loading_regression.py": "2e80b3ce86b0607a5b62cdd49d7e898c17c23fd5e67597a5e8789bc71076ba41",
|
||||
"escapists-ai/tests/faction_alignment_regression.py": "37666426aae9f303f255861f89cf4cacefb38a6994fc2dd6fced11f53e1b7c7f",
|
||||
"escapists-ai/tests/helicopter_availability_regression.py": "b8f92feaf7f8057082a9c7c20cc889da3b614d74d19e206491ccecceec7e92e0",
|
||||
"escapists-ai/tests/helicopter_recovery_regression.py": "38e693a1c9f204dbab1a4ab800fa219d6aa3b7c378957434ab312a2f84832d25",
|
||||
"escapists-ai/tests/hq_body_search_regression.py": "975abef7f7ef378b150e2c46266574a786588a2fa0ff6ee43e708d58227222c8",
|
||||
"escapists-ai/tests/hq_journal_regression.py": "426a04d4117c2e9c3d4ce5aef112cb628cb0cd6511b727d05e554b6a29ae1c8e",
|
||||
"escapists-ai/tests/hq_menu_checks.py": "6f14906d08ddd67e909eae5ef37ca8395476fc84920fed77ca276012a58dd88b",
|
||||
"escapists-ai/tests/hq_network_regression.py": "a09b5cbf3453e6af31d1d888b5489586efbddbdb89b6e2b2d6eed52ce67e1098",
|
||||
"escapists-ai/tests/hq_observation_regression.py": "76b715d46f44d560896c502d01ed89ce16b6366596b607cef111db886cb6dcf6",
|
||||
"escapists-ai/tests/hq_regression.py": "4b9a0b66851f27700584e548c82cda8de7f9fda72868566e4bac227500951172",
|
||||
"escapists-ai/tests/hq_settings_regression.py": "1e68b985cf7d0446894eeecfa16335d4581e78c386a2ed81454e62512f6c76d6",
|
||||
"escapists-ai/tests/hq_watch_regression.py": "87e9bb484e2a37bfda9a4827d1fa4cd50b0c38bde07659df171c7e9c800a2150",
|
||||
"escapists-ai/tests/mine_task_regression.py": "5eca78bfa4fdc11f6f9107e83b06676f6f20cc4fb75b940768a25ffaaa6f812b",
|
||||
"escapists-ai/tests/mortar_deployment_regression.py": "8fdb4994d05a56409f46f074c2f41298143628d19c5644093e21eaf423eee31d",
|
||||
"escapists-ai/tests/mortar_engagement_regression.py": "a39ecc1132b51e13d80f4136a1d219fb5fc08d193b9e6c0be48dd9378e1e762a",
|
||||
"escapists-ai/tests/mortar_footprint_regression.py": "56ec6d478c036d1c7b1f65fde9170f73af77c8ed8175dc443cb079344c7a2c92",
|
||||
"escapists-ai/tests/mortar_logging_regression.py": "49d2c83c6f18ae8ffed152c5cc8480079a85731ec94fbd1f014362ec7d93f174",
|
||||
"escapists-ai/tests/mortar_operator_regression.py": "80f2a2d5e1bc8c38345b76f5e83cb3bc527fac7ad41111b3dee9327e60bbcaf5",
|
||||
"escapists-ai/tests/mortar_regression.py": "f4ed7027857056e158291d7a0c64072d435494c3d1dc71df4e6eee0c4a7e5c16",
|
||||
"escapists-ai/tests/mortar_salvo_regression.py": "bba2d57c4f5ccb76819ce90a63bc157e29fd033a3430318689c84c5e4c5f6f29",
|
||||
"escapists-ai/tests/mortar_settlement_regression.py": "6672605e495c1e7a3abd1dc1311f5449397d09152d17fd41a2d1cb78ff395492",
|
||||
"escapists-ai/tests/prison_airfield_regression.py": "30f48b626ddccfbd0a8ca6295f00000cc89554c9491ecbb177032a48a746d15f",
|
||||
"escapists-ai/tests/response_capture_regression.py": "b6d309fe82dc538d6c6bb48e943f72fb9fb012b4e140acd36f9095ab12cb1878",
|
||||
"escapists-ai/tests/resupply_regression.py": "72828f53e6f77db41558cbece31da6ace6eeefc0674648dd16eaec659b46daab",
|
||||
"escapists-ai/tests/roadblock_deployment_regression.py": "b696ec1c5fabdade9b8c4deb831d33db118f30b63e66229d8fd885d62b49c9bd",
|
||||
"escapists-ai/tests/roadblock_regression.py": "e0725fe89b07e8b5371102800088d7be38158bf5248b155250595efb20cd8598",
|
||||
"escapists-ai/tests/runtime_resources_regression.py": "d8c0c602c60e5fea1ef35364be6163547b77d670b0d24ec5fcd76a97e1769c8d",
|
||||
"escapists-ai/tests/scope_detection_regression.py": "6865b52d1cbfe44d1b1b7a40555f202298056ecd2f3a93a09b6d36f6d28b3765",
|
||||
"escapists-ai/tests/scope_prefabs_regression.py": "8959c7d1d494d1808e660411ce4c2afb538e17af3220a57fa1f14fdf2f03f506",
|
||||
"escapists-ai/tests/session_fixes_regression.py": "b78419295f7b080de7068823a33ef81bef7ecfa49d739c77c9f56f99df098999",
|
||||
"escapists-ai/tests/simulation_chat_regression.py": "28f906f687a98eb1800a9f28ba7f7a550a0e40e6d4746eb134cca0094c5fd94c",
|
||||
"escapists-ai/tests/simulation_intel_bridge_regression.py": "f8ec1c424ff90838b7d34616a98ed1cd80e082c68de81c6743940a5a37785bf3",
|
||||
"escapists-ai/tests/simulation_prison_regression.py": "a901b2eb4b462d4794157e67b0818b88b2176f0beb2dfb38fd71685f86909080",
|
||||
"escapists-ai/tests/simulation_regression.py": "0e01653cfcae35530f68cd1bf5d5636e71b05e1dd396ba2194cda649c5a39237",
|
||||
"escapists-ai/tests/simulation_spectator_regression.py": "0fd3b920f691880be1d8c197bbec399d90361ef28586ba67ad4d5c7c93b7f2b5",
|
||||
"escapists-ai/tests/sniper_optics_regression.py": "5dedc2bb50455877f23209756251120a6eae83543fd5ccb5dabe0afc6739d47f",
|
||||
"escapists-ai/tests/sniper_weapon_lookup_regression.py": "fa077b2b6abb45a11216979b49c871e832a3a1573d8d823198e439475455b528",
|
||||
"escapists-ai/tests/spawn_selection_regression.py": "c9001edc39258e1f4419ae62f53ee4b0fa6535718810600d2afc14f73bc5ceae",
|
||||
"escapists-ai/tests/stinger_equipment_regression.py": "eaa3b92e1c9339c17beb589a7fa61a2cbdec06fce65c7e91bba456cdf27f9a47",
|
||||
"escapists-ai-norhs/NORHS.md": "a5c78b6eb975a6353140ad2542a2a54c44a7ff669224c95fa021cfe5ab925298",
|
||||
"escapists-ai-norhs/Prefabs/Logistics/EAI_DepotStock.et": "87f76285abe1d14206fd2eff904cb6e0d4375083d46a007244c1b13a5821af74",
|
||||
"escapists-ai-norhs/Prefabs/Logistics/EAI_DepotStock.et.meta": "c51cca4cefb69e5fef27dbe05e32fb6edd29cc423db6e76aeb19c0c9d2fc999f",
|
||||
"escapists-ai-norhs/Prefabs/StartAreas/EAI_ImprovisedPrison.et": "0204b836cda9729ae219747cb994d438cfddf41fa625377b5c89c49d50b27686",
|
||||
"escapists-ai-norhs/Prefabs/StartAreas/EAI_ImprovisedPrison.et.meta": "58b6929ecc44886111c928981ac1442c05941d8838cd6295bb46b17662ade8a6",
|
||||
"escapists-ai-norhs/Prefabs/StartAreas/EAI_PrisonBackpack.et": "21ec7e0ea4b7b0493d899e0fec525fbc7d302a2473aedafbd4efcab3599022a1",
|
||||
"escapists-ai-norhs/Prefabs/StartAreas/EAI_PrisonBackpack.et.meta": "2accace9ab6effa571e93ce841fa379139268ba09f25fb62448129c220a3084b",
|
||||
"escapists-ai-norhs/Prefabs/StartAreas/EAI_PrisonGate.et": "b958e2250e047c95bce5176b9c291dd3ad430d7734891e65a2d9bbdf0f924dc2",
|
||||
"escapists-ai-norhs/Prefabs/StartAreas/EAI_PrisonGate.et.meta": "cd3cd4a36f11eb443b8f711b98d7470bb71b3bbd9f4f9a5715bcb96e2cafdaa0",
|
||||
"escapists-ai-norhs/Prefabs/StartAreas/EAI_PrisonWall.et": "d3009ecd7c3b977ae34a523c1926c13c9e9cc9ff8e531f83e861467a26ff3e98",
|
||||
"escapists-ai-norhs/Prefabs/StartAreas/EAI_PrisonWall.et.meta": "e686e8001f68d15c3e8dec35c7e46a44122414fb7ba1d81d443d85186e32192e",
|
||||
"escapists-ai-norhs/Prefabs/Vehicles/Helicopters/EAI_AmmoMi8.et": "77a0bba1123c8313619db85358bb575fc9bd5cd4be9b6cb545c2ec82cd54dc16",
|
||||
"escapists-ai-norhs/Prefabs/Vehicles/Helicopters/EAI_AmmoMi8.et.meta": "e1a7ebd382bf60ee22bd6405f795e6d81aced7b6f62de9b0ce216f012fcfee1a",
|
||||
"escapists-ai-norhs/Prefabs/Vehicles/Helicopters/EAI_ReconMi8.et": "a37e137b48c8ca08891eb173e46181ee9fe840dd505ee42450cb901ba19431be",
|
||||
"escapists-ai-norhs/Prefabs/Vehicles/Helicopters/EAI_ReconMi8.et.meta": "1e3f4ec9b3e6ac1e0717a14f497c015b3ad6b53694ad6588208f4cb007e6f72d",
|
||||
"escapists-ai-norhs/Prefabs/Vehicles/Parachutes/EAI_AssaultParachute.et": "e7bded543194e9de132c0b9972948141da1fcfa56c7b663cc333c9caa2e73e85",
|
||||
"escapists-ai-norhs/Prefabs/Vehicles/Parachutes/EAI_AssaultParachute.et.meta": "7123819a9c0912a7e286343c96ed07bc9ef9010395e38b627048080ba2be1adb",
|
||||
"escapists-ai-norhs/Prefabs/Weapons/Attachments/Optics/Optic_SPP/Optic_SPP.et": "06e593c1677954e0f7a05b0b040ccca8f7a987961f8bfbe90e0582a07b151953",
|
||||
"escapists-ai-norhs/Prefabs/Weapons/Attachments/Optics/Optic_SPP/Optic_SPP.et.meta": "390d06cda3bbd58095e9fc84cec957db357aae22e1f689cbf78ed7b398082552",
|
||||
"escapists-ai-norhs/Prefabs/Weapons/Core/WeaponSight_Base.et": "0183016add1789e87f07783211168680de5caa9ecbf803d61b52e3d762013593",
|
||||
"escapists-ai-norhs/Prefabs/Weapons/Core/WeaponSight_Base.et.meta": "23301df84b1ebc22a1f789b04b00faae6a48b2d9d6888e26038bfbce019f9e74",
|
||||
"escapists-ai-norhs/README.md": "2f8f2bbef53f3fe101f9d47c8137097d4c61545e15dce1748bb81f42a2c4d5b0",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_AIConfig.c": "f4d11962dd88b437b7f6bcd31d9b295cfd0ec9cdfb1daa443a3bce505e860eff",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_AIResponseSystem.c": "b3e1263e986837744a70fbaedaa6e57afae7f2981a21211d3a2066e2c63ac84d",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_AirAssault.c": "a9c0c2bf59fb4f9b351913708cee54a302a9e447d30c2766faa91c7573af1b6d",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_AirRecon.c": "7e72c9eac0fce21865f09a923cbfd638c25939c8492b3e1e5dfdda1f1394f51e",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_AirSupportPolicy.c": "51605d83624073a30f672881d46c652bd03a7e040ccc4d812c9e8d0c456be87f",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_AircraftAmmo.c": "52bed2b0008762f221bed4f139cfe0a34e69e0ee455ef3dc47276d3dc3373c45",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_AmmoSupply.c": "97587483227699b78e78f1223f46ebf286d458ffcf06b79f458807b6e95f969e",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_AssaultParachute.c": "b2d2be240d184c436a5b2fd1a03d446763a1c27b6b5c825a988b05feaec7a346",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_ConvoySettings.c": "6ceb44226c2608ef09bb246af1238679030c04a6dab5351e97e3dfe955b446c7",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_DependencyGuards.c": "094744d77c5c99f7a46e6b3a0aba071f34b4b34cb467eea30264d5f63151a7d9",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_DepotLoading.c": "5b608f36621c9d744bdc55829b1000af70ba9d8853b8a90828d774557a204375",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_DisableAmbientEvents.c": "8e9d6b5abb4aaa3e83654abf5aeda429093b3bd6cb03f7f9b3953dc028d4023f",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_FactionRelations.c": "1595926655f3597cbe3c648cd52a0372bc24346eefd99802a3dafe853f935651",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_GroupLookup.c": "0cf7ed906afca4ac5f31175b0daef394056b05f89cf00baa0d2de0d0986f388b",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_GroupTactics.c": "226eb3981765284afa0cead84411244806a84440003fe4af69f2208028cef23d",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_HQ.c": "4898ac471fb16433fc5d98244a8cec89c5e8e006af2c94bbcd89113a2b7107c8",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_HQBodySearch.c": "c46e318d4331bedefbefad19f735dc45752ed21d0a2c232880673c1cbe2c686c",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_HQJournal.c": "0d714bc60940898dac560ee0902997ca82e324395dc2696c6424909a0a587c81",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_HQNetwork.c": "1a7e279b050514bad86f18fdd233b7eb5728e99bab3daae3aedb31ceb571c271",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_HQObservation.c": "735611603dbfa80218a42c6722dda09a3de8c7369aa5689cb8cb711851ede6dd",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_HQRoadblocks.c": "128776f0b448162ee36cfc71b2a38d2cd06d6d6e4679253f215896aa3fcabb98",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_HQSettings.c": "82f2a9b7f2a60d499ce4155c3584ccf42121ebf16b944392bc5a7fe1bef25df7",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_HQStatus.c": "7127dcf23be7bcbb9415d8ef6c8f1da5bec551fbf16fc1054487dcd7a877d885",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_HQWatch.c": "7807aa97c4625a82841b6992416a9d0c8836f987767a99264934c1f79320f64a",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_HelicopterAvailability.c": "bb565c5c5f7d4e671a295ae7e951f9ebdde626ffdecc4ae7d92e0e776e1730e0",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_HelicopterRecovery.c": "3ab340e7790ca0536b97a809daf00a155cc972b557297a03532fe622ac0db87c",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_ImprovisedPrisons.c": "e1b7dd3b7b45bc803e61e2031030d873101947def8b6a41fe450555e90d000b9",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_Landing.c": "7d335cd93e9141b779c90fd0e4962af290e2b6c0ec4c6e9501ded3e2fd165f09",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_LogisticsVehicle.c": "8e109e6f010f1af1a4d8ec9ad01d0f683dad014c76c9a763b091bba8a320de9b",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_MineTask.c": "d5a06b646b0d789832badacb75e7a10a5097c4a4ac32dffd72aca3390b5d9e60",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_Mines.c": "108cbe8175e339db88f2c0f36ef3c22d29805cf7794b63cb4edc171e29f92ef3",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_MortarEngagement.c": "853bea893bd39d90621a7e391e98931d7518ec07b61da921204dfd9e50c82f27",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_MortarFiring.c": "aadd057a1f3f4326bd41500be7a12051a16de9d5925fca2452a46cdfbf0d6d12",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_MortarPrediction.c": "b58d9ea6e211fc479a1674c380be4979ebacf46d14facae74257aa0937b6cd49",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_MortarSalvo.c": "f0235c4516eebd03e5721d259dabcb516a4e457e9909a1b8bb08553a0f7bc652",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_MortarSystem.c": "b355227b2b221147d35e1dacbc07cf650838229b9a6d22cd30cc1e304112b33f",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_NativeRadioCall.c": "ed9ad2a8137395e25363f94e81d4854e159136a53a67e2be4b89fdcb08d712d6",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_Performance.c": "f9ea5747e4ca16d88dfe56d796268d7d3cf01efe037e37ba7798835f2b17813d",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_ResponseSafety.c": "b3dcbe8f3dd840791e91e9ec202cd392ebc4895714816cdcedcdc591baa62b05",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_Resupply.c": "dfa28d0741c5515c85a6e62bc6d1a104f5474ddc22a6e58931be1583133f3586",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_RuntimeGuards.c": "d843e7807501eb94f31a4c7628e8357e2404c2e598c5c3c697b091b1ab266edb",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_SettlementSafety.c": "6961ad593d20f86c30b557542b4f67fd44d9579037776b07cd95616927eda83d",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_SniperOptics.c": "60518f87e917e5d1f381b2e1116fdbc64339b81b141a0c83c0eddf189d5dd3e3",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_StartSelection.c": "5dae5de5efe59cf2b40a289becafb6ef1aed00271cc561769cdb1f570174ee7b",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_StartingOutfit.c": "a8dedb2e405537e33c3bbc338a4c5fad01c7de9034cc8e02386d48e0732350b7",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_StingerEquipment.c": "b8ce09f2d3ed61e58beadc1f158daed6eceb17b08243f7979b46d8c27e917695",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/EAI_SupplyConvoys.c": "a896fdacfd9c0f2db52e588642623545a3a5d6e8041fb72000a68e720fc2b7a5",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/Simulation/EAI_Simulation.c": "4688fd4eccb490ae416707400ae889aae6bf3794402d5e68da0d03efddf01ab1",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/Simulation/EAI_SimulationBot.c": "9d9e809a6f39623bda49749304bbffb89c19b9e83e4f30f1ac2a9780d4526397",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/Simulation/EAI_SimulationIntel.c": "d53fcb1933bc563aa0d72bc4093bfec68da69241abe6639f5e030422457d1cf1",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/Simulation/EAI_SimulationLifecycle.c": "c375a4ad7c7af621f89c16150f42262ff6501fb92e2a96ab85f28f879cb0ac39",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/Simulation/EAI_SimulationMedical.c": "a9da70fdecd20d8fd9e23f45fcb2b070916b76f0ee0418f72f18805f2d2149f0",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/Simulation/EAI_SimulationPrison.c": "f9098c2f312e202130b3789eb2b67ca38ed3c44a859be24543816a028a552644",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/Simulation/EAI_SimulationSpectators.c": "0e3b911914cf06e31c836323cba170782ef994338d75cd8202b5ab7c4e9285f4",
|
||||
"escapists-ai-norhs/Scripts/Game/EscapistsAI/Simulation/README.md": "0cfb17d257924e71b76e4697a53e0c34399e9fbf001cda446484503fce41fc00",
|
||||
"escapists-ai-norhs/TESTING.md": "6ea91133ff6fcdc7db4d55590b365f24f2772ec18c08d5d12d17e15dfde0b091",
|
||||
"escapists-ai-norhs/addon.gproj": "5de80e1c9186db83451532d7204a2c209290335e97eea67c7eaebe5a067117d7",
|
||||
"escapists-ai-norhs/diagnostics/2026-09-11-server-performance.md": "a6e2fa75ab529d1a2e23eab80958f991e8d77d4c4814eea436def95f60607bd4",
|
||||
"escapists-ai-norhs/diagnostics/2026-09-12-captured-uaz-defeat.md": "10a3b15214126e540ad44dd923240fabf8e04896f413c0caff0e45e631c38912",
|
||||
"escapists-ai-norhs/diagnostics/2026-09-12-hq-nato-reporting.md": "3ae76c1ae837812f8637f7cb8c0a9456bef07332a8d795a0fc949e8706bf8fa8",
|
||||
"escapists-ai-norhs/diagnostics/2026-09-13-hellsos-session-audit.md": "7fbae760c1495dd9199e43fcf490ec4d8e44be2c370f98ffa11c16b104203865",
|
||||
"escapists-ai-norhs/diagnostics/2026-09-13-session-fixes.md": "0bd9d29286e66b04cdd6d4942782ff5e4c8fd4370e428c7ce8157c0d5baa8c23",
|
||||
"escapists-ai-norhs/tests/ai_chat_config_regression.py": "b4b0dc6a74a4a5beda787fb676a378316bfb9c9589bd6365ded0ae3da44d91df",
|
||||
"escapists-ai-norhs/tests/ai_config_regression.py": "7dec0063274ec84a861f11b4df15b75c68dc88fa132f1ce9762063ef05bdd504",
|
||||
"escapists-ai-norhs/tests/air_assault_regression.py": "f27ea28bf4c6e52ecaf9ce45fa3bfab1bce7b6e07cd8eac377f465a7d4d6bad2",
|
||||
"escapists-ai-norhs/tests/air_support_regression.py": "b0c0cbf9d2918b03b37297575cbd678a633296939cf6c64095769fac4ddb7074",
|
||||
"escapists-ai-norhs/tests/airport_reload_regression.py": "9ef8ab9ab33d02899636859ae3c65919726b92c0c7a9604af704bac2c1a78b85",
|
||||
"escapists-ai-norhs/tests/convoy_stop_regression.py": "245dd69dcd300a49fe743875280321165d1da15c0cdbe23188631eec3e418c54",
|
||||
"escapists-ai-norhs/tests/depot_loading_regression.py": "2e80b3ce86b0607a5b62cdd49d7e898c17c23fd5e67597a5e8789bc71076ba41",
|
||||
"escapists-ai-norhs/tests/faction_alignment_regression.py": "37666426aae9f303f255861f89cf4cacefb38a6994fc2dd6fced11f53e1b7c7f",
|
||||
"escapists-ai-norhs/tests/helicopter_availability_regression.py": "b8f92feaf7f8057082a9c7c20cc889da3b614d74d19e206491ccecceec7e92e0",
|
||||
"escapists-ai-norhs/tests/helicopter_recovery_regression.py": "38e693a1c9f204dbab1a4ab800fa219d6aa3b7c378957434ab312a2f84832d25",
|
||||
"escapists-ai-norhs/tests/hq_body_search_regression.py": "975abef7f7ef378b150e2c46266574a786588a2fa0ff6ee43e708d58227222c8",
|
||||
"escapists-ai-norhs/tests/hq_journal_regression.py": "426a04d4117c2e9c3d4ce5aef112cb628cb0cd6511b727d05e554b6a29ae1c8e",
|
||||
"escapists-ai-norhs/tests/hq_menu_checks.py": "6f14906d08ddd67e909eae5ef37ca8395476fc84920fed77ca276012a58dd88b",
|
||||
"escapists-ai-norhs/tests/hq_network_regression.py": "a09b5cbf3453e6af31d1d888b5489586efbddbdb89b6e2b2d6eed52ce67e1098",
|
||||
"escapists-ai-norhs/tests/hq_observation_regression.py": "76b715d46f44d560896c502d01ed89ce16b6366596b607cef111db886cb6dcf6",
|
||||
"escapists-ai-norhs/tests/hq_regression.py": "4b9a0b66851f27700584e548c82cda8de7f9fda72868566e4bac227500951172",
|
||||
"escapists-ai-norhs/tests/hq_settings_regression.py": "1e68b985cf7d0446894eeecfa16335d4581e78c386a2ed81454e62512f6c76d6",
|
||||
"escapists-ai-norhs/tests/hq_watch_regression.py": "87e9bb484e2a37bfda9a4827d1fa4cd50b0c38bde07659df171c7e9c800a2150",
|
||||
"escapists-ai-norhs/tests/mine_task_regression.py": "5eca78bfa4fdc11f6f9107e83b06676f6f20cc4fb75b940768a25ffaaa6f812b",
|
||||
"escapists-ai-norhs/tests/mortar_deployment_regression.py": "8fdb4994d05a56409f46f074c2f41298143628d19c5644093e21eaf423eee31d",
|
||||
"escapists-ai-norhs/tests/mortar_engagement_regression.py": "a39ecc1132b51e13d80f4136a1d219fb5fc08d193b9e6c0be48dd9378e1e762a",
|
||||
"escapists-ai-norhs/tests/mortar_footprint_regression.py": "56ec6d478c036d1c7b1f65fde9170f73af77c8ed8175dc443cb079344c7a2c92",
|
||||
"escapists-ai-norhs/tests/mortar_logging_regression.py": "49d2c83c6f18ae8ffed152c5cc8480079a85731ec94fbd1f014362ec7d93f174",
|
||||
"escapists-ai-norhs/tests/mortar_operator_regression.py": "80f2a2d5e1bc8c38345b76f5e83cb3bc527fac7ad41111b3dee9327e60bbcaf5",
|
||||
"escapists-ai-norhs/tests/mortar_regression.py": "f4ed7027857056e158291d7a0c64072d435494c3d1dc71df4e6eee0c4a7e5c16",
|
||||
"escapists-ai-norhs/tests/mortar_salvo_regression.py": "bba2d57c4f5ccb76819ce90a63bc157e29fd033a3430318689c84c5e4c5f6f29",
|
||||
"escapists-ai-norhs/tests/mortar_settlement_regression.py": "6672605e495c1e7a3abd1dc1311f5449397d09152d17fd41a2d1cb78ff395492",
|
||||
"escapists-ai-norhs/tests/norhs_dependencies_regression.py": "e401d9049089e977a2c1216ec702b7f5f291ec9e58fb9f94074685dc30a57ae7",
|
||||
"escapists-ai-norhs/tests/prison_airfield_regression.py": "30f48b626ddccfbd0a8ca6295f00000cc89554c9491ecbb177032a48a746d15f",
|
||||
"escapists-ai-norhs/tests/response_capture_regression.py": "b6d309fe82dc538d6c6bb48e943f72fb9fb012b4e140acd36f9095ab12cb1878",
|
||||
"escapists-ai-norhs/tests/resupply_regression.py": "72828f53e6f77db41558cbece31da6ace6eeefc0674648dd16eaec659b46daab",
|
||||
"escapists-ai-norhs/tests/roadblock_deployment_regression.py": "b696ec1c5fabdade9b8c4deb831d33db118f30b63e66229d8fd885d62b49c9bd",
|
||||
"escapists-ai-norhs/tests/roadblock_regression.py": "e0725fe89b07e8b5371102800088d7be38158bf5248b155250595efb20cd8598",
|
||||
"escapists-ai-norhs/tests/runtime_resources_regression.py": "d8c0c602c60e5fea1ef35364be6163547b77d670b0d24ec5fcd76a97e1769c8d",
|
||||
"escapists-ai-norhs/tests/scope_detection_regression.py": "6865b52d1cbfe44d1b1b7a40555f202298056ecd2f3a93a09b6d36f6d28b3765",
|
||||
"escapists-ai-norhs/tests/scope_prefabs_regression.py": "8959c7d1d494d1808e660411ce4c2afb538e17af3220a57fa1f14fdf2f03f506",
|
||||
"escapists-ai-norhs/tests/session_fixes_regression.py": "b78419295f7b080de7068823a33ef81bef7ecfa49d739c77c9f56f99df098999",
|
||||
"escapists-ai-norhs/tests/simulation_chat_regression.py": "28f906f687a98eb1800a9f28ba7f7a550a0e40e6d4746eb134cca0094c5fd94c",
|
||||
"escapists-ai-norhs/tests/simulation_intel_bridge_regression.py": "f8ec1c424ff90838b7d34616a98ed1cd80e082c68de81c6743940a5a37785bf3",
|
||||
"escapists-ai-norhs/tests/simulation_prison_regression.py": "a901b2eb4b462d4794157e67b0818b88b2176f0beb2dfb38fd71685f86909080",
|
||||
"escapists-ai-norhs/tests/simulation_regression.py": "0e01653cfcae35530f68cd1bf5d5636e71b05e1dd396ba2194cda649c5a39237",
|
||||
"escapists-ai-norhs/tests/simulation_spectator_regression.py": "0fd3b920f691880be1d8c197bbec399d90361ef28586ba67ad4d5c7c93b7f2b5",
|
||||
"escapists-ai-norhs/tests/sniper_optics_regression.py": "5dedc2bb50455877f23209756251120a6eae83543fd5ccb5dabe0afc6739d47f",
|
||||
"escapists-ai-norhs/tests/sniper_weapon_lookup_regression.py": "fa077b2b6abb45a11216979b49c871e832a3a1573d8d823198e439475455b528",
|
||||
"escapists-ai-norhs/tests/spawn_selection_regression.py": "c9001edc39258e1f4419ae62f53ee4b0fa6535718810600d2afc14f73bc5ceae",
|
||||
"escapists-ai-norhs/tests/stinger_equipment_regression.py": "eaa3b92e1c9339c17beb589a7fa61a2cbdec06fce65c7e91bba456cdf27f9a47",
|
||||
"escapists-chat/Configs/System/chimeraMenus.conf": "656287f08263e6b386174866a521cc48942916ad68d172cb28293b93f7a0023c",
|
||||
"escapists-chat/Configs/System/chimeraMenus.conf.meta": "fd3c24df790b1384d159cc98f5de8e994d50ccab8135356522a9dbd1145329d1",
|
||||
"escapists-chat/README.md": "be913023a866d5c13f8635325ca5da5e6d4b6339df74bc34f57804f0e4281d87",
|
||||
"escapists-chat/SIMULATION.md": "7ef73904cec374a25feade1b3537bb3ac1e0e196fec882455879cdd7db9ce360",
|
||||
"escapists-chat/Scripts/Game/EscapistsChat/ECHAT_AdminCommands.c": "2d69b740298650aca6be2f45785ae016b4087c3688525c0c3f5b50b680d2c9e6",
|
||||
"escapists-chat/Scripts/Game/EscapistsChat/ECHAT_AdminMenu.c": "a50694429991ed0f00f310654142679e0d875babc721f0163fc3afa929ead7d8",
|
||||
"escapists-chat/Scripts/Game/EscapistsChat/ECHAT_HeliSnapshot.c": "c64faf70d0ac78d7600b60be445d289358566b7013fdd7df0fd6c94dfab908d3",
|
||||
"escapists-chat/Scripts/Game/EscapistsChat/ECHAT_HeliTest.c": "911519b9869b41a9a7e5e425e2924b7da4d80326bf074ca982dcc43db2f1113b",
|
||||
"escapists-chat/Scripts/Game/EscapistsChat/ECHAT_SimulationCommands.c": "bbc2ecb2ec55a31944673ba2628570f73cf2195da329b401bada8482478cda5e",
|
||||
"escapists-chat/Scripts/Game/EscapistsChat/ECHAT_SimulationIntel.c": "54aefe55c7bd1ea505076f5e7375c614eea1f3286567f380f82a66bee4b8bf99",
|
||||
"escapists-chat/UI/layouts/EscapistsChat/AdminMenu.layout": "9fb9a76ccaaff2a3c85cb6112ef5f6d272b3570bd4216d81c723c0f0c62cef84",
|
||||
"escapists-chat/UI/layouts/EscapistsChat/AdminMenu.layout.meta": "cb1d4c556dc2d267c80d7eb810a626e4c6549b2b40df51867e7d87f887f26f22",
|
||||
"escapists-chat/addon.gproj": "1abe8e6424ede84554ee3a3e6fc3cdac5b7033cdd081b8cfe9ddab4da86ed9a9",
|
||||
"escapists-intel/MAINTAINER_NOTES.md": "0b2005a9665cade015ac80102c44a80efcd86cea610342bfed3e8ea5f92cfcd6",
|
||||
"escapists-intel/README.md": "3d21e8ddae419783cd878aa1e8226b56802afa07dc871f919c1311fe02d7e055",
|
||||
"escapists-intel/Scripts/Game/EscapistsIntel/EI_IntelLifecycle.c": "7a987c65f0ec10ddcc138785409e370b9c1cc6abbda48027b7406459b42d00a9",
|
||||
"escapists-intel/Scripts/Game/EscapistsIntel/EI_IntelService.c": "0009786c543c2758dcd55d3d6936feca5641dd4c4b2ff820564a38815e4cca57",
|
||||
"escapists-intel/Scripts/Game/EscapistsIntel/EI_Log.c": "2471380ed8c8ae7cf4d0eddb438cec9470a22810c844398711e5363b598b296e",
|
||||
"escapists-intel/Scripts/Game/EscapistsIntel/EI_MapDiscoveryUI.c": "d3f44ecc2dc29d34e3ba6feda271d68bf795ed3a1c37b15a54f0e460d8a997bd",
|
||||
"escapists-intel/Scripts/Game/EscapistsIntel/EI_PlayerBriefing.c": "1aa7d8c7abf24542cf3b6488dc430fb65278dc4ba2e729b623d487ed65f464de",
|
||||
"escapists-intel/Scripts/Game/EscapistsIntel/EI_SimulationIntelBridge.c": "fa24c1aa89b2317cbe47a9248ba157b08ab365a807bcd22b8590fded907e5e61",
|
||||
"escapists-intel/Tools/pak_extract.py": "d19e6d0a595699d1a3755a028b3c30d4c91faa00248f7a59bf24721217e73bd1",
|
||||
"escapists-intel/Workshop/IMAGE_SOURCE.md": "c6f129be4a46bf1a86cb5caed00fb0509982a8b2e9ba2ce56bd48a71de04169e",
|
||||
"escapists-intel/addon.gproj": "90d38e584da4b94e2e64067c941553cc1a2ccd52801f9f9d2ddf3002050e1192",
|
||||
"escapists-map/Materials/ESM_MapRenderTarget.emat": "9877c5b175c5f30dd80bea36c711b21ab38219aa7075adf9ae79932e1d4c76bc",
|
||||
"escapists-map/Materials/ESM_MapRenderTarget.emat.meta": "f46a7255d51af1b43d9f9fd8e884640fed9e87a610a8eac1778e27cc2c262e5a",
|
||||
"escapists-map/Prefabs/Items/Equipment/ESM_SharedFieldMap.et": "8c0cdcf3e3af96eac710c75ccc54a7bbcb6713caf76a63a58f5519c009e747f7",
|
||||
"escapists-map/Prefabs/Items/Equipment/ESM_SharedFieldMap.et.meta": "33457ec2ead243640e57dc12c969be0d59923455f89669024e50998f63cca690",
|
||||
"escapists-map/Prefabs/Items/Equipment/Maps/Map_Paper_01/PaperMap_01_folded.et": "932b7f2273226ae5a2ce6fea7fee76007061bfc671f6e7c44e65512f0e5c2979",
|
||||
"escapists-map/Prefabs/Items/Equipment/Maps/Map_Paper_01/PaperMap_01_folded.et.meta": "a03019f632735602e9c6cf1f01d1c46975e19368098113211e5fe76eb74c24da",
|
||||
"escapists-map/README.md": "cbaf0a313235a0862b35a4c1e82438f5d84b174af44a8f17d546526369af6176",
|
||||
"escapists-map/Scripts/Game/EscapistsMap/ESM_SharedMapComponent.c": "26201b9d2b04986b9684be81dff47200a631d8cd01b57e96788a153fb56e6b4d",
|
||||
"escapists-map/UI/layouts/EscapistsMap/SharedMapRenderTarget.layout": "49a2da4181b94d42174f58c7f9b6bf2207116c99427d61ff1c212092ac7db4d2",
|
||||
"escapists-map/UI/layouts/EscapistsMap/SharedMapRenderTarget.layout.meta": "3311c3d2163fa0a59eb98ca07cdf79814f1d5131e95231a0a49783e8dc455cf7",
|
||||
"escapists-map/addon.gproj": "a1e6a6c3dc59f04ff6c3a660f65106c00a2994035fdcb4c79e9bc91f5eb54f21",
|
||||
"escapists-patch/Assets/Patches/ESCP_Skull.emat": "6907bc9e0368b76404696a8b29533caed8c609959a9df90add50efcb1541f750",
|
||||
"escapists-patch/Assets/Patches/ESCP_Skull.emat.meta": "a383bda2070b1bbbaab67fa6f4d91312b0d250446f04f91211d2260b2d5278fe",
|
||||
"escapists-patch/Assets/Patches/ESCP_Skull_A.edds.meta": "27a2993cc12e30f7746cf3f0dfa208e68a30b0d47b348da3c99ceff1a139bbf7",
|
||||
"escapists-patch/Assets/Patches/ESCP_Skull_BCR.edds.meta": "f540294da03bf946d4ae7055fbf3f6fe7d28f1b2259f47620021b6b1ad5c2bc2",
|
||||
"escapists-patch/Assets/Patches/Models/ESCP_Back_225mm.xob.meta": "8fd4e5c13e6ea5b5712382dbea8677b269f665dff1dc6d168516ba3aa9498e4d",
|
||||
"escapists-patch/Assets/Patches/Models/ESCP_Back_Curved225mm.xob.meta": "a5073dd7c371e3d8491e3a1053a8b8656b831dc2cb31244792f293c00ffe093c",
|
||||
"escapists-patch/Assets/Patches/Models/ESCP_Pack_180mm.xob.meta": "d18b1a75fa049f3588b604dd7a1ccab07d33b6ebfc93b7c86fd305df8c579f6d",
|
||||
"escapists-patch/Assets/Patches/Models/ESCP_Sleeve_72mm.xob.meta": "c32a2353b27cf6726d7e53b4de695e2a77593fd02b8964813289160431e1d1bb",
|
||||
"escapists-patch/Assets/Patches/Models/ESCP_Sleeve_Curved72mm.xob.meta": "8a5af9eadd928c9757646a160bde66cc4e92a7bb81744f8465d8c0ee44d92ab6",
|
||||
"escapists-patch/Assets/Patches/Models/ESCP_Sleeve_Fitted72mm.xob.meta": "0d4382171a3fa3a0ff8501d9b22b5d553dfab7f44d957821ec0b61628314fa51",
|
||||
"escapists-patch/Prefabs/Characters/HeadGear/ESCP_Helmet_PASGT_Patched.et": "757ef59516294e92022fde33c9599927c2e80eb0664c6d0dfc9c0a845019b92f",
|
||||
"escapists-patch/Prefabs/Characters/HeadGear/ESCP_Helmet_PASGT_Patched.et.meta": "4b2da8c3ff1866ecbb3081a946399a26052b3d77e4bf958a7885cb534f1a6878",
|
||||
"escapists-patch/Prefabs/Characters/HeadGear/Helmet_DH132_01/Helmet_DH132A_01_base.et": "a91c158e46eff06e7ad6f3ac0bf4e782034c61645f33028e4534b0068f59c2ea",
|
||||
"escapists-patch/Prefabs/Characters/HeadGear/Helmet_DH132_01/Helmet_DH132A_01_base.et.meta": "609dc0beb722f3b9770acd749344919fb00400c5d95166fc74cf1055b6d9d9a6",
|
||||
"escapists-patch/Prefabs/Characters/HeadGear/Helmet_M1_01/Helmet_M1_01_base.et": "ae68ad4503037d812cb5d2d1651eecc5c7648204268c0c84aaf06c090a0ea808",
|
||||
"escapists-patch/Prefabs/Characters/HeadGear/Helmet_M1_01/Helmet_M1_01_base.et.meta": "1683b448b8be6b4baa1b97d54c425eb07c3eed1c8449ca050fb24738efb8afd3",
|
||||
"escapists-patch/Prefabs/Characters/HeadGear/Helmet_PASGT_01/Helmet_PASGT_01_base.et": "ff7c3b3510074263a12b73f7907463519d342099be9339b7d7244b9742885dbe",
|
||||
"escapists-patch/Prefabs/Characters/HeadGear/Helmet_PASGT_01/Helmet_PASGT_01_base.et.meta": "7a1cc8fee277e1841a5b7fb2a270697dc9bdb8acc8912daa79c6263fc2cde09c",
|
||||
"escapists-patch/Prefabs/Characters/HeadGear/Helmet_SPH4_01/Helmet_SPH4_01_base.et": "2556cd6ce1e6636fa271a5956e7719de69c1fc4738a9f68486a54bc29758b792",
|
||||
"escapists-patch/Prefabs/Characters/HeadGear/Helmet_SPH4_01/Helmet_SPH4_01_base.et.meta": "7329c347f09015b91b876fad9ca130a67f240525bc446f4061cc7f41cb328e31",
|
||||
"escapists-patch/Prefabs/Characters/HeadGear/Helmet_SSh68_01/Helmet_SSh68_01_base.et": "aea145545fc4a981f00dc2043bdc3431a988f2501fadb9df774b0ac9553f7f82",
|
||||
"escapists-patch/Prefabs/Characters/HeadGear/Helmet_SSh68_01/Helmet_SSh68_01_base.et.meta": "38ad6395317249d34c7cca74182a0153468995b70856047cd78398ee1ef30fe4",
|
||||
"escapists-patch/Prefabs/Characters/HeadGear/Helmet_TSh4_01/Helmet_TSh4_01_base.et": "f2b4bbd516d689b1b06bab647aeada8d1223b0ad7e9f3d36b8598cacb3287a22",
|
||||
"escapists-patch/Prefabs/Characters/HeadGear/Helmet_TSh4_01/Helmet_TSh4_01_base.et.meta": "452bf31d7dd9716fc42de76ac0b4e13c3c1a41b4c3f15abef6b4fe98e961b771",
|
||||
"escapists-patch/Prefabs/Characters/HeadGear/Helmet_ZSh5_01/Helmet_ZSh5_01_base.et": "2f73f242f3c123fe0af4cf9c98ae59cf76597eb1328d7be4ba9eb2a28139107b",
|
||||
"escapists-patch/Prefabs/Characters/HeadGear/Helmet_ZSh5_01/Helmet_ZSh5_01_base.et.meta": "fd17dce03515044ccc2679f34f03e4f00f2b973fb38223a0dbb68ff857228ccf",
|
||||
"escapists-patch/Prefabs/Characters/Uniforms/ESCP_Jacket_M65_TigerStripe_Patched.et": "93f4f5358f0d2a735c4a14368d57049c18c8d2ba93fdf6db3b6c79ae6b833d0e",
|
||||
"escapists-patch/Prefabs/Characters/Uniforms/ESCP_Jacket_M65_TigerStripe_Patched.et.meta": "658512e1ff18389932a47624513d56aef0ea6a7b1b71d5de8b39fa127de769ee",
|
||||
"escapists-patch/Prefabs/Characters/Uniforms/Jacket_M88_base.et": "93b8453c1452b21d2bda2934c503b07a41c6a8641bbf45f569c21350e4e3d3a8",
|
||||
"escapists-patch/Prefabs/Characters/Uniforms/Jacket_M88_base.et.meta": "104a389bacbddcf4d2f938cba68b10fd4530c81223cf902adfc5501e51a4c369",
|
||||
"escapists-patch/Prefabs/Characters/Uniforms/Jacket_Tanker_USSR_01/Jacket_Tanker_USSR_01_base.et": "ae605ff397836037e17b7b21bb7db32323d55745256e64e42423f9ae1d353645",
|
||||
"escapists-patch/Prefabs/Characters/Uniforms/Jacket_Tanker_USSR_01/Jacket_Tanker_USSR_01_base.et.meta": "06d46e927bdb92aeb12856966812a944782d432c3a832ad8d9f5c998afbe99e5",
|
||||
"escapists-patch/Prefabs/Characters/Uniforms/Jacket_US_BDU_base.et": "eea1a6e1c49a38bd6a6ab6450990695ddd9bd9700013d79ab8358bbe231e6294",
|
||||
"escapists-patch/Prefabs/Characters/Uniforms/Jacket_US_BDU_base.et.meta": "6a492b8a31bed7db145a2c419e25ca4894f3a578b74cf0c7a4b00512f1479a9f",
|
||||
"escapists-patch/Prefabs/Characters/Uniforms/Suit_KLMK/Suit_KLMK_base.et": "be210c5e9492621a16a04d0c6b815487ba337b42c355127ac76a11cd1f109459",
|
||||
"escapists-patch/Prefabs/Characters/Uniforms/Suit_KLMK/Suit_KLMK_base.et.meta": "1f21cfd82bce281e2cd50986f0ded8e974545d8d481c9e935d8e1a7400b06eb0",
|
||||
"escapists-patch/Prefabs/Characters/Uniforms/Suit_Tanker_US_01/Suit_Tanker_US_01_base.et": "e278548232e5c11603b86006c6184581674e969380e4729d65c7ac82af98ff55",
|
||||
"escapists-patch/Prefabs/Characters/Uniforms/Suit_Tanker_US_01/Suit_Tanker_US_01_base.et.meta": "7ceb163e10d80336118585d934c0f3f6e743a7298d7a877f402084baf8a264a2",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/Backpack_ALICE_Medium.et": "8f3bf70ba09ebacfa1a28a12c227124d9de85d873cfc23bba769f50ee545ead1",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/Backpack_ALICE_Medium.et.meta": "61612ddddd6e103518dad67eab01fcc72986bc429d6b9ac969137f476d6cd951",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/Backpack_ALICE_Medium_assembled.et": "3a15856b9f40660ebd765036b1c902531fdc0885802233ab2e03b5be44d1c3db",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/Backpack_ALICE_Medium_assembled.et.meta": "7223838bac409f61f2234537cbe0168dbb490c6062cc266fb39d6c535e6ddd1c",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/Backpack_IIFS_FieldPack.et": "3c456ef65ac9e82dac0a36463799c6bb00a4b72ebca70c28a81d063189453c04",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/Backpack_IIFS_FieldPack.et.meta": "3d7a4f366bfcc1ad424102e1f221a91ef5c8ecee4d3ada88cc91d41e13c04788",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/Backpack_Kolobok.et": "4cb770b2d6b88b2657ca9900851bcff799bc3d826b17e0f31dc14d18ecc4cb05",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/Backpack_Kolobok.et.meta": "6f5ceadadc66bd6ba8031941a8ce03e15572359230d06002de28e9a0284770b7",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/Backpack_M70_Swiss.et": "05605c4eee9acc70df6ef042a6ed3e8bfb482d7f76985e10fc7639240808abb5",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/Backpack_M70_Swiss.et.meta": "e43217419c363f42ec83ddf10f508f19dd35ed3984ab19a63abb939a1ac861ac",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/Backpack_Medical_M5.et": "c17d5c0ab32c6b9ad69bbbb201b0bda6e67a3cf936778bf004cdddfeeb00f8ca",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/Backpack_Medical_M5.et.meta": "f425171d25268dd805b4a2b0475e8ddba102f42c08f8c046ac5789f8b51f0cb3",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/Backpack_Medical_Soviet.et": "0dd38da4c5f65cce3537d8133cc6d40ae0b6ec80f77fbb3b3b37b26ca2febdf4",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/Backpack_Medical_Soviet.et.meta": "e2defcf634d9c40986b592758c22226a494b5cdf725bd254337242e49a42641f",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/Backpack_RPG_Assistant.et": "fe9feb72eaf6aae99fe5808886ff2520f7a345ac711e28b1f30cfa7da10338c5",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/Backpack_RPG_Assistant.et.meta": "188f317c0c8a74648221bfc7030e347d4699ec35e013ef819f2d76f9d7058991",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/Backpack_RPG_Gunner.et": "d36ae6c431d72b32dc7d56117a5cc9f0a722e6a1ab061c7727c517a050e5912d",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/Backpack_RPG_Gunner.et.meta": "e275c9a0a9133568cfdcb46915a85b4cd3fb7dd52fc0f77baf90e56311802f5b",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/Backpack_Suharka_base.et": "7f64ccca0f90ba51c1ef7eb6f5586c3f59e109b4ce8d9f21cb2214d39d42cf12",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/Backpack_Suharka_base.et.meta": "2b8ce61e9ddb1e9e469c747fd4d6c5176565b8b1e7a6c8b4c6fd39f16b61f761",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/Backpack_Suharka_type2.et": "497c331ef43bf9d287a07f20fa8306c434f99ec89e701915ace4568788a4b4e8",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/Backpack_Suharka_type2.et.meta": "c599046782445724cb4a53abd682dc2fee5dbe26105a20f71f972fb412c5f73f",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/Backpack_Veshmeshok.et": "066a13e190368b09982f94ee663d01111bb1135a0a9abc4a7008448d00b3bbb2",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/Backpack_Veshmeshok.et.meta": "99112032863d20910cd8cc1476bdb2d8befa699d2adbfc0b0e3615f88ef4e166",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/FILBE_Backpack.et": "d916e45452b62f2da86159489b74a268500608abe525e47f0e961fe089aa1838",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/FILBE_Backpack.et.meta": "23300f705f2afd0a9343ea5d1adc2d4d63d70d35e0da7bef1cb963957fdc6227",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/FILBE_Backpack_Heavy.et": "59aeef62b03a2e4a13c160c6f28a7feb2f6037b83ab19028f177ba3990420154",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/FILBE_Backpack_Heavy.et.meta": "dd1bd5df67d3c4d84fe61c5b7ff24d422797fa3f1502507829090435dbfb1282",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/FILBE_hydration_pack.et": "2b119bab03d0092a5e2cbbad82c631ef3ea20ce10d10fa17faebd567894aa469",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/FILBE_hydration_pack.et.meta": "24d287958d97bf777e6c2161a74df89fa398c3a4076acd9a0907c8308e1153db",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/backpack_511_rush12/Backpack_511_rush12_base.et": "6fd3b2a452d4713826f8fcbfd21c3e1c2eee01ba3f6e4ed1b63e6720bbd630fd",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/backpack_511_rush12/Backpack_511_rush12_base.et.meta": "54504ab186fb3ff03b333fad39c7dfda29947c4977d6ff9d64c7182ec1475666",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/backpack_Ratnik_6B46/Backpack_Ratnik_6B46.et": "e15ae6282732b739db54527bc8fdfe81c1274886d4f9afcabc3ec18d02492c4b",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/backpack_Ratnik_6B46/Backpack_Ratnik_6B46.et.meta": "3b872d49e1d8da367226759c10c20b076a33c809d0c9d5a2961049c46745e4eb",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/backpack_Ratnik_6sh117/Backpack_Ratnik_6sh117.et": "5e9b64c3c1bc36782cff619742c8bbe4c537201b58205d5d24eaf4a8153a39a1",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/backpack_Ratnik_6sh117/Backpack_Ratnik_6sh117.et.meta": "e8eb63cafa3bba4997686fcd746e0cd2b45fced3fdcc0f8564933516bcb5172e",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/backpack_Ratnik_6sh118/Backpack_Ratnik_6sh118.et": "05f62416f2da5b591b1c27be40c514997e48cf805d0baca3e4ea464c18478aa6",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/backpack_Ratnik_6sh118/Backpack_Ratnik_6sh118.et.meta": "97e1072fafee6033005fb254914abc3d51a40f0aaa6ebfc6923ea1ed417a29ba",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/backpack_Wartech_BB102/Backpack_Wartech_BB102_base.et": "9cbd67c8a69232d89b95930b9b5d204ae2eab60c386eb17de92bd83d152ec078",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/backpack_Wartech_BB102/Backpack_Wartech_BB102_base.et.meta": "b6fa72a3c1ea2f16b1bd5c3f7b10c4d2de6bbec6ef67d4029712159248378041",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/backpack_ZipOnPanel2.0/ZipOnPanel2.0_pack.et": "5212d8b4797006afc220080e58efc146f5f81f695b6ea58bdf519257bee13837",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/backpack_ZipOnPanel2.0/ZipOnPanel2.0_pack.et.meta": "be8902502435a48ecc0abe3711f21be85d807da661d0211e9fdbdc4038e0c41a",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/backpack_ZipOnPanel2.0/ZipOnPanel2.0_pack_ATACS.et": "354dc9b10ce8ca87ce8eb7955a4f0d144bc6c0a1f3fe6810292daf52ea1e1748",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/backpack_ZipOnPanel2.0/ZipOnPanel2.0_pack_ATACS.et.meta": "2a216d09d0fc659b97c098388d9919339a7e446e8dfd0c25c5edfa728b83e27a",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/backpack_ZipOnPanel2.0/ZipOnPanel2.0_pack_MC_Black.et": "50640ebb82f05aa9954c438a4479864f45b353d49faa26642954f8257197fce2",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/backpack_ZipOnPanel2.0/ZipOnPanel2.0_pack_MC_Black.et.meta": "21cccc2eb06f2d3a73b48a3f365f433194524acc4592afed2f0c4e2910d28804",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/backpack_ZipOnPanel2.0/ZipOnPanel2.0_pack_Multiterrain.et": "5d449668953103ce90bee658c1d4293271cae00b2c807904c463ec105f54a694",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/backpack_ZipOnPanel2.0/ZipOnPanel2.0_pack_Multiterrain.et.meta": "439576767a36105e6391c6fddf65da337aba4114de98f06cb67b81ba0f34d6bb",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/backpack_ZipOnPanel2.0/ZipOnPanel2.0_pack_OD.et": "cda0f3bc354b644ea522c078cdd80a375741f3fbbbe8bd772def75d7c0e3fc2a",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/backpack_ZipOnPanel2.0/ZipOnPanel2.0_pack_OD.et.meta": "3286cc9db06bf35a2fd343f8afc8cb4ffaee243ed6fe152a611a6c570f0c20bb",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/backpack_ZipOnPanel2.0/ZipOnPanel2.0_pack_multicam.et": "4140d8e5ac0084c0ee4f994ec6a71ea1dbc287e22c3c58fa48857262702c476f",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Backpacks/backpack_ZipOnPanel2.0/ZipOnPanel2.0_pack_multicam.et.meta": "f9ee7b1193e1695610657299068b9a7ba30746dbdefcec1c54cda30a59d57e96",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Patches/ESCP_Skull.et": "03af13f2fe8dd860b7118a9fc12e3c081aac7e26847cd770e3e0ed97485ba700",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Patches/ESCP_Skull.et.meta": "f1f8d521bac66aa0b5530862b51639defe7635dedb1a724eef9cd364d09951d0",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Patches/ESCP_Skull_Back.et": "7716d4d05bf5e6226957a6e7f6ee7ce5b731289a1df2a164b57aebbe8f72a709",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Patches/ESCP_Skull_Back.et.meta": "0bfb0416b37c904f97a1c8c2dbda1a8498cfc3d0b9cc12cd01f11d0ba2bb2ad5",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Patches/ESCP_Skull_Helmet.et": "b4b828c79229380e3beaca8d53d2ef3db2061654f59ba73ab56481aab1d659a5",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Patches/ESCP_Skull_Helmet.et.meta": "31e763a24c7624ab75212d5689ab55f4e679735f4034e0a93a34afc2a50ae366",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Patches/ESCP_Skull_Pack.et": "be4ab09f440dc41b8e4d1cb54eca91078c6765cfc5831496466c00c05724697a",
|
||||
"escapists-patch/Prefabs/Items/Equipment/Patches/ESCP_Skull_Pack.et.meta": "a9d48cce76b5208c91d1f90c125963e4c2533f634afad13ec160203a6c735b5a",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharFILBEFit1.et": "f043d9aa8fde3fde62c29d142bdd7522d8e55f5833aae4fc506e0e163f39dea9",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharFILBEFit1.et.meta": "779935d511265d25628978184d07dd23aae3de3c12e26511205de1b6488b5ecd",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharFILBEFit2.et": "d87d9324249f238d3b075943a9809f6b43bf0a5f98a7ff709cd8b2f4e5616074",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharFILBEFit2.et.meta": "ba9927d2ce1d9a650273fe58065669cfe5394c37ea7d592afcdd13dda0302bb6",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharFILBEFit3.et": "76814586e6715bc255286bb93d7fbe048c3a1a89acbecbc4d1f171722ca344d0",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharFILBEFit3.et.meta": "02dc6dccea360364bc6c9ba15a1569b1eabd245516c06ad9b2f46f786322e216",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharGear1.et": "653c6b66563f1bff092f7ba4f74666fa51a063f1667e3e2c7dcbff1010d173c5",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharGear1.et.meta": "9e45b171616626d3342091b18ace2d1137478c06bf5e09ebcf8104534ce569ae",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharGear2.et": "d78a162975e8650b801b5be5a218088382d381f0b4f64622664c673d795ace88",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharGear2.et.meta": "4da326804005c97938c859809c49fac9dac228e86ac72329beb53fc6bc01a286",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharHelmetFourM1.et": "814da9bdb66365d8daed186d62ac9e6940529fd9334a9091c6e7cef1912f0c9e",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharHelmetFourM1.et.meta": "cf856a875b18c336f5005fb9de72c6ec74599931914026adc955b9139895650e",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharHelmetFourM1Tilt.et": "87dbc5ae16cda3230d9b9d61ca3b33cc327db494da6248774572ba1d0d7730bc",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharHelmetFourM1Tilt.et.meta": "8f022f3c3ddaec4a879d3cd9cc648696a7afa7bc0af2596df891dc7309007cba",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharHelmetFourPASGT.et": "3a052bc57c5099ad4c9cf470943acd0034fa3bee69d4564b78092c4b6b70fedd",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharHelmetFourPASGT.et.meta": "9ca4c7c76fd5ae3e358656a3b8a5ee13598a2ff5ca9c6e9ce3a5a0fe58da9c96",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharHelmetFourPASGTTilt.et": "3db2f11830872ec63ae91b4f08b39248824765dce53d562e15ff2032c3e46f01",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharHelmetFourPASGTTilt.et.meta": "78342ddab8a2c04d16a8f9a634872b493377356f5bd49d319ea26b0bcee81ac4",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharHelmetPASGTFront1.et": "9fa494c0653a05a4b62b6fcddeece5e22918bf93ba973ab39f2fb889ad667be9",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharHelmetPASGTFront1.et.meta": "9ad9b05f0ce713a479d34a5d1cb431e8fe455dc93333310107c1883f8dd9643d",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharHelmetPASGTFront2.et": "6e6b5ca474a17edc6497b767743d55eeb5f46f31b724658ea85d263df9ef4b34",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharHelmetPASGTFront2.et.meta": "f5f955899fafaa4a41e16a1904d7bb70389347de9b7ebaef06b76c8b34e8c112",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharHelmetPASGTFront3.et": "e3a3c4837e17ca52db15e29fc39c35ab4cb1c00e33c4a11a573ff4b0b865e858",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharHelmetPASGTFront3.et.meta": "b64d2a2bc0ddb3e5bd6fa4b1320d2eeb16e5f76535b91a8803e9a74f4b3f46a0",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharHelmetPASGTRear1.et": "54030fc52189ae70eff80cd770956c239f16cc772541a975eb8c8b73dd25fb3b",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharHelmetPASGTRear1.et.meta": "0618331eb609b5b532a3e20beccfc886e43625f38ff81f77d15bc7690dddd9e0",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharHelmetPASGTRear2.et": "e36ba83df18f417a0085ffb8229d9d21197b48545cc0817ec8ccd8383c312d3a",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharHelmetPASGTRear2.et.meta": "0b01283fe92cae30bf47e54f6e38ae000653fb27df6543f337407c57a492f6bb",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharHelmetPASGTRear3.et": "d77ec36f1f75baf07ceb9e38b4439ae6f13445b5e0f93cb7b77cb98df20da84e",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharHelmetPASGTRear3.et.meta": "13c30640b1908f47c6da67fd881b0430d69a4f581b51d3777b6cc2e78268449b",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharTigerFit66.et": "7325a3e33daacd3bf522c9135fcae5aaa19e449c4db52be9a8a80740d9868520",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharTigerFit66.et.meta": "28ae6c3c9d98dfd13835e87e5f30de03dcb0ff025deb4baf09fe1ebf0793014c",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharTigerFit67.et": "be48215f404dd4e8560d2b991e8635a4e93942600b2ad38bcb82a121455a5557",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharTigerFit67.et.meta": "eaa4615864bc9b253f3dd1f32c25542550f23773280ca1866c4ace61da1c600f",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharTigerFit68.et": "b411b59961ee42db5088afc5d5bf61d3e59c8a7dbf128feac940ba83c40eccb2",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/CharTigerFit68.et.meta": "de104a8a6c072a508c858b3d6cd7c0201e6e6cb5ceeda24a694799abba4e126e",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/GearFILBE.et": "4273df31a80ca8621581339a4f7aef0b8d6d55234e03f95957322b830dab8f27",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/GearFILBE.et.meta": "4779b12e7ecd8bb8849346aaabcb9800ee8ec723be765cb92168d7b9b6f9a519",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/GearFILBEFit1.et": "503014cdf4f826e4cdf81915df4452d88e218c58ac55c2db21f5e9f565291c33",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/GearFILBEFit1.et.meta": "8a7348d0a19822e10e062305a58d6337a82d61dc9fd91c39eb0911bfaa932478",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/GearFILBEFit2.et": "5770eacb70da360743418cfda2e8da90c7ee8bdb2fec5745872f42ecf0b13525",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/GearFILBEFit2.et.meta": "427062afeaa3613e6b55847a53b89d6e907f1df4c18e95e59ef967be0826b586",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/GearM1.et": "01b49694615db2187251a672334847a018b5cd9486265dd5bb10196a61707765",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/GearM1.et.meta": "6a4019b8ab670ac1ac5e7a5ca25b42f466bed7355cb533fb244b3f9577fee343",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/GearM5.et": "9bc94ede40b929ce1082aa036568d84c9e15a8d40da48baddcfd4f156fb8233b",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/GearM5.et.meta": "07caa5e3868837ea4a54a83cc97bbe103170bf03aac4d9f7a5b7722727a65338",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/GearPASGT.et": "3eed9d554a9980f0227abf96a8ae815d4724b7dc4eb2858b1c7d52e5643b8c98",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/GearPASGT.et.meta": "e5f4f8bf6ff9699ef6cb8edbaf5018e78f72876473f76fe8e991fc34c7ff60cf",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/HelmetFourM1.et": "f4e0a280ba3d13fa85a955ee31b8bc0cd9dfc584f737c712a8f5ae67f0dafae7",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/HelmetFourM1.et.meta": "05cea2bb21ab97c6e01cc0752f8f2b1917bb2d0df19ecd93fbd3990db8e3ef29",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/HelmetFourM1Tilt.et": "f0dc7865fc4a21e72aceb4a7d3588ff1bd9d748884f3a79816a0fc1819af1df9",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/HelmetFourM1Tilt.et.meta": "f79c1f175e81f7949eb3359fca70ccbbe4335ecc7d26c65d859f1ed8c66d13e0",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/HelmetFourPASGT.et": "01ea6fa20590fe3ad26cbbf3e1b87c2e74a5fcd631989cf1a0b77dd350678b05",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/HelmetFourPASGT.et.meta": "a01b312784805d9c2fc24d9180c85c3e0c36241b4c461318a9b850cda2f44cec",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/HelmetFourPASGTTilt.et": "c291114210171b0b6a0501a5684c9d6df3a7212f630696a0b8377e7e11d1b5bc",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/HelmetFourPASGTTilt.et.meta": "f3751486872ad1278fbe26b1e3fba6744d422c01374c7cba421126ab4b8be5c0",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/HelmetPASGTFront1.et": "65bc7abac576d3c17822b609f72c92a957c42b4cb7cbbe7d38e7c45f3adc215b",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/HelmetPASGTFront1.et.meta": "53ec0ebced3c482a0495e06fa44dc7779bd59968eff251d99d6352f9893a38f8",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/HelmetPASGTFront2.et": "e7e0e63fd242feb9706f6d3b2479b9153aee2078d1355e7f12581765be1dd8e7",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/HelmetPASGTFront2.et.meta": "8fe87ecc675e163c125bc194513e964c90e54df2c785ba3531bf0df30c38c29a",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/HelmetPASGTFront3.et": "9788e9de001b477897aa77c2a4379c2d11fbf3b3b7f1684244d09f05d7d9e5e2",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/HelmetPASGTFront3.et.meta": "ece97f945cf0595232e1ca5207fcbdc55b4f76e8b3757438261b50b771d5376b",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/HelmetPASGTRear1.et": "3e08bdb142cf2470ee2b7ceaad5a33d20c0142e15d30195953923e90e4f4b5d4",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/HelmetPASGTRear1.et.meta": "4fd6bf7091f47e5a8702d09929f9037fcd4c8149ba614392fee791fddbd1dc92",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/HelmetPASGTRear2.et": "544f8e5a96fc0768ce2b3927b7def6f50dde6c5b7c55c053c4ee59a8e0565489",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/HelmetPASGTRear2.et.meta": "26a5a91621c45c9bf6104ff71e9e819341f43606ebd9c0305d3c17d7fe061562",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/HelmetPASGTRear3.et": "31454710876a877217aab9aec08ea90c66d4f42bf8db2f16e32888ca0a0059e6",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/HelmetPASGTRear3.et.meta": "bb6cb5e8ecda38f7378f5c94a5d23fd08e531f2d018e2a56d9fbe82ed85f0aaa",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/TigerFit66.et": "7583fff28b5db08d6da28bcfd5df55deba8170b7161548e0508f14a41a4f334a",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/TigerFit66.et.meta": "e92eb4a8df52936d8c68e20d2316a74e9ec9d6f06e399538948f077ef19b91e8",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/TigerFit67.et": "a0a7d127293c08987d28f3e160e69f2e2537c6a9e1363eb7a080dceb98de795e",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/TigerFit67.et.meta": "b07e8f7eaf5cfb30bc370b7cead96910365c7f6b4d8e00c1b3ce6924d3bbdb17",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/TigerFit68.et": "5d491854b47893ab50b71d1d70298041bc7696997a1c68bc8cfe223e2d92d3d7",
|
||||
"escapists-patch/Prefabs/_ESCPDebug/TigerFit68.et.meta": "1acb86a96f19fabde1e594f8ea1b8990a0b355e6114f5b032f1a5dd123fe50f3",
|
||||
"escapists-patch/README.md": "cc5afa38b5b3177bc143fb170e82c08dcab74a2cfa719f568cbf9c1aa25b4daa",
|
||||
"escapists-patch/Scripts/Game/EscapistsPatch/ESCP_AutoPatches.c": "0232a89435019b20fceec37135f92598145ac77894a98ea5a5f7942be18bf422",
|
||||
"escapists-patch/TESTING.md": "344d032f42b18b18d400daa2935576875c5317b5cc42a4020dd89b77df76beb6",
|
||||
"escapists-patch/Tools/build_textures.py": "6a0240adf01fcd1aa48efb6fde78a370e8e61407fab2942c1ab57a4113c426d2",
|
||||
"escapists-patch/Tools/export_patch_meshes.py": "48f7731fcc57622c90ac575e0c4a8748ef2ff8e15882a437937193eb49b92a88",
|
||||
"escapists-patch/Tools/verify_assets.py": "39fb7b3e4d67409ff7dd8a40d883662ac1266ced3a6db84eab26926a6e422c1a",
|
||||
"escapists-patch/Tools/verify_gear.py": "d7df9acdf8d99cb96d460f61ae94a3291dcc1bfbb9796ce57bc38a012b3e2ed7",
|
||||
"escapists-patch/Tools/verify_uniforms.py": "d3de406ab6fcb267e3a776e5e71494650d53651d8645239f25a9aa74b70533f3",
|
||||
"escapists-patch/addon.gproj": "e234f2a7903933a86ee6a0be8719006a98d2bff06a9f39508eb2baa98a2e32a8",
|
||||
"reforger-statistics/AGENTS.md": "74fc082b1e6c70abc3fa4e99a5f289bffd30625c309392c8664350c2dcb228dd",
|
||||
"reforger-statistics/MAINTAINER_NOTES.md": "346dabbd1a5e0ce56b5aac7be06c91f2011f9b671161fcc829a06ebdc0bdfda8",
|
||||
"reforger-statistics/MAPS.md": "30ba372dde52740ee09bbb22d4e2c293afda20e251ce6cfe91b819efeaccd282",
|
||||
"reforger-statistics/ModBrowser653511F4AE001B05/addon.gproj": "925385584840803646b02b832e4680cf04a8296c9d284ca268b51b8cb19176e4",
|
||||
"reforger-statistics/NogovaRecreated/README.md": "8e7bd24229284e0794b994f899e1da6af96e660d47cf562a49a08f826788af83",
|
||||
"reforger-statistics/NogovaRecreated/Tools/generate_nogova_heightmap.py": "bcb830378ec15d3d612a82d5e2767db7bf5924bbefa44c3f7bfce6508a598ac8",
|
||||
"reforger-statistics/NogovaRecreated/Worlds/NogovaRecreated/nogovarecreated/nogovarecreated.terr.meta": "24243ba2ac2926fdb1fff0405fb40d079b86060816692024319eaadab35afcc3",
|
||||
"reforger-statistics/NogovaRecreated/Worlds/NogovaRecreated/nogovarecreated.ent": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
"reforger-statistics/NogovaRecreated/Worlds/NogovaRecreated/nogovarecreated.ent.meta": "c930722a465fed142452360442917b1e328cc81fe691fb03f17fcf67e6e8dd56",
|
||||
"reforger-statistics/NogovaRecreated/Worlds/NogovaRecreated/nogovarecreated_Layers/default.layer": "7bd60da4456ef72567e7521972ad2da35bc1e98b111465f4884b5ee7eacf08ac",
|
||||
"reforger-statistics/NogovaRecreated/addon.gproj": "c38a08818c6c265a7e083f4daccd4fb9e288236c81bdc6c00489b1cf23c6f548",
|
||||
"reforger-statistics/README.md": "1066ecc10864286880695cdc35995e641a6dfb3b33a8ed8a70ca7a52bce5d279",
|
||||
"reforger-statistics/Scripts/Game/ReforgerStatistics/RFS_StatisticsGameMode.c": "bef865f08d4368bb6d2903826b8ca5c44317fb6954d6096752c7305b9c024803",
|
||||
"reforger-statistics/Scripts/WorkbenchGame/EnfusionMCP/EMCP_WB_Clipboard.c": "0351359a89acd3e5548b08abe34a0c35e3c01791fbc4d1739ba2c29e2bf3e44f",
|
||||
"reforger-statistics/Scripts/WorkbenchGame/EnfusionMCP/EMCP_WB_Components.c": "459252728379a1af3cb601c1873700a7695dcc51208cadf7dc978c829a5381c8",
|
||||
"reforger-statistics/Scripts/WorkbenchGame/EnfusionMCP/EMCP_WB_CreateEntity.c": "c5c2aebb9ec2d82d86eed8cb7945a6b72fef82e1b27fdcea9139887d211e79b1",
|
||||
"reforger-statistics/Scripts/WorkbenchGame/EnfusionMCP/EMCP_WB_DeleteEntity.c": "a45080f34548e360f9f7b9d227d75e84963f7d1c3adc7aeec93f1b280fe45267",
|
||||
"reforger-statistics/Scripts/WorkbenchGame/EnfusionMCP/EMCP_WB_EditorControl.c": "d4ab44c4fe4550de70c90b6a5a4d58cdf1e6c6282576c062b9a27fdeffb10e7b",
|
||||
"reforger-statistics/Scripts/WorkbenchGame/EnfusionMCP/EMCP_WB_ExecuteAction.c": "ad5572ab6e94009926029a3f53c73f28d73508795f94d00dd1a292c86e747806",
|
||||
"reforger-statistics/Scripts/WorkbenchGame/EnfusionMCP/EMCP_WB_GetEntity.c": "2d3e4ba796c74cf920178588fa0acb23e83462423d4d8dda3165e9042327969a",
|
||||
"reforger-statistics/Scripts/WorkbenchGame/EnfusionMCP/EMCP_WB_GetState.c": "e695c16fba27141e00f2b37c2eb7bde8f5ac9b7dcec8cfa9360a568f2749475c",
|
||||
"reforger-statistics/Scripts/WorkbenchGame/EnfusionMCP/EMCP_WB_Layers.c": "93f88fa2618d00a6ea364693830bf84249e8f116a26c99443e7177a364ff2e9d",
|
||||
"reforger-statistics/Scripts/WorkbenchGame/EnfusionMCP/EMCP_WB_ListEntities.c": "c01d16c58ecc5e6eba5e9ed9ee8ec197f90ea1d6d9783267f4744694f8b2498c",
|
||||
"reforger-statistics/Scripts/WorkbenchGame/EnfusionMCP/EMCP_WB_Localization.c": "43c2bc3718df7047147c2190c586308a2e45de74375e2bebcf419dc3bfe1f0f3",
|
||||
"reforger-statistics/Scripts/WorkbenchGame/EnfusionMCP/EMCP_WB_ModifyEntity.c": "f01a3442a19a45fb2032e2177b0c7c2dd5b4cb32bc219685a047ed5b0ce0b74d",
|
||||
"reforger-statistics/Scripts/WorkbenchGame/EnfusionMCP/EMCP_WB_Ping.c": "f7fd1e089315a2f7c52d05dfd479754569666872ef9301e9569689dee7ce72b2",
|
||||
"reforger-statistics/Scripts/WorkbenchGame/EnfusionMCP/EMCP_WB_Prefabs.c": "eac3e032494512809671341d666ef125eb3a5dfedae654867db91c9fa72b5eb8",
|
||||
"reforger-statistics/Scripts/WorkbenchGame/EnfusionMCP/EMCP_WB_Reload.c": "26fcc69b68680c8a749d4d0830dc89411b482e66875a235693aa6de1978e15c1",
|
||||
"reforger-statistics/Scripts/WorkbenchGame/EnfusionMCP/EMCP_WB_Resources.c": "0a51834fe3dbd92aaa12fe3c4196ccc7756284dd3f6d0338f35311918dc41ffc",
|
||||
"reforger-statistics/Scripts/WorkbenchGame/EnfusionMCP/EMCP_WB_ScriptEditor.c": "0b1ad81f2ec305bb69d3079a08d03765e149e62eef1c6ba5c34b055eb47aa7a0",
|
||||
"reforger-statistics/Scripts/WorkbenchGame/EnfusionMCP/EMCP_WB_SelectEntity.c": "028e4ec21667a5fe1d8437709c81afc0f55beb33f621db930d4cfea893cd1a8a",
|
||||
"reforger-statistics/Scripts/WorkbenchGame/EnfusionMCP/EMCP_WB_Terrain.c": "e553fb2fdfa1285c208a731a2a8fa443df5990dfa763c5225bdd50cc79e4bdf6",
|
||||
"reforger-statistics/Tools/EnfusionMapMaker/Enfusion/Scripts/WorkbenchGame/EnfusionMapMaker/AutoCameraScreenshotWorldEditorTool.c": "b032182dc79490f236f34cf72e1acf7388fa73bb1ef75216af49869b6c8bcf79",
|
||||
"reforger-statistics/Tools/EnfusionMapMaker/Enfusion/Scripts/WorkbenchGame/EnfusionMapMaker/ResourceQueryWorldEditorTool.c": "8b126c6b5aa793061164cdb8b41239f6e08c16188ff73634637170c6622cd1db",
|
||||
"reforger-statistics/Tools/EnfusionMapMaker/Enfusion/addon.gproj": "98a71462d0dd07fe5fb8c1a1c6d641dbb5359ffd7b63faee6114112e3887100f",
|
||||
"reforger-statistics/Tools/EnfusionMapMaker/README.md": "fdfc5a33d9b052354964eb59fa41a62ead5c1d6edd2c98e352c2671d754c4ecc",
|
||||
"reforger-statistics/Tools/EnfusionMapMaker/Scripts/create_zoom_levels.py": "7918876af71452d9a6c256ea8fa151fe392bf57de35779a666adf71b116b5826",
|
||||
"reforger-statistics/Tools/EnfusionMapMaker/Scripts/crop_screenshots.py": "56ef111f2b563b62ec59f0aec207cdf52b4b7e1342419c33da58fce7f58d7948",
|
||||
"reforger-statistics/Tools/EnfusionMapMaker/UPSTREAM.md": "acf26612dad9e95d7ae2fcb9d1651a6865f6b14d4e9ee4d3de1f2cb3eb8b94d0",
|
||||
"reforger-statistics/Tools/import_map_tiles.py": "b2b72c102fe6604c9bf9cf359d5dcc65c227eb214fd1af375017887bae829b06",
|
||||
"reforger-statistics/Tools/x11ctl.py": "cca150c5cd9e711273df2ad98a6ffdf0a18de29839c14e938f9887865874df32",
|
||||
"reforger-statistics/Workshop/IMAGE_SOURCE.md": "754525d21c54f4d83ee7ac386373f0ca9382c8b8a672151e298cf687644f0179",
|
||||
"reforger-statistics/Workshop/LISTING.md": "ad45525219f08863ffdb93141c286fdea324806bb3d88b3dfe13de454f42b236",
|
||||
"reforger-statistics/addon.gproj": "852939fe636606e19515b9b1b94ed61982bcb1c0cc9bd0b6fd53bbe26c594871",
|
||||
"reforger-statistics/analysis/2026-07-30-captured-events.md": "c2bf50544fd345d839a74ba5909984e69747e3b5fb71ad4894691c7027e4149b",
|
||||
"reforger-statistics/build/MissionNightGear/addon.gproj": "30006449a8336ab5dfee4ffd7abbce3202ff75a32b40cea23cdfb5fdcf060bf6",
|
||||
"reforger-statistics/build/ReforgerStatistics/addon.gproj": "852939fe636606e19515b9b1b94ed61982bcb1c0cc9bd0b6fd53bbe26c594871",
|
||||
"reforger-statistics/data/README.md": "401f37e81fa6379480d051579edf2be16ce0681cecd076a4f656d3d667b10676",
|
||||
"reforger-statistics/receiver/maps.py": "07d90dc3659ec6500193e62b35366be456c8c12589c9204435fd249c0b135d01",
|
||||
"reforger-statistics/receiver/server.py": "d36ee5eeab78a426568d5d15720c057dff87b73fb8a048c4cd01c6384cfb597c",
|
||||
"reforger-statistics/tests/map_regression.py": "6d9162745726e84c80f3c427447819607447762207b1ab2f2c62773ecf7ffc8e",
|
||||
"reforger-statistics/tests/statistics_upload_regression.py": "cff3a9d699e8a869ba3e135a818a210d8c31a7b5445ba2fa8b3d02c3ac604470",
|
||||
"tools/check.py": "1b5a97c644599f444612bced0f72daf3feb9adc84f311db883f5348fb789037c"
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
{
|
||||
"complete": true,
|
||||
"scope": "Configuration and finite supply recovery plus bounded resource audit correction; no new native qualification or package change",
|
||||
"suite": {
|
||||
"exit": 0,
|
||||
"inputs_unchanged": true,
|
||||
"regression_programs": 305,
|
||||
"suite_inputs_sha256": "d4ddadb4624be964249ed736bb33bf03d7df796f9ff1493cb575cc6b8e92d77d",
|
||||
"suite_result_sha256": "0e65713b176ce28a334d8c4f860436205fe584f169752b4295526809d78a329f"
|
||||
},
|
||||
"integration_sha256": "60e8910288a739e572c65e32cc32bbeab2f7de0b8e9ad484f0efa993f467f08c",
|
||||
"proposals": {
|
||||
"config": {
|
||||
"manifest_sha256": "2fd845ee6bd744e8c405f7e9dc40562df2a82cb2ff215cf0df7db481b85e735f",
|
||||
"patch_sha256": "9ddefab1f87ef5d0924e096d51359482e43de9b250c7986c98360c97d432104d",
|
||||
"files": {
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ProfileConfig.c": "9df8ccf45fc2ed12f4b14d08270878696e8785760a3ae51fe032b6f3818fc0e6",
|
||||
"tests/test_profile_config.py": "727dc330db23d744fca0c965474f834d0cb70432e58938f286fde28bd8415435"
|
||||
}
|
||||
},
|
||||
"supply": {
|
||||
"manifest_sha256": "7d98965a23809a0dc4999a762c6dd8240f37cfc68290035fb884ab07744e33ea",
|
||||
"patch_sha256": "ece65980fbe99627d6984e3d964a4aa30d6d80bcc44939245c49644e0225bb6a",
|
||||
"files": {
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c": "ca8eee2704e7758172e33014404bb1307c683f19b561b840d4592f6312051e62",
|
||||
"tests/test_infantry_resupply_planning.py": "9879a27816dbc6b9c4da19c4714407614b4c6e20b2dd831b2701e5f3500ede6a",
|
||||
"tests/test_infantry_resupply_coordinator.py": "a7eaa26e21f587fd8abde5dee6f7f8afc1e9f2f7ed0bcf40ed6a087a56908adc",
|
||||
"tests/test_infantry_ammo_transfer.py": "18029a092262d0d1a309108a158597a174c1a05f58157eafd096c1c707fa0e29"
|
||||
}
|
||||
},
|
||||
"optional-identity": {
|
||||
"manifest_sha256": "fdb25d5b1bdefc114291475dc9b68a195a3aadc55e8c7b662fc2d5a913b2b2e3",
|
||||
"patch_sha256": "d02ed79ad88f21138e66a77189bbaf7130cf1e36331f47f1c3b5db026a1953c1",
|
||||
"files": {
|
||||
"tools/resource_references.py": "2e6080227bece7213fd67e58e7a4d27aba9847e610f8c000f6f2f65b623e567c",
|
||||
"tools/check.py": "fb6bf594dd6544abee60d4e172d1d28f34f223cae93678e2356156f34e653f00",
|
||||
"tools/source_bundle.py": "5d1d0150d8009f24a950ee85501d0da8b1f69d5fcbb5a7118b08957f14658f57",
|
||||
"tests/test_external_addons.py": "4b0eb867b3aec1bca906f68168948a4e42cdc0bced0bec2856a3ba68187a6e24",
|
||||
"docs/vanilla-resources.json": "e10f60ce74a743b4619b0c2f2cc7fefcf09a94ab3ca1cbb332f386d6fb0da387"
|
||||
}
|
||||
}
|
||||
},
|
||||
"preservation": {
|
||||
"baseline_paths": 996,
|
||||
"inherited_unchanged_except_integrated": true,
|
||||
"index_sha256": "670073db5d7531aca4466cc9d2827d10a46bfcfbd35f27ac97724de9d2fd3725",
|
||||
"original_files": 533,
|
||||
"original_manifest_sha256": "661c5ddf080c4ba8d4463aa4907f739d4d96acaa8694ac8d6f3d85bb94231226",
|
||||
"original_unchanged": true,
|
||||
"sealed_candidates": [
|
||||
{
|
||||
"candidate": "/home/jakub/devel/escapistsrereintroduced/.build/playtest-2026-10-03-mounted-pair",
|
||||
"files": 429,
|
||||
"manifest_sha256": "9fee715f8c9c324c465387ba1f88744c9c3748cb49668ce65e9c9500a38b14d7",
|
||||
"unchanged": true
|
||||
},
|
||||
{
|
||||
"candidate": "/home/jakub/devel/escapistsrereintroduced/.build/playtest-2026-10-03-mine-safety",
|
||||
"files": 431,
|
||||
"manifest_sha256": "202fa0854cf60a6c08ace1f22b276d826abcb538c79b6e052b48e5e51f458a87",
|
||||
"unchanged": true
|
||||
},
|
||||
{
|
||||
"candidate": "/home/jakub/devel/escapistsrereintroduced/.build/playtest-2026-10-03-ground-supply",
|
||||
"files": 432,
|
||||
"manifest_sha256": "0b58fde4127486894917db58ce92b684f984233b341317418e336b1740cac107",
|
||||
"unchanged": true
|
||||
},
|
||||
{
|
||||
"candidate": "/home/jakub/devel/escapistsrereintroduced/.build/playtest-2026-10-03-depot-mines",
|
||||
"files": 432,
|
||||
"manifest_sha256": "c91acda173e2914fea59fd3e264a451158ee21d85918fe1ec5c8312dd46f7074",
|
||||
"unchanged": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"native": {
|
||||
"native_check_started": false,
|
||||
"reason": "Read-only host preflight found an existing Arma Reforger game (PID1451030); left untouched. No launch, window, input, audio or process changes.",
|
||||
"compile_or_gameplay_proof": false,
|
||||
"prefix_process_check": "clear"
|
||||
},
|
||||
"retained_initial_suite_failure": {
|
||||
"exit": 1,
|
||||
"regression_programs": 20,
|
||||
"suite_result_sha256": "47ba24ecb4524a253ff37aaab6273ec866d7f255cd158b0db9fd566f8c060b27"
|
||||
},
|
||||
"archive_files": {
|
||||
"base-gameplay-review.json": "70d6efba95e2f5c15389cebf3c95b16b50e45e2e94d5260fe5ff7531c75cbdda",
|
||||
"config/apply-check.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
"config/baseline-red.log": "a51853e6c0004c0c17b932fb4b2d201d7618648fe1ba6f802c31011228f3c404",
|
||||
"config/baseline/addons/core/Scripts/Game/ERR/00_Core/ERR_ProfileConfig.c": "ac28363fd5861523db278bb18aa5499f356fef69d35435d1f4ef547da704b67d",
|
||||
"config/baseline/tests/test_profile_config.py": "088ea06a32a59711d8e02c426d5fdd4a14657cded725b831af312bd8eb5f133f",
|
||||
"config/build-test.py": "0e16f59444f0bd9b16a6f5a53fc36bfd6136e2060a4d7f96ad24be31813ee783",
|
||||
"config/finding.json": "b06cf00382b3dd855cdf0c10c433932e9b1ad1d38d9ba296d0f91596b397c4b5",
|
||||
"config/fix.patch": "9ddefab1f87ef5d0924e096d51359482e43de9b250c7986c98360c97d432104d",
|
||||
"config/independent-review.json": "52e31b6e43dd37a2a797ecb980f7f8064d48de5231afa66d031f018fd7662371",
|
||||
"config/previous-validation-red.log": "0f8438d6a2ad9c46e8372fc1ad3f4e2c01d07179c3bc19d1279de1066ae42ae9",
|
||||
"config/proposal-green.log": "1c414380eb465210146fed3d49b2108f593abd625b6ffb92f50e7f27131de6f0",
|
||||
"config/proposed/addons/core/Scripts/Game/ERR/00_Core/ERR_ProfileConfig.c": "9df8ccf45fc2ed12f4b14d08270878696e8785760a3ae51fe032b6f3818fc0e6",
|
||||
"config/proposed/tests/test_profile_config.py": "727dc330db23d744fca0c965474f834d0cb70432e58938f286fde28bd8415435",
|
||||
"config/source-manifest.json": "2fd845ee6bd744e8c405f7e9dc40562df2a82cb2ff215cf0df7db481b85e735f",
|
||||
"config/test-results.json": "20af613fa5168dc7e93734b4ce1b0f5ef771946bc310e802b58e93dee09f89cd",
|
||||
"optional-identity/apply-check.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
"optional-identity/baseline-bundle-red.log": "5a326f80f5671a5c56f5f5ba6880942fcd83821675a0f8454ee860541d4e8f52",
|
||||
"optional-identity/baseline-scanner-red.log": "e18a68ba778b467108eeba569dd0d924abfbdad365e7bc482708bb243b8a2943",
|
||||
"optional-identity/baseline/docs/vanilla-resources.json": "588192d151f382b612ca6ce9a564193b57d4a9e7ce9a3918bf8ad2f7e877d1f4",
|
||||
"optional-identity/baseline/tests/test_external_addons.py": "4e2c3fa2c92661c49ea0c492648b736bebd54f24cd244f3fe27710a0c7a487ab",
|
||||
"optional-identity/baseline/tools/check.py": "d60357b1c6b0d61dfeb80148d4a6684121e468bd3a044a9adc8f76752f60a41a",
|
||||
"optional-identity/baseline/tools/source_bundle.py": "e8b06f9340a8d67da992373f4642385a028acebe9aa1b3752f62cab95c8fce98",
|
||||
"optional-identity/finding.json": "0db9e9ba31079f7fc7ea7bb199976c00570cc625ed048ad6ba2f76f6bed27efb",
|
||||
"optional-identity/fix.patch": "d02ed79ad88f21138e66a77189bbaf7130cf1e36331f47f1c3b5db026a1953c1",
|
||||
"optional-identity/independent-review.json": "6c3e08c39f1ab4b082e71d69d3420950879c97913595a61471ee32a0a7e5ebb7",
|
||||
"optional-identity/optional-identity-audit.json": "87581b0c0c210e76dfdb9f5285417fed0fa164a58897a0012f964e795236275b",
|
||||
"optional-identity/prepare-test.py": "8d38dab2a814c952918d55e651d5ef1031123f85b017799e56aa94621ab14ef4",
|
||||
"optional-identity/proposal-green.log": "dec02332cb628dd7b75eff0af6e7a6c0f2f5ccab482b8d20b76bf97dcdc62468",
|
||||
"optional-identity/proposal-initial-missing-vanilla.log": "0950195851664e3296729d14adaa159459b95adf7905537b18be74ff52f4009e",
|
||||
"optional-identity/proposed/docs/vanilla-resources.json": "e10f60ce74a743b4619b0c2f2cc7fefcf09a94ab3ca1cbb332f386d6fb0da387",
|
||||
"optional-identity/proposed/tests/test_external_addons.py": "4b0eb867b3aec1bca906f68168948a4e42cdc0bced0bec2856a3ba68187a6e24",
|
||||
"optional-identity/proposed/tools/check.py": "fb6bf594dd6544abee60d4e172d1d28f34f223cae93678e2356156f34e653f00",
|
||||
"optional-identity/proposed/tools/resource_references.py": "2e6080227bece7213fd67e58e7a4d27aba9847e610f8c000f6f2f65b623e567c",
|
||||
"optional-identity/proposed/tools/source_bundle.py": "5d1d0150d8009f24a950ee85501d0da8b1f69d5fcbb5a7118b08957f14658f57",
|
||||
"optional-identity/source-manifest.json": "fdb25d5b1bdefc114291475dc9b68a195a3aadc55e8c7b662fc2d5a913b2b2e3",
|
||||
"optional-identity/test-results.json": "a3c9e916289b106bd0c3befbf7c675ea8f08579359b7d074538e787705aa063d",
|
||||
"optional-identity/test-source-inputs.json": "1fcc9536c2fcbdd332cb62ba01a02bdc190f5fc6bbc8975f5abf2c94f6811c06",
|
||||
"optional-identity/vanilla-character-audit.json": "625379d9757e265e4947b822df0b64548b4b36613c55ada811663fba2ede871c",
|
||||
"optional-identity/vanilla-identity-proof.json": "ac34caa4dcdc2ef734d6013da57838526468340d684acce8c1ad7a0469282d02",
|
||||
"preservation/depot-mines-candidate-sha256.json": "c91acda173e2914fea59fd3e264a451158ee21d85918fe1ec5c8312dd46f7074",
|
||||
"preservation/ground-supply-candidate-sha256.json": "0b58fde4127486894917db58ce92b684f984233b341317418e336b1740cac107",
|
||||
"preservation/mine-safety-candidate-sha256.json": "202fa0854cf60a6c08ace1f22b276d826abcb538c79b6e052b48e5e51f458a87",
|
||||
"preservation/mounted-pair-candidate-sha256.json": "9fee715f8c9c324c465387ba1f88744c9c3748cb49668ce65e9c9500a38b14d7",
|
||||
"preservation/original-reference.json": "661c5ddf080c4ba8d4463aa4907f739d4d96acaa8694ac8d6f3d85bb94231226",
|
||||
"root/baseline.json": "b754fa12b42d106b63831e900ccc2f6ad828406e364991112acb20094b439e09",
|
||||
"root/final-review.json": "92c25e3264133bc5d948c306bbe18fa465c441f97eb6996159433777cc1385bf",
|
||||
"root/first-suite-failure/full-suite.log": "39ba40807787077d5ac76006ca565dad8a1bb681f9f115c3cc5dc8afa531f944",
|
||||
"root/first-suite-failure/suite-inputs.json": "6d7e74d97cd0955d700b9d09d7f14828da6c71dcc9d67febda4dd2a6be7d0c70",
|
||||
"root/first-suite-failure/suite-result.json": "47ba24ecb4524a253ff37aaab6273ec866d7f255cd158b0db9fd566f8c060b27",
|
||||
"root/full-suite.log": "c304c3d5bba1b1664782d7bac90881c1859a75d263587fcc9182d1d746251a5c",
|
||||
"root/integrate.py": "047c5994de86fc4babe4d9937c5facebc1e8b8312c7e0c9195e3a92010e3d1eb",
|
||||
"root/integration.json": "60e8910288a739e572c65e32cc32bbeab2f7de0b8e9ad484f0efa993f467f08c",
|
||||
"root/native-deferred.json": "5f755cf077e7d1c8ae4efad2e69048bc6ebef44399a3d7af7329f02343d75367",
|
||||
"root/optional-identity-audit.json": "87581b0c0c210e76dfdb9f5285417fed0fa164a58897a0012f964e795236275b",
|
||||
"root/run-suite.py": "8ce92c56b5553d2a26fee220578e02d39a18a541bdc5f9d6dc19262ae4918fb5",
|
||||
"root/suite-inputs.json": "d4ddadb4624be964249ed736bb33bf03d7df796f9ff1493cb575cc6b8e92d77d",
|
||||
"root/suite-result.json": "0e65713b176ce28a334d8c4f860436205fe584f169752b4295526809d78a329f",
|
||||
"root/vanilla-character-audit.json": "625379d9757e265e4947b822df0b64548b4b36613c55ada811663fba2ede871c",
|
||||
"supply/apply-check.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
"supply/baseline-test_infantry_resupply_planning.log": "bf89459dc00b4db4c351933d382c400b1736f885a69443856fdd630175b742ff",
|
||||
"supply/baseline.json": "d053779f016057f2d89b18321a9a64159019885cb5eb21bf7e68309624cfcbd5",
|
||||
"supply/baseline/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c": "1bfc1079961eaecee0c1ebb434570aaeb359c008f9f309033b33582092557b35",
|
||||
"supply/baseline/tests/test_infantry_ammo_transfer.py": "0d2ebe4d5c18a4187745784013d07df621b8495967d0c01f39bd5a68ae574d26",
|
||||
"supply/baseline/tests/test_infantry_resupply_coordinator.py": "f9cf7d583a25a12cec9f5f80539b2590449560331f4ef34e33ea2db283c5d54a",
|
||||
"supply/baseline/tests/test_infantry_resupply_planning.py": "20747ffda8754f81f3b9e9912b9f60a300c439f2ea2c473bb900302f61dd691f",
|
||||
"supply/finding.json": "7a573f29c1c6c1d66ab9cce77263db84a6adae930153da3861354994f66d318d",
|
||||
"supply/fix.patch": "ece65980fbe99627d6984e3d964a4aa30d6d80bcc44939245c49644e0225bb6a",
|
||||
"supply/independent-review.json": "1fbfdfd38b6e9ba0591cfe9557e0dd4c72f74f6d6094253dd66323bf537223b0",
|
||||
"supply/prepare.py": "14e636685a8b1ab125350e35eaa6417ceab9b3a60b002ba338ce25a9f5f61b96",
|
||||
"supply/proposal-test_infantry_ammo_transfer.log": "27d49fc10aa8a5f150cdae91a192788fe84cb01b5998760ad6aba83d3c44d469",
|
||||
"supply/proposal-test_infantry_resupply_coordinator.log": "956e431f178f472436c3abd25fcd34bfd6309ae1446335c9fbc23229428bc7cd",
|
||||
"supply/proposal-test_infantry_resupply_planning.log": "c12aa5ba9b2141830d3916c3ab0285c06cbb44f606a9f8fbe42787ade0e67b21",
|
||||
"supply/proposed/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c": "ca8eee2704e7758172e33014404bb1307c683f19b561b840d4592f6312051e62",
|
||||
"supply/proposed/tests/test_infantry_ammo_transfer.py": "18029a092262d0d1a309108a158597a174c1a05f58157eafd096c1c707fa0e29",
|
||||
"supply/proposed/tests/test_infantry_resupply_coordinator.py": "a7eaa26e21f587fd8abde5dee6f7f8afc1e9f2f7ed0bcf40ed6a087a56908adc",
|
||||
"supply/proposed/tests/test_infantry_resupply_planning.py": "9879a27816dbc6b9c4da19c4714407614b4c6e20b2dd831b2701e5f3500ede6a",
|
||||
"supply/source-manifest.json": "7d98965a23809a0dc4999a762c6dd8240f37cfc68290035fb884ab07744e33ea",
|
||||
"supply/test-results.json": "c68108d773de900e6d559fd8f63829b8bdb2084a3e885820a67aae89d3b7bed9"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Preview by default; --apply creates only this turn's new evidence archive.
|
||||
Run after successful bound suite and before separate documentation edits.
|
||||
No native launch, test execution, package rewrite or third-party payload copy.
|
||||
"""
|
||||
from pathlib import Path
|
||||
import argparse,hashlib,json,subprocess,sys,shutil,tempfile
|
||||
ROOT=Path('/home/jakub/devel/escapistsrereintroduced')
|
||||
WORK=Path('/tmp/erri-gameplay-root-1509')
|
||||
DEST=ROOT/'docs/evidence/config-supply-recovery-2026-10-03'
|
||||
PROPOSALS={'config':Path('/tmp/erri-config-review-1509'),'supply':Path('/tmp/erri-ai-review-1509'),'optional-identity':Path('/tmp/erri-optional-identity-1509')}
|
||||
ORIGINAL=Path('/home/jakub/devel/escapists')
|
||||
REFERENCE=Path('/tmp/erri-heartbeat-20260930-1542-reference.json')
|
||||
def sha(p):
|
||||
return hashlib.file_digest(p.open('rb'),'sha256').hexdigest()
|
||||
def load(p):return json.loads(p.read_text())
|
||||
def require(ok,why):
|
||||
if not ok:raise RuntimeError(why)
|
||||
def capture_inputs():
|
||||
sys.path.insert(0,str(ROOT/'tools'))
|
||||
from source_manifest import addon_manifest
|
||||
result=addon_manifest(ROOT)
|
||||
for folder in ['tests','tools','terrain-profiles','terrain-adapters','terrain-integrations']:
|
||||
result.update({str(p.relative_to(ROOT)):sha(p) for p in (ROOT/folder).rglob('*') if p.is_file() and '__pycache__' not in p.parts and p.suffix!='.pyc'})
|
||||
result.update({str(p.relative_to(ROOT)):sha(p) for p in (ROOT/'docs').iterdir() if p.is_file()})
|
||||
for name in ['README.md','.gitignore']:result[name]=sha(ROOT/name)
|
||||
return result
|
||||
|
||||
def seal_archive():
|
||||
inventory={str(p.relative_to(DEST)):sha(p) for p in DEST.rglob('*') if p.is_file() and p.name!='artifact-sha256.json'}
|
||||
(DEST/'artifact-sha256.json').write_text(json.dumps(inventory,indent=2)+'\n')
|
||||
def finalize():
|
||||
require(DEST.is_dir(),'Archive must exist before documentation finalization')
|
||||
seal_before=load(DEST/'artifact-sha256.json')
|
||||
require({str(p.relative_to(DEST)):sha(p) for p in DEST.rglob('*') if p.is_file() and p.name!='artifact-sha256.json'}==seal_before,'Archive changed before final seal')
|
||||
changes=load(WORK/'post-suite-docs.json');inputs=load(WORK/'suite-inputs.json')
|
||||
require(set(changes)=={'docs/current-status.md','docs/configuration.md','docs/infantry-resupply.md'},'Unexpected post-suite document scope')
|
||||
expected=dict(inputs)
|
||||
for name,values in changes.items():
|
||||
require(inputs[name]==values['before'] and sha(ROOT/name)==values['after'],'Post-suite document binding mismatch '+name)
|
||||
expected[name]=values['after']
|
||||
require(capture_inputs()==expected,'Unreviewed post-suite input changes')
|
||||
baseline=load(WORK/'baseline.json');integrated=load(WORK/'integration.json')
|
||||
for name,digest in baseline['files'].items():
|
||||
expected_hash=changes.get(name,{}).get('after',integrated.get(name,{}).get('after',digest))
|
||||
require((ROOT/name).is_file() and sha(ROOT/name)==expected_hash,'Inherited path changed after docs '+name)
|
||||
index=hashlib.sha256(subprocess.check_output(['git','diff','--cached','--binary'],cwd=ROOT)).hexdigest()
|
||||
require(index==baseline['index_sha256'],'Index changed after docs')
|
||||
original=load(REFERENCE);require(len(original)==533 and all(sha(ORIGINAL/n)==v for n,v in original.items()),'Original changed after docs')
|
||||
for label in ['mounted-pair','mine-safety','ground-supply','depot-mines']:
|
||||
candidate=ROOT/f'.build/playtest-2026-10-03-{label}'
|
||||
require({str(p.relative_to(candidate)):sha(p) for p in candidate.rglob('*') if p.is_file()}==load(DEST/f'preservation/{label}-candidate-sha256.json'),'Candidate changed after docs '+label)
|
||||
for name in ['post-suite-docs.json','update-docs.py']:
|
||||
require(not (DEST/'root'/name).exists(),'Already finalized '+name)
|
||||
shutil.copyfile(WORK/name,DEST/'root'/name)
|
||||
(DEST/'finalization.json').write_text(json.dumps({'complete':True,'post_suite_document_changes':changes,'source_tests_tools_unchanged':True,'fresh_suite_after_prose_changes_claimed':False,'index_unchanged':True,'original533_unchanged':True,'four_sealed_candidates_unchanged':True},indent=2)+'\n')
|
||||
seal_archive();print('Final document delta archived and evidence resealed')
|
||||
def main():
|
||||
parser=argparse.ArgumentParser(description=__doc__);group=parser.add_mutually_exclusive_group();group.add_argument('--apply',action='store_true');group.add_argument('--finalize',action='store_true');args=parser.parse_args()
|
||||
if args.finalize:return finalize()
|
||||
require(not DEST.exists(),'Refusing existing evidence archive')
|
||||
baseline=load(WORK/'baseline.json');integrated=load(WORK/'integration.json');suite=load(WORK/'suite-result.json');inputs=load(WORK/'suite-inputs.json')
|
||||
require(suite['exit']==0 and suite['inputs_unchanged'] is True,'Full unchanged-input suite required')
|
||||
programs=suite['programs'];require(programs and len(programs)==suite['regression_programs'] and all(p['exit']==0 for p in programs),'Incomplete/failed registered test list')
|
||||
require(capture_inputs()==inputs,'Current suite inputs differ; do not archive as current pass')
|
||||
for name,item in integrated.items():
|
||||
require(sha(ROOT/name)==item['after']==inputs[name],'Integrated source/test binding differs: '+name)
|
||||
for name,digest in baseline['files'].items():
|
||||
expected=integrated.get(name,{}).get('after',digest)
|
||||
require((ROOT/name).is_file() and sha(ROOT/name)==expected,'Unreviewed inherited change: '+name)
|
||||
index=hashlib.sha256(subprocess.check_output(['git','diff','--cached','--binary'],cwd=ROOT)).hexdigest()
|
||||
require(index==baseline['index_sha256'],'Index changed')
|
||||
original=load(REFERENCE);require(len(original)==533,'Unexpected original reference scope')
|
||||
require(all((ORIGINAL/name).is_file() and sha(ORIGINAL/name)==digest for name,digest in original.items()),'Original reference changed')
|
||||
# Only manifests are archived; sealed source/ZIP/PAK/runtime payloads stay in place.
|
||||
candidates=[];copies={}
|
||||
for label in ['mounted-pair','mine-safety','ground-supply','depot-mines']:
|
||||
sealpath=ROOT/f'docs/evidence/playtest-refresh-2026-10-03-{label}/candidate-sha256.json'
|
||||
seal=load(sealpath);candidate=ROOT/f'.build/playtest-2026-10-03-{label}'
|
||||
actual={str(p.relative_to(candidate)):sha(p) for p in candidate.rglob('*') if p.is_file()}
|
||||
require(actual==seal,'Sealed candidate changed: '+label)
|
||||
copies[f'preservation/{label}-candidate-sha256.json']=sealpath
|
||||
candidates.append({'candidate':str(candidate),'files':len(seal),'manifest_sha256':sha(sealpath),'unchanged':True})
|
||||
copies['preservation/original-reference.json']=REFERENCE
|
||||
base_review=Path('/tmp/erri-base-review-1509/finding.json');require(base_review.is_file(),'Missing bounded base review');copies['base-gameplay-review.json']=base_review
|
||||
root_required=['baseline.json','integration.json','suite-inputs.json','suite-result.json','full-suite.log','run-suite.py','native-deferred.json','optional-identity-audit.json','vanilla-character-audit.json']
|
||||
for name in root_required:
|
||||
require((WORK/name).is_file(),'Missing root evidence '+name);copies['root/'+name]=WORK/name
|
||||
for name in ['integrate.py','host-idle-inspection.json','preflight.json','review.json','final-review.json']:
|
||||
if (WORK/name).is_file():copies['root/'+name]=WORK/name
|
||||
failed=load(WORK/'first-suite-failure/suite-result.json')
|
||||
require(failed['exit']!=0,'Retained initial suite failure must remain a failure')
|
||||
for name in ['full-suite.log','suite-inputs.json','suite-result.json']:
|
||||
path=WORK/'first-suite-failure'/name
|
||||
require(path.is_file() and not path.is_symlink(),'Missing original suite failure '+name)
|
||||
copies['root/first-suite-failure/'+name]=path
|
||||
proposal_bindings={}
|
||||
# Explicit owned artifacts only. No recursive scratch copy or installed resources.
|
||||
optional=['baseline.json','finding.json','report.json','result.json','test-results.json','independent-review.json','review.json','apply-check.log','baseline-red.log','proposal-green.log','previous-validation-red.log','red.log','green.log','mutation-red.log','baseline-test.log','proposed-test.log','prepare.py','build-test.py','prepare-test.py','optional-identity-audit.json','vanilla-character-audit.json','vanilla-identity-proof.json','test-source-inputs.json']
|
||||
for label,folder in PROPOSALS.items():
|
||||
manifest_path=folder/'source-manifest.json';manifest=load(manifest_path)
|
||||
copies[label+'/source-manifest.json']=manifest_path
|
||||
patch=folder/'fix.patch';require(patch.is_file(),'Missing patch '+label);copies[label+'/fix.patch']=patch
|
||||
if 'patch_sha256' in manifest:require(sha(patch)==manifest['patch_sha256'],'Patch changed '+label)
|
||||
files=manifest.get('files',manifest);selected={}
|
||||
for name,item in files.items():
|
||||
if not isinstance(item,dict):continue
|
||||
digest=item.get('proposal_sha256',item.get('proposed'))
|
||||
if not digest:continue
|
||||
allowed=name.startswith(('addons/core/Scripts/Game/ERR/','tests/'))
|
||||
if label=='optional-identity':allowed=name in {'tools/resource_references.py','tools/check.py','tools/source_bundle.py','tests/test_external_addons.py','docs/vanilla-resources.json'}
|
||||
require(allowed and '..' not in Path(name).parts,'Unexpected proposal scope '+name)
|
||||
require(name in integrated and integrated[name]['after']==digest and sha(folder/name)==digest,'Unbound proposal '+name)
|
||||
copies[label+'/proposed/'+name]=folder/name;selected[name]=digest
|
||||
base=folder/'baseline'/name
|
||||
if base.is_file():
|
||||
expected=item.get('baseline_sha256',item.get('before_working',item.get('before')))
|
||||
require(expected and sha(base)==expected,'Proposal baseline mismatch '+name);copies[label+'/baseline/'+name]=base
|
||||
require(selected,'Empty proposal '+label)
|
||||
require((folder/'independent-review.json').is_file(),'Independent review required '+label)
|
||||
independent=load(folder/'independent-review.json')
|
||||
require(independent.get('approved') is True and independent['patch_sha256']==sha(patch) and independent['source_manifest_sha256']==sha(manifest_path),'Independent review binding differs '+label)
|
||||
for name,digest in manifest.get('artifacts',{}).items():
|
||||
require(Path(name).name==name and sha(folder/name)==digest,'Manifest artifact differs '+label+'/'+name)
|
||||
if label=='optional-identity':
|
||||
for name in ['optional-identity-audit.json','vanilla-character-audit.json']:
|
||||
require(sha(folder/name)==manifest[name+'_sha256']==sha(WORK/name),'Audit evidence differs '+name)
|
||||
audited=manifest['audited_source']
|
||||
require(audited['modified'] is False and sha(ROOT/audited['path'])==audited['sha256'],'Optional audited source changed')
|
||||
if 'test_results_sha256' in manifest:require(sha(folder/'test-results.json')==manifest['test_results_sha256'],'Test result binding differs '+label)
|
||||
for name in optional:
|
||||
if (folder/name).is_file():copies[label+'/'+name]=folder/name
|
||||
for log in folder.glob('*.log'):
|
||||
require(log.is_file() and not log.is_symlink(),'Unexpected log link '+str(log))
|
||||
copies[label+'/'+log.name]=log
|
||||
proposal_bindings[label]={'manifest_sha256':sha(manifest_path),'patch_sha256':sha(patch),'files':selected}
|
||||
deferred=load(WORK/'native-deferred.json');require(deferred['native_check_started'] is False,'Unexpected native scope')
|
||||
report={'complete':True,'scope':'Configuration and finite supply recovery plus bounded resource audit correction; no new native qualification or package change','suite':{'exit':0,'inputs_unchanged':True,'regression_programs':len(programs),'suite_inputs_sha256':sha(WORK/'suite-inputs.json'),'suite_result_sha256':sha(WORK/'suite-result.json')},'integration_sha256':sha(WORK/'integration.json'),'proposals':proposal_bindings,'preservation':{'baseline_paths':len(baseline['files']),'inherited_unchanged_except_integrated':True,'index_sha256':index,'original_files':533,'original_manifest_sha256':sha(REFERENCE),'original_unchanged':True,'sealed_candidates':candidates},'native':deferred,'retained_initial_suite_failure':{'exit':failed['exit'],'regression_programs':failed['regression_programs'],'suite_result_sha256':sha(WORK/'first-suite-failure/suite-result.json')},'archive_files':{name:sha(path) for name,path in sorted(copies.items())}}
|
||||
print(json.dumps({'ready':True,'destination':str(DEST),'files':len(copies),'programs':len(programs),'apply':args.apply},indent=2))
|
||||
if not args.apply:return
|
||||
# All binding/preservation checks finish before the first destination mutation.
|
||||
DEST.parent.mkdir(parents=True,exist_ok=True)
|
||||
staging=Path(tempfile.mkdtemp(prefix='.config-supply-recovery-',dir=DEST.parent))
|
||||
try:
|
||||
for name,path in copies.items():
|
||||
out=staging/name;out.parent.mkdir(parents=True,exist_ok=True);shutil.copyfile(path,out)
|
||||
require(sha(out)==report['archive_files'][name],'Copy verification failed '+name)
|
||||
(staging/'review.json').write_text(json.dumps(report,indent=2)+'\n')
|
||||
shutil.copyfile(Path(__file__),staging/'archive.py')
|
||||
(staging/'README.md').write_text('# Configuration and supply recovery — 3 October 2026\n\n'
|
||||
'Malformed recognized configuration sections now prevent unrelated saves from replacing the only valid backup. Ordinary rifle resupply retains exact claims while its existing native transfer remains unresolved.\n\n'
|
||||
+str(len(programs))+' registered regression programs passed with unchanged captured inputs. Focused baseline failures and corrected-method controls are retained under config/ and supply/. Read review.json for exact source, input and preservation bindings.\n\n'
|
||||
'The initial suite failure is retained under root/first-suite-failure/. Shared scanners now distinguish one unchanged, hash-pinned optional prefab identity comparison from hard resource references; the actual vanilla Character_Base load has an ordinary audited resource entry. Optional runtime dependency closure is unchanged. The proposal and scanner baseline failures are retained under optional-identity/.\n\n'
|
||||
'Native checks were deferred because an existing game was running. No new native compilation, physical transfer, manual escape, multiplayer or FPS qualification is claimed. Original missions and four previous sealed packages remain unchanged.\n')
|
||||
require(not DEST.exists(),'Destination appeared during finalization')
|
||||
staging.rename(DEST)
|
||||
seal_archive()
|
||||
except BaseException:
|
||||
if staging.exists():shutil.rmtree(staging)
|
||||
raise
|
||||
if __name__=='__main__':main()
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"full_suite_exit": 0,
|
||||
"programs": 305,
|
||||
"unique_programs": true,
|
||||
"inputs_unchanged": true,
|
||||
"integrated_files_exact": 11,
|
||||
"production_sources_changed": 2,
|
||||
"native_check_started": false,
|
||||
"compile_or_gameplay_proof": false,
|
||||
"first_suite_failure_preserved": true
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
PASS: shared config transaction rejects client writes, preserves first-save/prior/fallback state across open, write, backup, partial-copy, readback and mismatch failures
|
||||
PASS: actual Save/Commit preserves semantically valid backup across unrelated menu edits and repairs; unknown fields/default sections retained; actual terrain parser; other parsers, catalog and disk doubled
|
||||
....
|
||||
----------------------------------------------------------------------
|
||||
Ran 4 tests in 0.001s
|
||||
|
||||
OK
|
||||
PASS: actual objective overlay lifecycle preserves separate ownership, late readiness/reopen, data refresh, pan/zoom/culling, supported sibling/shared-frame parents, coordinate offsets, native task-clear isolation and terminal cleanup; native rendering remains unverified
|
||||
PASS: actual map element initializes each widget, retries missing widgets, updates position and changes only stale text/icon data; no native image-load claim
|
||||
PASS: actual native fixture root/config ownership and idempotent cleanup preserve foreign map, selector excludes ordinary route, fixed budgets/screenshots/UGC boundaries retained; native operations not executed
|
||||
PASS: actual full Inspect rejects canvas parenting, wrong active container/canvas, omitted origin offset, wrong rendered box and stale coordinates; differing origins and DPI accepted
|
||||
PASS: actual long-warning phases retain visible label through1500ms checkpoint then restore radio before close; synthetic marker separated from unmoved player
|
||||
PASS: actual Center places marker100screenpx left of pan center at both fixture zooms without altering disclosed coordinates
|
||||
PASS: missing, child-only, malformed, zero and duplicate prefab root IDs rejected
|
||||
PASS: delayed scene/inventory arrival, deferred preload, identity checks, stale replies, timeout and observer cleanup
|
||||
PASS: actual inventory manifest, delayed/missing/wrong-owner item links, finite cap, consumed-stock refresh and preload ordering
|
||||
PASS: spawn scene remains held through final acknowledgement and nearby use; leaving, reassignment, disconnect and teardown release it
|
||||
PASS: production prison AI hold/release, repeat activation, authority/faction/player exclusion, dead actor and stop cleanup
|
||||
PASS: actual protected/capped damage plus exact-actor terminal fixture bypass through delayed native damage, fail-closed ownership and untouched ordinary actor; no native claim
|
||||
PASS: actual full planner selection/commit body, 360 equivalence scenarios, orders/reservations/cooldowns identical; one128-unit scan vs >10000 repeated unit visits; no FPS claim
|
||||
PASS: actual observer monitor/recovery/cleanup rejects retained old controller, preserves new camera/editor/hints/timer, restarts once and retains normal recovery; native effects modeled from SDK, no runtime claim
|
||||
PASS: former chat controller releases only its own callbacks and preserves replacement menu; current-owner stop/scope and repeated teardown remain intact
|
||||
PASS: wrong observer fixture selector rejected before runtime/profile setup; no engine launched
|
||||
PASS: actual depot mixed-roster worker/item selection, ownership/refusal and radio/planning/two-leg state transitions, fixed deadline, late proof quarantine, finite import and no adoption after Stop
|
||||
PASS: actual depot HQ lifecycle, existing planner priority, server/mode/owner gates, idempotent polling and owner replacement
|
||||
PASS: actual HQ mine/magazine claim separation, real demand methods, exact token cleanup and original authority gates; native availability doubled
|
||||
PASS: actual full magazine/inert-PMN4 depot leaf, exact custody, isolated callbacks, finite reservation, false/unknown and Stop quarantine, once-only delivery and caps; native movement unqualified
|
||||
PASS: actual mine/magazine provenance and separated finite mine imports; actual authored identity capture, READY-only detached provenance, same shared stock admission, completed exact two-leg proof, lifetime caps and Stop no late adoption
|
||||
Traceback (most recent call last):
|
||||
File "/tmp/erri-gameplay-root-1509/run-suite.py", line 30, in <module>
|
||||
try:module.check()
|
||||
~~~~~~~~~~~~^^
|
||||
File "/home/jakub/devel/escapistsrereintroduced/tools/check.py", line 69, in check
|
||||
assert resources.get(g)==path or vanilla.get(path)==g or resource_allowed(external,visibility[p.relative_to(ROOT/'addons').parts[0]],g,path),f'Unresolved/mismatched resource in {p}: {g} {path}'
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
AssertionError: Unresolved/mismatched resource in /home/jakub/devel/escapistsrereintroduced/addons/core/Scripts/Game/ERR/00_Core/ERR_ReaperRHSCompat.c: 574AA64002B8E308 Prefabs/Characters/REAPER_SpectatorCameraHelper.et
|
||||
PASS: 35 prefabs have unique saved root entity IDs
|
||||
Suite exit 1 programs 20 unchanged True
|
||||
+1000
File diff suppressed because it is too large
Load Diff
+89
@@ -0,0 +1,89 @@
|
||||
{
|
||||
"exit": 1,
|
||||
"seconds": 13.28,
|
||||
"inputs_unchanged": true,
|
||||
"removed_override_names": [],
|
||||
"regression_programs": 20,
|
||||
"programs": [
|
||||
{
|
||||
"path": "tests/test_profile_config.py",
|
||||
"exit": 0
|
||||
},
|
||||
{
|
||||
"path": "tests/test_welcome_voice.py",
|
||||
"exit": 0
|
||||
},
|
||||
{
|
||||
"path": "tests/test_objective_map_presentation.py",
|
||||
"exit": 0
|
||||
},
|
||||
{
|
||||
"path": "tests/test_objective_map_element.py",
|
||||
"exit": 0
|
||||
},
|
||||
{
|
||||
"path": "tests/test_native_objective_map_probe.py",
|
||||
"exit": 0
|
||||
},
|
||||
{
|
||||
"path": "tests/test_prefab_identity.py",
|
||||
"exit": 0
|
||||
},
|
||||
{
|
||||
"path": "tests/test_spawn_scene.py",
|
||||
"exit": 0
|
||||
},
|
||||
{
|
||||
"path": "tests/test_spawn_scene_inventory.py",
|
||||
"exit": 0
|
||||
},
|
||||
{
|
||||
"path": "tests/test_spawn_scene_lease.py",
|
||||
"exit": 0
|
||||
},
|
||||
{
|
||||
"path": "tests/test_prison_ai.py",
|
||||
"exit": 0
|
||||
},
|
||||
{
|
||||
"path": "tests/test_native_player_death_fixture.py",
|
||||
"exit": 0
|
||||
},
|
||||
{
|
||||
"path": "tests/test_hq_planner_budget.py",
|
||||
"exit": 0
|
||||
},
|
||||
{
|
||||
"path": "tests/test_observer_ownership.py",
|
||||
"exit": 0
|
||||
},
|
||||
{
|
||||
"path": "tests/test_chat_client_ownership.py",
|
||||
"exit": 0
|
||||
},
|
||||
{
|
||||
"path": "tests/test_native_observer_selector.py",
|
||||
"exit": 0
|
||||
},
|
||||
{
|
||||
"path": "tests/test_ground_depot_loading.py",
|
||||
"exit": 0
|
||||
},
|
||||
{
|
||||
"path": "tests/test_ground_depot_lifecycle.py",
|
||||
"exit": 0
|
||||
},
|
||||
{
|
||||
"path": "tests/test_ground_depot_mine_claim.py",
|
||||
"exit": 0
|
||||
},
|
||||
{
|
||||
"path": "tests/test_ground_depot_transfer.py",
|
||||
"exit": 0
|
||||
},
|
||||
{
|
||||
"path": "tests/test_ground_depot_provenance.py",
|
||||
"exit": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,741 @@
|
||||
PASS: shared config transaction rejects client writes, preserves first-save/prior/fallback state across open, write, backup, partial-copy, readback and mismatch failures
|
||||
PASS: actual Save/Commit preserves semantically valid backup across unrelated menu edits and repairs; unknown fields/default sections retained; actual terrain parser; other parsers, catalog and disk doubled
|
||||
....
|
||||
----------------------------------------------------------------------
|
||||
Ran 4 tests in 0.001s
|
||||
|
||||
OK
|
||||
PASS: actual objective overlay lifecycle preserves separate ownership, late readiness/reopen, data refresh, pan/zoom/culling, supported sibling/shared-frame parents, coordinate offsets, native task-clear isolation and terminal cleanup; native rendering remains unverified
|
||||
PASS: actual map element initializes each widget, retries missing widgets, updates position and changes only stale text/icon data; no native image-load claim
|
||||
PASS: actual native fixture root/config ownership and idempotent cleanup preserve foreign map, selector excludes ordinary route, fixed budgets/screenshots/UGC boundaries retained; native operations not executed
|
||||
PASS: actual full Inspect rejects canvas parenting, wrong active container/canvas, omitted origin offset, wrong rendered box and stale coordinates; differing origins and DPI accepted
|
||||
PASS: actual long-warning phases retain visible label through1500ms checkpoint then restore radio before close; synthetic marker separated from unmoved player
|
||||
PASS: actual Center places marker100screenpx left of pan center at both fixture zooms without altering disclosed coordinates
|
||||
PASS: missing, child-only, malformed, zero and duplicate prefab root IDs rejected
|
||||
PASS: delayed scene/inventory arrival, deferred preload, identity checks, stale replies, timeout and observer cleanup
|
||||
PASS: actual inventory manifest, delayed/missing/wrong-owner item links, finite cap, consumed-stock refresh and preload ordering
|
||||
PASS: spawn scene remains held through final acknowledgement and nearby use; leaving, reassignment, disconnect and teardown release it
|
||||
PASS: production prison AI hold/release, repeat activation, authority/faction/player exclusion, dead actor and stop cleanup
|
||||
PASS: actual protected/capped damage plus exact-actor terminal fixture bypass through delayed native damage, fail-closed ownership and untouched ordinary actor; no native claim
|
||||
PASS: actual full planner selection/commit body, 360 equivalence scenarios, orders/reservations/cooldowns identical; one128-unit scan vs >10000 repeated unit visits; no FPS claim
|
||||
PASS: actual observer monitor/recovery/cleanup rejects retained old controller, preserves new camera/editor/hints/timer, restarts once and retains normal recovery; native effects modeled from SDK, no runtime claim
|
||||
PASS: former chat controller releases only its own callbacks and preserves replacement menu; current-owner stop/scope and repeated teardown remain intact
|
||||
PASS: wrong observer fixture selector rejected before runtime/profile setup; no engine launched
|
||||
PASS: actual depot mixed-roster worker/item selection, ownership/refusal and radio/planning/two-leg state transitions, fixed deadline, late proof quarantine, finite import and no adoption after Stop
|
||||
PASS: actual depot HQ lifecycle, existing planner priority, server/mode/owner gates, idempotent polling and owner replacement
|
||||
PASS: actual HQ mine/magazine claim separation, real demand methods, exact token cleanup and original authority gates; native availability doubled
|
||||
PASS: actual full magazine/inert-PMN4 depot leaf, exact custody, isolated callbacks, finite reservation, false/unknown and Stop quarantine, once-only delivery and caps; native movement unqualified
|
||||
PASS: actual mine/magazine provenance and separated finite mine imports; actual authored identity capture, READY-only detached provenance, same shared stock admission, completed exact two-leg proof, lifetime caps and Stop no late adoption
|
||||
PASS: actual immutable measured footprint/root/attachment matching, bounds/transforms, moving geometry, seated-body and cargo reciprocity, finite hierarchy caps; native geometry doubled
|
||||
PASS: actual BMP singleton geometry and typed current order; one survey, full straight segment, width, known history, reservations, settlement/clearance and work caps; placement/footprint tested separately
|
||||
PASS: actual five random-radius diagnostic wrappers, disabled transparency, cached opt-in, exact zero and exclusion branch, native arguments/returns/outarg preservation, single superclass call and shared16-log cap
|
||||
PASS: zero-radius trace disabled by default, scoped before setup, exact opt-in emission; no native launch
|
||||
PASS: complete actual supply-travel probe, immutable 6+2 formations and 25 actors, admission/travel deadlines, six observed native-boundary moves, stop/ownership/partial-substitution refusals
|
||||
PASS: actual distinct supply-travel hook, fixed420s selector, original observer protection/restoration, failure/terminal cleanup and no legacy convoy setup
|
||||
PASS: actual supply-travel selector requires Chat, one round and480s; existing outcomes unaffected; no native launch
|
||||
usage: test_native_mounted_intercept.py [-h] [--steam STEAM]
|
||||
[--external-addons EXTERNAL_ADDONS]
|
||||
--compat COMPAT --profile PROFILE
|
||||
[--smoke {normal-escape-route,escape-route,optional-site-skip,infantry-combat,medical-combat,hunter-faction,unconscious-camera,objective-map,town-garrisons,site-garrisons,radio-interaction,enemy-loadout,aggression,air-logistics,air-assault,air-recon,airfield-markers,opening-tools,mortar-station,generated-sites,hq-local-handoff,infantry-transfer,hq-body,convoy,supply-convoys,supply-travel,mounted-ammo,alarm-hearing,hq-memory,hq-awareness,aircraft-field,aircraft-route,native-end-active,native-end-preparing,aircraft-control,aircraft-cancel,aircraft-translate,map-ownership,mortar-refresh,mortar-salvo,mortar-courier,station-teardown,prison-breach,powered-flight,powered-translate,local-admission,mortar-expiry,mortar-transfer,mortar-fire,patrol-hq,victory,lost-helicopter,player-death,radio-network,hq-response,mortar-inventory,startup-failure,site-survey,cache-loss,extraction-capacity,early-helicopter-loss,extraction-startup-failure,extraction-boundary-failure,transport-loss,transport-survey,lifecycle,objective-ui,recovery,prisoner-kit,medical,casualty-load,casualty-direct,casualty-bench,casualty-remove,environment,environment-restart,patrols,radio-document-loss,radio-document-loss-partial,guard-cancel,casualty-service}]
|
||||
[--trace-random-radius]
|
||||
[--maintenance-refuel]
|
||||
[--mounted-swap-eligibility]
|
||||
[--mine-stock] [--mounted-courier]
|
||||
[--mounted-intercept] [--convoy-cover]
|
||||
[--field-terrain-audit]
|
||||
[--field-service-cancel]
|
||||
[--route-service-cancel]
|
||||
[--station-teardown-diagnostics]
|
||||
[--flight-autohover]
|
||||
[--flight-action-inputs]
|
||||
[--flight-input-diagnostics]
|
||||
[--recon-takeover-only]
|
||||
[--body-recovery-only]
|
||||
[--rounds ROUNDS] [--timeout TIMEOUT]
|
||||
[--project {core,chat}]
|
||||
test_native_mounted_intercept.py: error: --mounted-intercept requires Chat --smoke convoy, one round and timeout at least900 seconds
|
||||
usage: test_native_mounted_intercept.py [-h] [--steam STEAM]
|
||||
[--external-addons EXTERNAL_ADDONS]
|
||||
--compat COMPAT --profile PROFILE
|
||||
[--smoke {normal-escape-route,escape-route,optional-site-skip,infantry-combat,medical-combat,hunter-faction,unconscious-camera,objective-map,town-garrisons,site-garrisons,radio-interaction,enemy-loadout,aggression,air-logistics,air-assault,air-recon,airfield-markers,opening-tools,mortar-station,generated-sites,hq-local-handoff,infantry-transfer,hq-body,convoy,supply-convoys,supply-travel,mounted-ammo,alarm-hearing,hq-memory,hq-awareness,aircraft-field,aircraft-route,native-end-active,native-end-preparing,aircraft-control,aircraft-cancel,aircraft-translate,map-ownership,mortar-refresh,mortar-salvo,mortar-courier,station-teardown,prison-breach,powered-flight,powered-translate,local-admission,mortar-expiry,mortar-transfer,mortar-fire,patrol-hq,victory,lost-helicopter,player-death,radio-network,hq-response,mortar-inventory,startup-failure,site-survey,cache-loss,extraction-capacity,early-helicopter-loss,extraction-startup-failure,extraction-boundary-failure,transport-loss,transport-survey,lifecycle,objective-ui,recovery,prisoner-kit,medical,casualty-load,casualty-direct,casualty-bench,casualty-remove,environment,environment-restart,patrols,radio-document-loss,radio-document-loss-partial,guard-cancel,casualty-service}]
|
||||
[--trace-random-radius]
|
||||
[--maintenance-refuel]
|
||||
[--mounted-swap-eligibility]
|
||||
[--mine-stock] [--mounted-courier]
|
||||
[--mounted-intercept] [--convoy-cover]
|
||||
[--field-terrain-audit]
|
||||
[--field-service-cancel]
|
||||
[--route-service-cancel]
|
||||
[--station-teardown-diagnostics]
|
||||
[--flight-autohover]
|
||||
[--flight-action-inputs]
|
||||
[--flight-input-diagnostics]
|
||||
[--recon-takeover-only]
|
||||
[--body-recovery-only]
|
||||
[--rounds ROUNDS] [--timeout TIMEOUT]
|
||||
[--project {core,chat}]
|
||||
test_native_mounted_intercept.py: error: --mounted-intercept requires Chat --smoke convoy, one round and timeout at least900 seconds
|
||||
usage: test_native_mounted_intercept.py [-h] [--steam STEAM]
|
||||
[--external-addons EXTERNAL_ADDONS]
|
||||
--compat COMPAT --profile PROFILE
|
||||
[--smoke {normal-escape-route,escape-route,optional-site-skip,infantry-combat,medical-combat,hunter-faction,unconscious-camera,objective-map,town-garrisons,site-garrisons,radio-interaction,enemy-loadout,aggression,air-logistics,air-assault,air-recon,airfield-markers,opening-tools,mortar-station,generated-sites,hq-local-handoff,infantry-transfer,hq-body,convoy,supply-convoys,supply-travel,mounted-ammo,alarm-hearing,hq-memory,hq-awareness,aircraft-field,aircraft-route,native-end-active,native-end-preparing,aircraft-control,aircraft-cancel,aircraft-translate,map-ownership,mortar-refresh,mortar-salvo,mortar-courier,station-teardown,prison-breach,powered-flight,powered-translate,local-admission,mortar-expiry,mortar-transfer,mortar-fire,patrol-hq,victory,lost-helicopter,player-death,radio-network,hq-response,mortar-inventory,startup-failure,site-survey,cache-loss,extraction-capacity,early-helicopter-loss,extraction-startup-failure,extraction-boundary-failure,transport-loss,transport-survey,lifecycle,objective-ui,recovery,prisoner-kit,medical,casualty-load,casualty-direct,casualty-bench,casualty-remove,environment,environment-restart,patrols,radio-document-loss,radio-document-loss-partial,guard-cancel,casualty-service}]
|
||||
[--trace-random-radius]
|
||||
[--maintenance-refuel]
|
||||
[--mounted-swap-eligibility]
|
||||
[--mine-stock] [--mounted-courier]
|
||||
[--mounted-intercept] [--convoy-cover]
|
||||
[--field-terrain-audit]
|
||||
[--field-service-cancel]
|
||||
[--route-service-cancel]
|
||||
[--station-teardown-diagnostics]
|
||||
[--flight-autohover]
|
||||
[--flight-action-inputs]
|
||||
[--flight-input-diagnostics]
|
||||
[--recon-takeover-only]
|
||||
[--body-recovery-only]
|
||||
[--rounds ROUNDS] [--timeout TIMEOUT]
|
||||
[--project {core,chat}]
|
||||
test_native_mounted_intercept.py: error: --mounted-intercept requires Chat --smoke convoy, one round and timeout at least900 seconds
|
||||
usage: test_native_mounted_intercept.py [-h] [--steam STEAM]
|
||||
[--external-addons EXTERNAL_ADDONS]
|
||||
--compat COMPAT --profile PROFILE
|
||||
[--smoke {normal-escape-route,escape-route,optional-site-skip,infantry-combat,medical-combat,hunter-faction,unconscious-camera,objective-map,town-garrisons,site-garrisons,radio-interaction,enemy-loadout,aggression,air-logistics,air-assault,air-recon,airfield-markers,opening-tools,mortar-station,generated-sites,hq-local-handoff,infantry-transfer,hq-body,convoy,supply-convoys,supply-travel,mounted-ammo,alarm-hearing,hq-memory,hq-awareness,aircraft-field,aircraft-route,native-end-active,native-end-preparing,aircraft-control,aircraft-cancel,aircraft-translate,map-ownership,mortar-refresh,mortar-salvo,mortar-courier,station-teardown,prison-breach,powered-flight,powered-translate,local-admission,mortar-expiry,mortar-transfer,mortar-fire,patrol-hq,victory,lost-helicopter,player-death,radio-network,hq-response,mortar-inventory,startup-failure,site-survey,cache-loss,extraction-capacity,early-helicopter-loss,extraction-startup-failure,extraction-boundary-failure,transport-loss,transport-survey,lifecycle,objective-ui,recovery,prisoner-kit,medical,casualty-load,casualty-direct,casualty-bench,casualty-remove,environment,environment-restart,patrols,radio-document-loss,radio-document-loss-partial,guard-cancel,casualty-service}]
|
||||
[--trace-random-radius]
|
||||
[--maintenance-refuel]
|
||||
[--mounted-swap-eligibility]
|
||||
[--mine-stock] [--mounted-courier]
|
||||
[--mounted-intercept] [--convoy-cover]
|
||||
[--field-terrain-audit]
|
||||
[--field-service-cancel]
|
||||
[--route-service-cancel]
|
||||
[--station-teardown-diagnostics]
|
||||
[--flight-autohover]
|
||||
[--flight-action-inputs]
|
||||
[--flight-input-diagnostics]
|
||||
[--recon-takeover-only]
|
||||
[--body-recovery-only]
|
||||
[--rounds ROUNDS] [--timeout TIMEOUT]
|
||||
[--project {core,chat}]
|
||||
test_native_mounted_intercept.py: error: --mounted-intercept requires Chat --smoke convoy, one round and timeout at least900 seconds
|
||||
usage: test_native_mounted_intercept.py [-h] [--steam STEAM]
|
||||
[--external-addons EXTERNAL_ADDONS]
|
||||
--compat COMPAT --profile PROFILE
|
||||
[--smoke {normal-escape-route,escape-route,optional-site-skip,infantry-combat,medical-combat,hunter-faction,unconscious-camera,objective-map,town-garrisons,site-garrisons,radio-interaction,enemy-loadout,aggression,air-logistics,air-assault,air-recon,airfield-markers,opening-tools,mortar-station,generated-sites,hq-local-handoff,infantry-transfer,hq-body,convoy,supply-convoys,supply-travel,mounted-ammo,alarm-hearing,hq-memory,hq-awareness,aircraft-field,aircraft-route,native-end-active,native-end-preparing,aircraft-control,aircraft-cancel,aircraft-translate,map-ownership,mortar-refresh,mortar-salvo,mortar-courier,station-teardown,prison-breach,powered-flight,powered-translate,local-admission,mortar-expiry,mortar-transfer,mortar-fire,patrol-hq,victory,lost-helicopter,player-death,radio-network,hq-response,mortar-inventory,startup-failure,site-survey,cache-loss,extraction-capacity,early-helicopter-loss,extraction-startup-failure,extraction-boundary-failure,transport-loss,transport-survey,lifecycle,objective-ui,recovery,prisoner-kit,medical,casualty-load,casualty-direct,casualty-bench,casualty-remove,environment,environment-restart,patrols,radio-document-loss,radio-document-loss-partial,guard-cancel,casualty-service}]
|
||||
[--trace-random-radius]
|
||||
[--maintenance-refuel]
|
||||
[--mounted-swap-eligibility]
|
||||
[--mine-stock] [--mounted-courier]
|
||||
[--mounted-intercept] [--convoy-cover]
|
||||
[--field-terrain-audit]
|
||||
[--field-service-cancel]
|
||||
[--route-service-cancel]
|
||||
[--station-teardown-diagnostics]
|
||||
[--flight-autohover]
|
||||
[--flight-action-inputs]
|
||||
[--flight-input-diagnostics]
|
||||
[--recon-takeover-only]
|
||||
[--body-recovery-only]
|
||||
[--rounds ROUNDS] [--timeout TIMEOUT]
|
||||
[--project {core,chat}]
|
||||
test_native_mounted_intercept.py: error: --mounted-intercept and --convoy-cover are mutually exclusive
|
||||
PASS: actual native interception witness requires real radio cursor/lineage, original actor identities, fixed movement/hold/expiry/resume and immutable deadline; no movement/delivery injection
|
||||
PASS: actual CLI rejects wrong mode/project/rounds/899s/conflict before runtime; valid flag and terminal branch identify synthetic-observation qualification
|
||||
PASS: visible base hook and actual fixture override delegate once; delivery proof uses retained pre-super route only on successful production transition
|
||||
actual mounted HQ dispatch planning, radio, ownership and lifecycle checks passed
|
||||
PASS: actual mounted intercept eligibility/order chronology, fixed destinations, native road selection bounds, width, segment heading, clearance and settlement delegation; no native driving claim
|
||||
PASS: actual paired arc geometry,40m/80m spacing, separate original polylines, both-position validation and128road/4096segment budget; no native driving proof
|
||||
PASS: actual typed original BMP singleton, loss/footprint/custody guards and native cancellation, UAZ-only pair admission, rollback, native allocation/revocation boundaries, per-member ownership, hold and expiry
|
||||
PASS: actual Tick clock initialization admits fractional first ticks and expires without extending the original start
|
||||
PASS: actual finite conservation/deadline/callback policies; read-only selection, bounded once-only inventory submission and no can refill; native transfer not executed
|
||||
PASS: actual exact-context membership, bounded identity/reach gates, native start/cache/eligibility ordering and no duplicate/foreign action start; fuel manager identity and empty-can headroom guards checked
|
||||
PASS: actual detached node/value snapshot and conservation refuse mismatched lengths before indexed reads, retain original identities under native out-array aliasing and log bounded counts once; native cause remains unknown
|
||||
PASS: actual mine evidence sealing/recovery, historical coarse publication, caps, canonical ownership, marker join retry/owner-change/stop; native arming and replicated vector-array transport untested
|
||||
PASS: actual full document recovery retains authored/sealed targets, one shared spent ledger, retry/exhaustion semantics and canonical multi-player ownership alongside supplemental mine intel
|
||||
PASS: actual infantry search suspension, quiet grace, finite resume, expiry/replacement and defensive/ownership boundaries
|
||||
PASS: infantry combat gate precedes radio delivery and preserves non-task transports
|
||||
PASS: actual HQ contact transition wakes only fit squad members, cancels only task orders and logs changes once
|
||||
PASS: actual finite medicine grants, authored stock deduction, full-backpack refusal/pouch fallback, no loot replenishment, unresolved-operation quarantine and ownership/stop guards
|
||||
PASS: only recent native detected/identified threats suspend hunter travel; stale/disarmed/destroyed contacts cannot strand patrols
|
||||
PASS: actual hunter combat transition cancels only its travel once, holds through renewed contact and resumes after quiet; unregistered startup preserved
|
||||
PASS: captured sighting retention, immutable details, expiry, replay rejection, bounded sound uncertainty/cooldown, radio loss, priority and overdue-status fairness
|
||||
PASS: arrow press/release, held keys, opposing keys, disabled/menu input and firearm-only retention
|
||||
PASS: town trigger and hard 700m exclusion for all observers, empty/invalid positions and final-check crossings
|
||||
PASS: exact finite site squads, invalid roster/count rejection, committed-site spacing and safe fallback boundary
|
||||
PASS: mortar couriers use the mobile site team and refuse permanent-only garrisons
|
||||
PASS: omitted preferred mortar depot selects a surviving owned camp/mobile team; no camp, foreign cache and permanent-only sites are unavailable; historical priority retained
|
||||
PASS: real-session mortar deadline, failed-support convoy admission and hunter survivor/recovery gates
|
||||
PASS: native-route retry preserves delivered target, limits attempts and suspends during combat
|
||||
PASS: stale/deleted AI utility cannot receive Complete; mortar HQ preflight withholds unsafe orders; mounted convoy cover never creates infantry Defend
|
||||
PASS: flight crew affiliation and group precede native boarding; preparation remains bounded even while passengers wait
|
||||
PASS: factionless/deleted map targets do not abort perception; faction lookup tolerates teardown; deleting helicopter releases without capture/engine access
|
||||
PASS: shoot adapter waits for a physical round; bounded same-shell retries, interrupted/never-started loads, committed no-retry, order/owner changes and normal native delegation
|
||||
PASS: missing/invalid faction crew defers before any native spawn or allowance insertion; all registered RHS factions have explicit soldier and medic profiles
|
||||
PASS: vehicle radio issued once; pending, refusal and looting cannot duplicate or fabricate a physical radio link
|
||||
PASS: actual vehicle-radio link requires the original seated crew, physical manpack and live uncaptured mission vehicle; looting, dismount, release and teardown remove it
|
||||
PASS: actual hunter release preserves survivors/HQ, releases driving ownership once, delegates capture/teardown, and excludes prison/patrol/mortar from generic objective defence
|
||||
PASS: actual player-entry hook latches original hunter capture before native callbacks; both release layers cancel ownership without new entities/refund; bounded current-owner guards and prior-release policy
|
||||
PASS: real opening road geometry enforces wide azimuths; fresh delivered contact preempts patrol cooldown, respects radio failures and does not starve in-flight interception
|
||||
PASS: actual scoped 10% tighter REGULAR aim error and alert perception; preserves equipment multiplier and restores vanilla behavior when unbound
|
||||
PASS: physical inspection and parent-wreck retention; server-only searched/report delivery unlocks native cleanup once with a 300-second delay
|
||||
PASS: bounded same-group empty-spawn retries, no casualty refill, queue retirement, delivery-gated intel, prepared-team reuse, throttled diagnostics and LOD release
|
||||
PASS: production airborne memory confidence, persistence, ground coverage, confirmed losses, artillery veto, cooldown and invalid-input rules
|
||||
PASS: production cover retains the carried HQ target until its deadline; airport reload waits until the drop pass and cover have finished
|
||||
PASS: air logistics reservation preserves delivered search until radio handoff, excludes guards/combat/in-flight orders, and quarantines unresolved native loads/moves
|
||||
PASS: actual ammunition cargo selector handles empty rifle/machinegun/sniper magazines, preserves loaded variants, excludes auxiliary launchers and tolerates missing native metadata
|
||||
PASS: original 15-minute launch/loss cadence, active/captured timer disarm, saved delay reset, stop, 300m orbit and bounded close-contact standoff at 30/60/120 Hz
|
||||
PASS: actual aircraft-removal notification guards owner/server/active/stop and schedules one full delay without replay extension
|
||||
PASS: actual helicopter delay applies resolved Random values, preserves countdown on save failure, and leaves active flights running
|
||||
PASS: hill prominence/elevation, actual road edges/heights/bends and server-only finite scout admission, pending stock, timeout and no replacements/refills
|
||||
PASS: mortar duty scope excludes players, other crews, stopped/client/inactive states; only destruction releases an active assignment, while the gunner may approach the gun
|
||||
PASS: random mode restrictions, full numeric ranges, independent calendar dates and strict daylight boundaries
|
||||
PASS: actual killais eligibility includes the 1000m boundary, excludes players/retained bodies/dead/non-character entities and checks full 3D distance
|
||||
PASS: actual generation scheduler bounds each tick, enforces deadline/candidate ceiling, validates fallback, commits only accepted positions, skips only dispensable sites, preserves required objectives/intel, and resets the next search budget
|
||||
PASS: terrain placement samples world bounds, retains streaming candidates, bounds waits/work, rejects foreign fallbacks, preserves objectives/intel and validates completion
|
||||
PASS: actual navigation readiness supports static meshes, yields only for loadable streaming tiles and refuses unreachable positions
|
||||
PASS: real sampling handles absent airports and extraction clearance preserves geometry/navigation/flatness while selecting the correct aircraft survey
|
||||
PASS: universal connector, embedded/standalone exports, multiple terrains, stable IDs, native nav configs, missing-nav visibility, path validation and overwrite protection
|
||||
PASS: airfield detection accepts physical runways/towers and bounded authored markers, rejects unrelated props, water and out-of-world markers, and samples terrain height
|
||||
PASS: configured airport parsing, bounded readiness, stale admission rejection and cleanup wiring
|
||||
PASS: automatic default, explicit header/CLI opt-out, editor/authored-mode guards, optional airport override precedence and fresh-round saving guard
|
||||
PASS: singleton identity guards, paired faction deserialization and client world-cleanup wiring
|
||||
PASS: task/map/respawn getters survive delayed old destruction and preserve ordinary-mode behavior
|
||||
PASS: replication hierarchy refuses absent/aliased nodes and establishes delivery dependencies idempotently
|
||||
PASS: standalone old faction delegates collected once, with null/deleted owners ignored
|
||||
PASS: actual terrain takeover startup skips mode-less/menu worlds, always forwards super, retains eligible/unsupported/authored/client/editor semantics
|
||||
PASS: native name callback preserves authored modes, opt-outs and failures; terrain suffix follows world changes, cached resolution and confirmed takeover metadata restores on cleanup without changing scenario resource or overwriting later titles
|
||||
PASS: actual terrain parent traversal, Armenhof/Nogova names, Everon alias, missing-resource fallback, empty names and bounded cycles/depth
|
||||
PASS: saved terrain GUIDs, defaults, restart persistence, clearing, backup recovery, corrupt-file preservation, write failures, and client write denial
|
||||
PASS: startup terrain capture protects client/editor/menu worlds, default behavior, same-map loads and reload-loop recovery
|
||||
PASS: actual transition waits for native startup, disconnects without bans, requires an empty session, retains every loaded mod, bounds waiting and consumes requests once
|
||||
PASS: actual faction resolution reserves explicit roles, samples without replacement, substitutes disabled selections, and rejects duplicate/unknown/missing choices and insufficient pools
|
||||
PASS: Random all submits persistent random roles immediately; manual mixed choices, stale/unauthorized UI guards and debounce preserved
|
||||
PASS: actual content policy gates parent packs, individual factions, faction identity and finite group rotation with vanilla fallback
|
||||
PASS: actual delivered road eligibility, ahead projection without chords, reservations, stock road query bounds, terrain/water/obstruction refusal and clean outputs
|
||||
PASS: actual delivered-task lineage, expiry, old-order retention, native commit, release, road precision expiry and duplicate delivery
|
||||
PASS: actual original-roster local handoff,100m3D bound,busy carrier/budget exclusion,origin interruption including deletedsource,normal radio delivery and per-source replay history
|
||||
PASS: actual visual intake retains source/time/position/id, rejects replay, prefers usable own route, excludes simultaneous callers and conservatively resets negative-sweep dwell
|
||||
PASS: actual fixture local/radio gating, immutable source/time/position, interrupted-report exclusion and exact-owner cleanup
|
||||
PASS: local-handoff runner refuses wrong project/round count/insufficient deadline before runtime work
|
||||
PASS: actual fixture allocator terminal/unsubmitted guard, original-group lookup and both candidate gates
|
||||
PASS: actual report-derived waypoint insertion/order and tighter positive radii; no formation navigation claim
|
||||
PASS: actual Place/Stop waits native pose update, bounds four attempts, preserves original position, restores pending/settled placement and respects ownership/accepted-move quarantine
|
||||
PASS: actual fixture current/original recipient ownership, unresolved transfer cleanup, exact-token release and idempotent Stop
|
||||
PASS: actual fixture phased-cargo readiness, bounded callbacks, captured-stock mixed-caliber selection/continuation, reservation cleanup and component magazine counts
|
||||
PASS: actual inventory-fixture setup uses ordinary prison unlock before constructing its convoy-waiting probe; failed unlock cannot run fixture
|
||||
PASS: actual authored storage anchors, native trace flags, own-hierarchy exclusion, external wall/vehicle obstruction, range, unknown geometry and bounded context refusal
|
||||
PASS: actual Compatible and bounded stock preflight before report/claim consumption, later compatible truck, launcher controls, convoy binding, finite identities, disjoint tokens, shared report replay/cooldown, original recipients and HQ cleanup
|
||||
PASS: actual finite convoy supply pool; immutable slots, shared demand state, sparse/capped discovery and permanent shutdown
|
||||
PASS: actual HQ rotates finite donors, skips unavailable/contacted trucks, uses delivered reports and dispatches at most one trip per planning cadence
|
||||
PASS: actual original turret identity, native/canonical guards, scoped maximum-skill profile, reset, dismount/reboard, requested-skill preservation and restoration
|
||||
PASS: bounded HQ startup/memory windows and outcome-specific full-route deadlines
|
||||
PASS: explicit escape-route skips only administrator stress, preserving original full-fixture wait/failure paths
|
||||
PASS: normal escape route keeps ordinary catalog and generated placement; historical selectors remain unchanged
|
||||
PASS: actual read migrates old valid settings, preserves explicit disabled state, rejects invalid data; next-round feedback and fixed menu remain honest
|
||||
PASS: actual automatic convoy timing/authority/admission/one-attempt/manual-task/stop policy; native deployment unproved
|
||||
PASS: late authoritative failure reason refreshes open result; detach, mode change and success subscriptions preserved
|
||||
infantry resupply actual rules, radio transitions, owned cleanup and unresolved-operation tests passed
|
||||
PASS: actual resupply Roster preserves permanent release, original slot mapping and bounded ownership
|
||||
PASS: actual designated zero/one original carrier selection, settled startup, shared finite claims, no refund after submission
|
||||
PASS: actual HQ startup grant readiness forwarding is authoritative and fail-closed
|
||||
PASS: actual finite PMN4 designated-zero/one entitlement, pinned original ownership, shared commit, physical custody, callback quarantine/deletion and no retry
|
||||
PASS: actual bounded empty-return and finite delivery; phase-isolated callbacks, exact ownership proof, stop quarantine and original actor/vehicle boundaries
|
||||
PASS: actual shared finite identity reservation; competing consumers, submission permanence, stale cleanup and96-item bound
|
||||
PASS: actual carried-mounted swap, shared committed claim, physical slot reach, exact two-way proof, uncertainty and terminal cleanup
|
||||
PASS: actual mounted pickup, exact finite ownership, pre-submission commit, physical custody, bounded callback and quarantine lifecycle; no native coverage claim
|
||||
PASS: actual mounted courier admission, radio, individual orders, two-stage transfer, reboarding, token cleanup and quarantine lifecycle
|
||||
PASS: actual scoped crew permit and native board completion/failure preserves foreign seats without teleport fallback
|
||||
PASS: actual shared mounted stock/history ownership, atomic exact HQ pair claim, and bounded stopped-owner proof polling
|
||||
PASS: actual carried/mounted early ammunition policy and status-first shared uplink; complete threshold, phases, cooldown, failures requested check-ins and non-urgent detached carried-mine status
|
||||
PASS: actual group radio startup preservation, finite native grants, callback quarantine, frozen selection/actor ownership and bounded observation
|
||||
PASS: actual maintenance native-stock check rejects missing/duplicate/wrong-identity/unowned/depleted/malformed stock and is read-only; native runtime not executed
|
||||
..................
|
||||
----------------------------------------------------------------------
|
||||
Ran 18 tests in 0.278s
|
||||
|
||||
OK
|
||||
PASS: actual radio node rejects current incapacitation, death, ownership and faction changes despite cached inventory; one-second capability refresh remains explicit
|
||||
PASS: Southern finite maintenance stock preserves weapons/clues and optional transport, historical Western fixture stays separate; native capacity/consumption untested
|
||||
PASS: optional transport deferred behind required readiness, bounded once-only spawn/omission, isolated cleanup, occupied-candidate retention and required-default preservation
|
||||
PASS: actual diagnostic fallback runs only on failed missing-context call, derives unique native pilot door, preserves stock eligibility and restores prior index on success/failure; diagnostics mutate no game state.
|
||||
PASS: actual native-prelude cleanup restores only original changed damage, refuses stale/incapacitated/aboard teleport; bounded five-seat/four-door fixture wiring checked. Native execution remains pending.
|
||||
PASS: actual CreateTransport requires successful scoped Configure after handbrake, preserves ordinary vehicles, tracks spawned entity before failures and never treats failed lock registration as ready.
|
||||
PASS: actual preparation Configure guards/idempotence/breach preservation, security eligibility/final current-body server mutation and all scoped action guards; all five seat/four door resource overrides. Native hold, prefab merge, replication and boarding remain unverified.
|
||||
PASS: production vehicle alarm single trigger/replica completion/no replay, fixed deadline/readiness wait, failed audio, dedicated server, moving exact handle, destruction/native end/deletion/clock and mission teardown. Native sound and multiplayer delivery require engine qualification.
|
||||
PASS: production alarm emitter/receiver original time/location, explicit native queue only, 32-entry cap, 50m local witness eligibility, bound perception, native-super preservation; actual engine broadcast/hearing remains unverified.
|
||||
PASS: actual optional candidate barrier, exact callback/custody proof and unchanged mine/primary snapshots; no native transfer claim
|
||||
Native finite mine-stock runner: parser, scope, exclusions and command pass
|
||||
PASS: actual bounded native mounted proof/detached payload/deadline/cleanup methods, production-only setup and isolated runner selector
|
||||
PASS: actual one-existing-convoy candidate readiness, sender-root identity, incomplete cargo refusal and fixed three-candidate bound
|
||||
PASS: actual once-only native dry query, exact before/after slots, native refusal, shutdown; shared bounded discovery and distinct opt-in verdict
|
||||
PASS: actual completion selector and pre-cleanup variant capture preserve separate radio and eligibility verdicts
|
||||
PASS: actual cargo diagnostic stages separate absent/foreign magazines, used/empty/invalid rounds, well mismatch and exact truck storage/attachment without mutation
|
||||
PASS: actual native courier witness rejects missing radio/custody/swap/reboard evidence; CLI opt-in bounded; native success remains unqualified
|
||||
PASS: actual courier constructor/Tick waits for preparation, returns before physical checks, preserves fixed deadline and sticky stop/failure; Enfusion startup awaits native verification
|
||||
PASS: actual arranged native alarm fixture deadline, single emit, natural-route observation, original timestamp/area/detail assertions, natural observer proximity/activation wait, failure cleanup and independent canonical-body restoration; native delivery itself remains unqualified.
|
||||
PASS: actual convoy cover observation/snapshot/uplink/HOLD/RESUME/cleanup transitions; native boundaries mocked, non-convoy runner opt-in refused
|
||||
Enemy optics actual-service ownership, preservation, callback, deadline and bounded-inspection policies passed
|
||||
PASS: actual delivered cover freshness/lineage/replay and canonical executor; owned waypoint-only hold, one resume at preserved route index, invalid ownership/crew/ledger refusal and fail-closed native recreation
|
||||
PASS: actual Stinger show/set/help state precise actor-roll effects; read-only help, bounded values, malformed syntax and failed-save preservation; no rerolls/gameplay edits and no native persistence claim
|
||||
PASS: new/retasked search and radio delivery ammo gates; active tasks and delivered release preserved
|
||||
HQ convoy delivered-report planning and downlink regressions passed
|
||||
PASS: actual own-inventory ammo inspection deduplicates loaded/carried/shared wells, separates chambers/launchers, freezes scalar snapshots and treats unsupported/capped/foreign inventory as unknown
|
||||
PASS: actual carried PMN4 inventory, original-owner guards, bounded deduplication, independent unknown state and detached counts
|
||||
PASS: actual mounted hierarchy sampling, ownership exclusion, deduplication, completeness/caps, quarter threshold and detached validation; no runtime policy or ammunition mutation
|
||||
PASS: WORKBENCH opt-in diagnostics distinguish cycles/cap/storage/manager/mount failures without repeated native traversal
|
||||
PASS: actual HQ original convoy-root admission rejects wrong force/server/group and never supplies replacement lookup
|
||||
PASS: production mounted structural seat scan ignores >128 carried/cargo descendants, shares exact native mount/magazine ownership, preserves attachment seats and exact occupants, rejects unknown/cyclic/oversize structures; native binding still requires qualification.
|
||||
PASS: native body fixture uses existing immutable actors, real production LOS/queued uplink, pre-delivery isolation, actual status overlap, bounded cleanup and no fabricated reports/spawns
|
||||
PASS: actual native fixture lookup selects exact BODY kind/identity/message from bounded evaluations, never sighting-only Get
|
||||
PASS: actual ammo snapshot comparison checks every scalar/category flag; native probe requires real roster rescan, loaded-round lower bound and separate immutable pending/Watch objects
|
||||
PASS: actual delivered slot-union bodies preserve overlap/disjoint evidence, replay idempotence, status subset integrity, full-wipe closure and formation-local bounds
|
||||
test_review_added_allowed_media_invalidates_snapshot (__main__.ReviewTests.test_review_added_allowed_media_invalidates_snapshot) ... ok
|
||||
test_review_added_source_directory_rejected (__main__.ReviewTests.test_review_added_source_directory_rejected) ... ok
|
||||
test_review_loose_root_resource_and_symlink_rejected (__main__.ReviewTests.test_review_loose_root_resource_and_symlink_rejected) ... ok
|
||||
test_review_metadata_media_and_sidecars_remain_allowed_and_bound (__main__.ReviewTests.test_review_metadata_media_and_sidecars_remain_allowed_and_bound) ... ok
|
||||
test_review_missing_link_rejected (__main__.ReviewTests.test_review_missing_link_rejected) ... ok
|
||||
test_review_package_guard_sees_new_scripts (__main__.ReviewTests.test_review_package_guard_sees_new_scripts) ... ok
|
||||
test_review_retargeted_private_link_rejected (__main__.ReviewTests.test_review_retargeted_private_link_rejected) ... ok
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 7 tests in 0.073s
|
||||
|
||||
OK
|
||||
PASS: actual report methods reproduce old starvation; status-first scheduler delivers check-ins and requires 30s without combat or actual visible contacts before negative reports
|
||||
PASS: actual actor group lookup retains controlled character membership when seated/inherited vehicle agents differ; missing control or parent refuses
|
||||
.................
|
||||
----------------------------------------------------------------------
|
||||
Ran 17 tests in 3.748s
|
||||
|
||||
OK
|
||||
PASS: actual convoy motion thresholds, native-only proof boundaries, physical cargo/crew ownership and pre-launch runner restrictions
|
||||
PASS: actual new measured ClearFootprint 25/441 sample grids, measured extents/height, water/invalid world/terrain/trace refusal plus legacy filled rotated-footprint TraceBox and nine terrain/water samples; broad tree/cable bounds alone accepted, actual collision/nonfinite trace refused, nonzero sweep and ENTS/OCEAN flags, bounded diagnostic query and reset
|
||||
PASS: actual road interpolation/projection/orientation, six35m starts,200m forward tail, preserved bends, short/far/degenerate/nonfinite/overdense/hairpin refusal and deterministic candidate ties
|
||||
PASS: actual authenticated convoy dispatch, active/ready admission gates, canonical receipt, safe unconsumed preflight retry, pool refusal, retained partial failure and consumed no-retry
|
||||
PASS: actual native readiness exact membership, one-time per-vehicle ledger admission/reservation, partial readiness retry without duplicate records and one-pass56-item cargo allocation without replenishment
|
||||
PASS: actual per-vehicle readiness reasons, native agent/activity counts, intended-seat diagnostics, five-second throttle and read-only observation
|
||||
PASS: actual convoy dispatch validates before receipt consumption, consumes once before native mutation, retains all12 partial-failure paths, accepts the selected non-USSR enemy, and allocates exact19 bodies without capacity shrinking
|
||||
PASS: own memberless prefab disables automatic spawn before initialization; actual admission rejects populated, immediate or authored-slot templates before finite crew creation
|
||||
PASS: actual native seated-group arrival outside35m, native waypoint removal, idempotent advance, and convoy waypoint idempotence/arrival/deadline, missing/dead/captured/reparented crew refusal, failed native waypoint release, original vehicle/member preservation and no replacement
|
||||
PASS: actual convoy/team Release retains original active survivors and HQ identity, rejects takeover/terminal/unknown roster, preserves exact logistics quarantine and normal eligibility
|
||||
PASS: actual convoy receipt identity/one-use, shared60-body and128-formation caps, outstanding/native-ledger accounting, exact19-body composition, source reuse, mode/client guards and no consumed receipt refunds
|
||||
PASS: actual supply route cycling/arrival/stops, finite startup bounds, contact freshness, dismount hold, quiet interval, interrupted boarding, timeout and lost-truck release
|
||||
PASS: moving-convoy perception boundaries and scoped individual/group abandonment priorities
|
||||
PASS: actual supply startup reasons expose unchanged body budget/requirement, journal only failure changes, preserve retry cadence/caps and report the true final refusal
|
||||
PASS: actual combat start releases only exact intercept claims before owning route/orders; foreign claim defers combat takeover
|
||||
PASS: actual StartOne plus actual pool preserve unconsumed receipt retry, reject consumed replay, skip impossible new-budget surveys, retain equality, retry caps and journal dedup; no FPS claim
|
||||
PASS: actual admission seeds use exact installed loaded prefab, reject replacement/foreign/projectile paths and preserve bounded immutable identity
|
||||
PASS: actual primary-before-mounted one-shot batch, shared96/128 caps, physical snapshot headroom, original ownership, callback refusal and admission pinning
|
||||
PASS: actual bounded HQ query validates only existing original binding without admission or replacement lookup
|
||||
PASS: exact optional PMN4 startup, primary callback independence, original owner,128 capacity/callback limits, terminal no-retry and callback-proven freeze
|
||||
PASS: production convoy spacing, physical arrival, stable follower targets, supply ownership, leader promotion and bounded stuck recovery
|
||||
PASS: convoy combat keeps native manoeuvres for unchanged contacts and refreshes when contact moves
|
||||
PASS: native convoy proof excludes pre-departure movement and ends via explicit fixture reset, not prohibited player death
|
||||
PASS: boarding retries only after approach/seat progress stops, capped at three, with delayed native reissue and completed-team preservation
|
||||
PASS: slow only owned vehicles near fit dismounted infantry; ignore passengers, casualties and released teams/vehicles
|
||||
PASS: restore missing native driving registration only for healthy owned seated crews; preserve existing association and refuse invalid/released vehicles
|
||||
PASS: actual body observer enforces owned physical roster, local death-only candidates, native trace gating, budget/cadence/caps, immutable body-only snapshots, radio retries and confirmed suppression
|
||||
PASS: own initial roster, explicit retained corpse evidence, unconscious/missing/ref transfer guards, fixed strength, no replacement adoption, detached samples, surviving radio sender, immutable convoy root/ledger, mounted capture release and lost-root unknown
|
||||
PASS: delivered-only status snapshots, two missed check-ins/reply deadline, last reported coordinates, episode/replay guards, confirmed-loss idempotence, detached/validated mounted payload replacement 256-record cap and detached carried-mine radio delivery/chronology
|
||||
PASS: actual failed-retask deadline rollback plus assignment cancellation/release preserves radio ownership, native waypoint lifecycle and failed-order retry boundaries
|
||||
PASS: actual force ledger, finite casualties/identity/cap, routes/arrival/elevation/overshoot, server and physical guards, staggered 256-record simulated hour without world queries
|
||||
PASS: actual equipment coordinator registration dedupe, startup delay, five member scans, finite component retries, unregister/stop terminal behavior and 256-group bound
|
||||
PASS: actual percentage selection, native/preferred launcher preservation, failure/removal fallback, pending-operation quarantine, capture, finite two-mine grants and no replenishment
|
||||
PASS: automatic inventory one-shot roll, exact item ownership, finite compatible ammo, rejection, capture/stop, deletion, loot and late callback quarantine
|
||||
PASS: enabled/valid catalog eligibility, category restrictions, content filtering, GUID deduplication across factions and bounded catalogs
|
||||
PASS: actual engineer native group-envelope admission and phase cancellation, preparation/deadline, original custody/identity, once-only callback removal, cancellation quarantine, withdrawal/clearance, native refusal and owned-action cleanup; native execution untested
|
||||
PASS: actual mine selector respects road and settlement flank safety; native boundaries doubled
|
||||
PASS: actual HQ and post ledger: second delivered post, one query/tick,2 active/32 jobs,4 consumed lifetime attempts, no-stock/query refusal consumption, pending old job and original identity constraints
|
||||
PASS: actual mine post ledger immutable history, strict chronology/evidence, aliases, >160m separation, detached sites and finite4/32 consumed attempts
|
||||
PASS: actual objective heading/threat/approach rules, persistent doctrine weight, fresh-contact coverage invalidation, stale-sweep rejection and atomic radio retask ownership
|
||||
PASS: actual bounded delivered-negative coverage, replay/freshness/expiry/invalid guards, oldest eviction, small-circle and nearest-unswept selection, reserved-cell exclusion and cleanup
|
||||
PASS: actual HQ active/pending reservations, interruption, committed replacement, bounded coverage and unchanged force counts
|
||||
PASS: actual bounded pursuit roles/objectives/scores, stale search degradation, physical/busy/home guards, finite lifetime and two-bearing escape gap; no hidden player reads or spawning
|
||||
PASS: actual HQ memory rules/service preserve delivered snapshots, chronology, replay bounds, decay, motion limits, identity and negative-search revisions
|
||||
..........
|
||||
----------------------------------------------------------------------
|
||||
Ran 10 tests in 0.219s
|
||||
|
||||
OK
|
||||
PASS: actual session Tick + journal router delivers each grant completion and new HQ line once, without repeats on empty/unavailable feeds or unauthorized ticks
|
||||
.....
|
||||
----------------------------------------------------------------------
|
||||
Ran 5 tests in 0.477s
|
||||
|
||||
OK
|
||||
PASS: actual current-controller/admin/mode authorization, per-round anti-replay, token-rotation refusal, command/snapshot throttles and client scope; owner-only replies and player-tool cleanup wiring
|
||||
PASS: mission provider registration is idempotent, optional dispatch is ordered, status aggregates, journals preserve cursors, aliases stay with their addons and topic help is bounded
|
||||
PASS: actual menu command routing covers all fifteen settings, rejects unsupported keys, gates companions, and matches unique authored widgets
|
||||
PASS: explicit weapon retention buttons use the same ready/authorized server command path
|
||||
PASS: item editor, preset controls and dynamic item-row layout are structurally valid
|
||||
PASS: catalog requests use authenticated sessions, independent admin page selections, loaded-mod allowlisting, bounded pages and allowlisted item mutations
|
||||
PASS: actual item rules, shared-source conflicts, missing/returning mods, bulk reset, independent named presets, bounds, malformed data and failed-save state preservation
|
||||
PASS: actual summaries preserve queued/delivered meaning, clear counts and IDs; raw records, legacy display, cursor gaps and RPC limits remain intact
|
||||
PASS: actual admin body authorization, god restoration, vanilla item deposit, callback completion/failure, timeout quarantine and stop/revocation paths
|
||||
PASS: same-body revoke/regrant preserves pending insertions and timeout quarantine; new-body binding isolates late callbacks and never inherits god mode
|
||||
PASS: actual Intel commands distinguish status/start/failure, preserve authorization gate and reject malformed requests; spent ledger is idempotent, server-only and bounded
|
||||
PASS: actual reroll snapshot, authority, cancellation, ownership, accepted operations, quarantine, bounded work and stop methods; no native runtime claim
|
||||
PASS: production Intel feedback coalescing, rough secrecy, rate limit, bounded dedupe, local/remote delivery and round cleanup; native UI/RPC not exercised
|
||||
PASS: actual per-squad bounded report selector rotates visible targets, survives ordering/turnover, records only queued attempts, and preserves radio intake ordering
|
||||
PASS: actual action denial/clearing, server request failure, single submitted-result feedback, current rescuer identity and terminal/stop suppression; native UI/RPC pending
|
||||
PASS: actual physical denial precedence and transport-seat occupancy/reservation/access/lock checks
|
||||
PASS: actual initial admission exhaustion and ServerTick grace; new/pending/empty/controller/life guards, normal death preserved
|
||||
......................
|
||||
----------------------------------------------------------------------
|
||||
Ran 22 tests in 0.294s
|
||||
|
||||
OK
|
||||
......................
|
||||
----------------------------------------------------------------------
|
||||
Ran 22 tests in 28.665s
|
||||
|
||||
OK
|
||||
..................
|
||||
----------------------------------------------------------------------
|
||||
Ran 18 tests in 3.342s
|
||||
|
||||
OK
|
||||
.........
|
||||
----------------------------------------------------------------------
|
||||
Ran 9 tests in 2.601s
|
||||
|
||||
OK
|
||||
...............
|
||||
----------------------------------------------------------------------
|
||||
Ran 15 tests in 1.291s
|
||||
|
||||
OK
|
||||
PASS: actual field result/braking observer and Chat dispatch rules; one finite fixed candidate, deferred callback failure and guarded cleanup; no native measurement
|
||||
PASS: actual opt-in terrain audit records one fixed1681-point grid, preserves original survey refusal/success and exact no-allocation scope; malformed heights stop without retry; no native data acquired
|
||||
....
|
||||
----------------------------------------------------------------------
|
||||
Ran 4 tests in 0.708s
|
||||
|
||||
OK
|
||||
PASS: actual field PI/ramp/vector caps, antiwindup, braking hypothesis, immutable admission limits and segment bounds; no native physics tested
|
||||
PASS: actual100m whole-field survey sampling/4096cap, rotated coverage, all-node terrain and native trace refusal; original certificate lineage retained; no native qualification
|
||||
PASS: actual QualifyField preserves original identity/footprint/time, orders complete surveys before issuance, and refuses failed stages/moved body/expired or changed world; native boundaries faked
|
||||
PASS: WORKBENCH first-refusal diagnostics preserve ordinary predicates, query order/count/budget and opt-in scope; no native logging run
|
||||
PASS: actual field startup delegation, immutable lease/target, braking/settling/cancel transitions, early abort, callback scope, physical terminal policy and shared landing demand; native boundaries faked
|
||||
PASS: actual inherited airborne pre-CLIMB cancellation enables verified native autohover once, refuses failed enable and never writes after capture
|
||||
PASS: actual Core maintenance/default/tick/stop methods; empty/populated authority, terminal reentry, no tactical resume or new scheduler; native boundaries substituted
|
||||
PASS: actual finite registration, unique claims/tokens, retention/cancel/stop, readiness gating, capture/expiry retirement and bounded cross-kind order history and typed field/route construction; native boundaries faked
|
||||
PASS: actual WORKBENCH route observer returns exact retained route subtype and refuses absent/field controllers
|
||||
.....
|
||||
----------------------------------------------------------------------
|
||||
Ran 5 tests in 0.772s
|
||||
|
||||
OK
|
||||
......................
|
||||
----------------------------------------------------------------------
|
||||
Ran 22 tests in 0.203s
|
||||
|
||||
OK
|
||||
................
|
||||
----------------------------------------------------------------------
|
||||
Ran 16 tests in 11.462s
|
||||
|
||||
OK
|
||||
......
|
||||
----------------------------------------------------------------------
|
||||
Ran 6 tests in 0.022s
|
||||
|
||||
OK
|
||||
PASS: actual production bridge lookup, lease/world/mode/seat/capture guards, no allocation, native super ordering and read-only fixture hooks
|
||||
...............
|
||||
----------------------------------------------------------------------
|
||||
Ran 15 tests in 0.059s
|
||||
|
||||
OK
|
||||
.............
|
||||
----------------------------------------------------------------------
|
||||
Ran 13 tests in 5.510s
|
||||
|
||||
OK
|
||||
PASS: actual route gain/caps/braking, callback selection, old landing/cancellation control and matching read-only telemetry
|
||||
..............................
|
||||
----------------------------------------------------------------------
|
||||
Ran 30 tests in 0.449s
|
||||
|
||||
OK
|
||||
..............
|
||||
----------------------------------------------------------------------
|
||||
Ran 14 tests in 0.220s
|
||||
|
||||
OK
|
||||
.........
|
||||
----------------------------------------------------------------------
|
||||
Ran 9 tests in 0.123s
|
||||
|
||||
OK
|
||||
PASS: actual gate observer binds native registered action/context and current life, reads accumulated progress, refuses stale bindings and never revives outside original bounds
|
||||
PASS: actual read-only look observer methods enforce explicit scope, pinned native camera/body/identity, normalized pose, terminal cancellation and original sample/time bounds
|
||||
...........
|
||||
----------------------------------------------------------------------
|
||||
Ran 11 tests in 0.076s
|
||||
|
||||
OK
|
||||
.......................
|
||||
----------------------------------------------------------------------
|
||||
Ran 23 tests in 0.039s
|
||||
|
||||
OK
|
||||
PASS: actual initial WAITING task/guide copy, configured duration, unchanged interruption and rounded progress; native task assertion pending
|
||||
........
|
||||
----------------------------------------------------------------------
|
||||
Ran 8 tests in 0.021s
|
||||
|
||||
OK
|
||||
PASS: actual inventory adapter scope, grid placement, sole compatible host, refresh reuse, rollback, foreign hierarchy refusal and exactly-once native delegation; native compatibility pending
|
||||
.................................................................................
|
||||
----------------------------------------------------------------------
|
||||
Ran 81 tests in 0.585s
|
||||
|
||||
OK
|
||||
......
|
||||
----------------------------------------------------------------------
|
||||
Ran 6 tests in 0.084s
|
||||
|
||||
OK
|
||||
.................
|
||||
----------------------------------------------------------------------
|
||||
Ran 17 tests in 0.004s
|
||||
|
||||
OK
|
||||
...........
|
||||
----------------------------------------------------------------------
|
||||
Ran 11 tests in 0.098s
|
||||
|
||||
OK
|
||||
.........
|
||||
----------------------------------------------------------------------
|
||||
Ran 9 tests in 0.370s
|
||||
|
||||
OK
|
||||
PASS: actual observer nonce, admission pins, baseline/menu sequencing, snapshots, bounded clocks/samples, cleanup and one-attempt latch; native untested
|
||||
PASS: actual corridor caps/height/hold and whole-rectangle survey bounds, terrain refusal, native trace refusal and exact certificate lineage; native route unqualified
|
||||
PASS: actual route entry, fixed corridor/target, hover hold, cancellation landing freeze, shared lease/capture/deadline gate and unchanged native startup/tick sequence
|
||||
PASS: finite opt-in route fixture, original native input order, meaningful physical-arrival evidence and guarded cleanup; no native launch
|
||||
PASS: actual Chat route step result dispatch and scoped completion/cleanup wiring; six real early-parser refusal paths leave no prefix/profile output
|
||||
PASS: actual retained-service fixture entry, immutable controller/token/deadline/count bindings, observer getter and cleanup ownership ordering; native route validation pending
|
||||
PASS: actual measured cancellation gate, one-shot retained service Stop, no premature drain, immutable lease, fresh real controller readback and separate physical cancellation result policy
|
||||
PASS: actual rough-intel objective selection, exact precedence, source grid dimensions and unchanged other-phase dispatch; native UI pending
|
||||
.................................
|
||||
----------------------------------------------------------------------
|
||||
Ran 33 tests in 0.143s
|
||||
|
||||
OK
|
||||
...............
|
||||
----------------------------------------------------------------------
|
||||
Ran 15 tests in 0.039s
|
||||
|
||||
OK
|
||||
PASS: actual preparation status scope, persistent updates, spinner restoration, placeholder replacement/deletion/destruction, native observation persistence/timeout; rendering remains native-pending
|
||||
PASS: actual guide ownership and scoped timer cancellation, current-controller preservation/reacquisition, hint retry/dedup and observer boundaries; native UI not exercised
|
||||
PASS: actual native-end shutdown, existing terminal snapshots, reentrancy, unchanged native end data and stale preparation guards
|
||||
....
|
||||
----------------------------------------------------------------------
|
||||
Ran 4 tests in 1.583s
|
||||
|
||||
OK
|
||||
PASS: actual three-state result wording and UI refresh; stale winner IDs never manufacture escape
|
||||
...........
|
||||
----------------------------------------------------------------------
|
||||
Ran 11 tests in 0.124s
|
||||
|
||||
OK
|
||||
PASS: actual immutable target, bounded autohover demand, drift refusal, five-second hold and unchanged qualification/deadline
|
||||
PASS: actual admission attempt budget bounds blocked/missing prerequisites; preparation, spent life and async pending remain protected
|
||||
PASS: delayed admission retry retains controller ownership across same-account recycled connection IDs
|
||||
PASS: actual scene deadline overrides delayed native preload only for rejection; late completion cannot assign, ordinary verified admission preserved
|
||||
PASS: actual action permission matrix unchanged; useful phase/intel/consciousness denials, stale reason cleared, native door denial preserved; no native UI claim
|
||||
.....
|
||||
----------------------------------------------------------------------
|
||||
Ran 5 tests in 0.279s
|
||||
|
||||
OK
|
||||
PASS: actual aircraft cancellation/stage rules, ground-only completion, expiry/capture faults, input ownership and no physical shortcuts
|
||||
PASS: actual exact-instance single-use qualification, native-clock staleness/movement refusal, footprint bounds and ownership-safe ground/fault cleanup
|
||||
PASS: actual optional screenshot helper flag/identity/world/life revalidation, one queued attempt, delayed capture and mission/world cleanup; no native image/presentation claim
|
||||
PASS: actual yard diagnostic exact registered prison ownership, eight native-bound corner projections, no root-sibling escape, bounded duplicate/deep/wide hierarchy traversal; native projection/mask still unmeasured
|
||||
PASS: actual CurrentActor, SpawnPosition and observer-selection methods reject pending/unregistered/replaced/recycled/foreign/dead bodies; canonical selection/cycling, unconscious following and prison/geometry fallback preserved; native boundaries adapted
|
||||
PASS: actual native-map fixture ownership, cleanup and callback evidence fail closed; native execution remains separate
|
||||
PASS: actual shared-map callbacks bind exact map/config/root, preserve replacement UI/camera, defer focus, and remove only owned delayed work
|
||||
PASS: actual Intel/HQ methods and one-shot qualified readiness handoff deliver late actors once; duplicate readiness, accepted spawn, pickup/drop, death and original negative rolls do not mint assignments
|
||||
PASS: Workbench-only read accessor rejects unknown/nonserver identities; Chat observes all distinct ready crew before existing shell-depletion mutation
|
||||
PASS: actual native-event latch survives deselection, requires exact activity/order, detaches before cleanup, preserves failure/timeout and never infers completion from physical shot count
|
||||
.........
|
||||
----------------------------------------------------------------------
|
||||
Ran 9 tests in 0.122s
|
||||
|
||||
OK
|
||||
PASS: actual refresh-fixture gates pin immutable observations/actual downlinks/original activity, reject unaccepted or relabelled commits, stop queueing early and require all queued contacts claimed before replay
|
||||
..........................
|
||||
----------------------------------------------------------------------
|
||||
Ran 26 tests in 0.227s
|
||||
|
||||
OK
|
||||
PASS: actual refresh scheduler/delivery/cancellation/projectile methods reject interrupted or replayed reports, retain committed ownership, preserve immutable snapshots/aim geometry and isolate stopped or replaced orders; native radio/crew behavior remains separate
|
||||
.....................
|
||||
----------------------------------------------------------------------
|
||||
Ran 21 tests in 0.040s
|
||||
|
||||
OK
|
||||
...........
|
||||
----------------------------------------------------------------------
|
||||
Ran 11 tests in 0.038s
|
||||
|
||||
OK
|
||||
PASS: actual full-salvo gates require eight fresh committed physical launches, natural closure and exact finite inventory; reject partial/extra/replayed events
|
||||
PASS: actual reason/availability guidance and refresh matrix; no-target copy omits cycling, hint retry retained, existing command/admin paths unchanged; native UI pending
|
||||
PASS: actual client camera policy closes immediately on healing or mission end; late unconscious metadata cannot keep the view active
|
||||
PASS: actual input dispatch, one press per edge, menu-held suppression; actual revival camera handoff with editor close/retry, missing camera, replacement body and stopped round
|
||||
PASS: first-person pose survives missing samples without drift, follows body motion/rotation, resumes fresh pose and cannot leak between targets
|
||||
................usage: test_native_package.py [-h] [--project {core}] --session SESSION
|
||||
--compat COMPAT [--steam STEAM]
|
||||
[--timeout TIMEOUT]
|
||||
[--external-addons EXTERNAL_ADDONS]
|
||||
[--silent-workbench | --exit-after-init]
|
||||
[--continue-on-failure]
|
||||
test_native_package.py: error: argument --exit-after-init: not allowed with argument --silent-workbench
|
||||
................................
|
||||
----------------------------------------------------------------------
|
||||
Ran 48 tests in 14.990s
|
||||
|
||||
OK
|
||||
.......
|
||||
----------------------------------------------------------------------
|
||||
Ran 7 tests in 0.293s
|
||||
|
||||
OK
|
||||
..............
|
||||
----------------------------------------------------------------------
|
||||
Ran 14 tests in 2.764s
|
||||
|
||||
OK
|
||||
....
|
||||
----------------------------------------------------------------------
|
||||
Ran 4 tests in 0.356s
|
||||
|
||||
OK
|
||||
....
|
||||
----------------------------------------------------------------------
|
||||
Ran 4 tests in 0.065s
|
||||
|
||||
OK
|
||||
PASS: actual finite-courier age, token, exact ownership/callback and delivered-status admission reject stale, replayed, captured, canceled and ambiguous work
|
||||
PASS: actual native-gun ownership gate rejects player/foreign/replaced/dead occupant, faction change, missing seat and missing registry
|
||||
PASS: four-battery courier selection preserves pending trip/report/transfer identity, skips unavailable crews, and selects the next depleted battery without new stock
|
||||
PASS: 64 bounded distinct storage candidates; native gates, five-store barrier and finite-stock ownership retained; native placement pending
|
||||
PASS: 128 coarse+80 local refinement+169 airport grid candidates retain all native clearance gates; real terrain untested
|
||||
PASS: actual prison registration/crossing policies reject missing/duplicate/destroyed initial gate, incomplete ownership/scan, outside-only body, jumps and stale samples; physical exit independent of later gate damage
|
||||
PASS: actual prison door execution blocks direct AI/UI bypass while locked and delegates unchanged native action once after unlock and permission approval
|
||||
..................
|
||||
----------------------------------------------------------------------
|
||||
Ran 18 tests in 2.353s
|
||||
|
||||
OK
|
||||
.....
|
||||
----------------------------------------------------------------------
|
||||
Ran 5 tests in 1.300s
|
||||
|
||||
OK
|
||||
PASS: native local-admission snapshot rejects changed life/key/body/participant/pending state; authentication is not simulated
|
||||
PASS: actual mortar report ledger prevents duplicate response after cancellation, expiry and interleaved reports; native scheduler separate
|
||||
.........
|
||||
----------------------------------------------------------------------
|
||||
Ran 9 tests in 0.015s
|
||||
|
||||
OK
|
||||
....
|
||||
----------------------------------------------------------------------
|
||||
Ran 4 tests in 0.185s
|
||||
|
||||
OK
|
||||
PASS: actual aim renewal requires fresh same-report solve and original-command equivalence; native firing untested
|
||||
........
|
||||
----------------------------------------------------------------------
|
||||
Ran 8 tests in 0.017s
|
||||
|
||||
OK
|
||||
PASS: actual startup/generation/ownership/timeout/callback policies and native-counter wait; integration preserves one-shot allocation and pending-crew cancellation
|
||||
PASS: rapid mortar cycle counts eight physical rounds once and waits for native completion without a ninth aim or shell
|
||||
PASS: actual probe binds native events to fresh immutable commits, permits delayed emission, rejects unrelated expiry closure and premature stop
|
||||
PASS: actual noSplash Load body requires both explicit diagnostic and noSplash, preserves vanilla otherwise, and handles repeated Load/reload
|
||||
PASS: actual fixture method permits one native resilience operation and restores either prior protection state, including failure paths
|
||||
PASS: actual safe-exit boundary policy, native action/door selection, stop/cache cleanup, separate old mechanism and opt-in runner contracts
|
||||
PASS: actual one-shot deadline/stability policies and preparation ownership, fuel, cleanup integration contracts
|
||||
PASS: pending-only cancellation retires copied instance intent, preserves physical/control actors, and stops once
|
||||
PASS: actual short-cast hit, upward support normal, no self support and no dynamic support
|
||||
PASS: actual committed-ticket structure preserves reservation after death, rejects missing bodies/seats and ends at observation expiry
|
||||
PASS: actual pending callback expires an empty-server reservation once, preserves its full lease, and cancels on completion/Stop
|
||||
PASS: rescue lease expiry/reordering, fresh five-second settling, independent rescue ranges and grounded upright aircraft motion boundaries
|
||||
PASS: requested guard population requires complete physical conscious membership before deadline
|
||||
......................................
|
||||
----------------------------------------------------------------------
|
||||
Ran 38 tests in 0.021s
|
||||
|
||||
OK
|
||||
..........
|
||||
----------------------------------------------------------------------
|
||||
Ran 10 tests in 0.003s
|
||||
|
||||
OK
|
||||
.....
|
||||
----------------------------------------------------------------------
|
||||
Ran 5 tests in 1.063s
|
||||
|
||||
OK
|
||||
PASS: authored radio/optional-site bounds and physical horizontal/vertical boundaries
|
||||
...
|
||||
----------------------------------------------------------------------
|
||||
Ran 3 tests in 0.001s
|
||||
|
||||
OK
|
||||
PASS: all phase transitions, terminal states, defence boundaries, stale/future observations, intel discovery
|
||||
PASS: Core document-discovery alias, companion-only alias exclusion, strict integer parsing and setting boundaries
|
||||
PASS: player admission phase/life/identity/controller matrix, preload displacement limits, pending reservation overlap and owner exclusion
|
||||
PASS: actual gate and pre-inventory document guards reject noncanonical/faction/life/disconnect/server mismatches; canonical reconnect and unconscious carried intel preserved
|
||||
PASS: WB-only native fault injection restores both body mutations before checks/returns and requires eligible held-document negative/positive proof; runtime pending
|
||||
PASS: actual discovery coordinates disclose stable 500m cell center until identified, then exact point, including negative/boundary coordinates
|
||||
PASS: actual local admission context/selection/latch, same-round late identity, replacement/mode failure, fresh round and untouched network path
|
||||
PASS: prison search packs 16 unique 3m-spaced inside-wall centers, prioritizes inner/edge positions and never bypasses clearance
|
||||
PASS: physical body occupancy rejects overlap, permits diagonal neighboring slots, and excludes own body and unrelated broad-phase bounds
|
||||
PASS: recovery state excludes dead bodies, preserves reservations, requires controlled rescuers and distinguishes empty/all-dead teams
|
||||
PASS: authority-scoped slow recovery, bleeding pauses resilience, medicine unaffected, player-only lethal damage cap without healing
|
||||
PASS: bleeding severity survives low health, retains armour, causes no knockout and restores the actual damage/blood-loss cap
|
||||
PASS: viable passive recovery survives native delay; bleeding, disabled/full effects and low-blood resilience do not block defeat
|
||||
PASS: every minute round-trips, malformed clocks rejected, defaults limited to added keys, progression bounds and day duration aligned
|
||||
PASS: native settings policy matches calendar boundaries 1900-2050, date/profile parsing is strict, authored defaults preserve old worlds
|
||||
PASS: view-distance bounds, default, save failures, command parsing, temporary ownership, server/platform limits and lifecycle wiring
|
||||
.....
|
||||
----------------------------------------------------------------------
|
||||
Ran 5 tests in 0.679s
|
||||
|
||||
OK
|
||||
.
|
||||
----------------------------------------------------------------------
|
||||
Ran 1 test in 0.434s
|
||||
|
||||
OK
|
||||
PASS: radio authorization/discovery/phase matrix, exact distance limits, defender handover, interruption, empty samples, clock regression and duration boundary
|
||||
PASS: actual radio feedback policy, initial wait, interruption persistence, resumption and terminal/new-round reset
|
||||
...............
|
||||
----------------------------------------------------------------------
|
||||
Ran 15 tests in 2.352s
|
||||
|
||||
OK
|
||||
..............................................
|
||||
----------------------------------------------------------------------
|
||||
Ran 46 tests in 1.151s
|
||||
|
||||
OK
|
||||
PASS: legacy values preserved, unsupported fields reported, invalid data rejected, existing files protected, runtime bounds aligned
|
||||
PASS: failed initial settings promotion leaves defaults writable after restart; prior/fallback saves survive copy, readback and mismatch faults
|
||||
PASS: real-carrier shortest-hop paths, 500m boundary, three-hop cap, no-manpack failure, three-second originating-call interruption, unchanged downlink hop timing, completed-hop survival, interrupted final uplink, radio loss, capture, motion, timeout, reset and network bounds
|
||||
PASS: migrated aircraft availability policy (controller migration still pending)
|
||||
PASS: migrated salvo offsets are deterministic, spread and bounded (native firing and complete salvo qualification are separate)
|
||||
PASS: 35 prefabs have unique saved root entity IDs
|
||||
PASS: 299 original script entries tracked across 18 unfinished responsibilities
|
||||
PASS: 1 isolated addons, acyclic dependencies, 58 unique resources, exact vanilla/authorized external references
|
||||
All repository checks passed. Native compilation and multiplayer tests are separate requirements.
|
||||
Suite exit 0 programs 305 unchanged True
|
||||
@@ -0,0 +1,14 @@
|
||||
from pathlib import Path
|
||||
import hashlib,json,sys,shutil
|
||||
R=Path('/home/jakub/devel/escapistsrereintroduced');B=Path('/tmp/erri-gameplay-root-1509')
|
||||
P=Path(sys.argv[1]);manifest=json.loads((P/'source-manifest.json').read_text())
|
||||
sha=lambda p:hashlib.sha256(p.read_bytes()).hexdigest()
|
||||
rows=manifest['files'];output=B/'integration.json';result=json.loads(output.read_text()) if output.exists() else {}
|
||||
for n,row in rows.items():
|
||||
assert n.startswith('addons/core/Scripts/Game/ERR/') or n.startswith('tests/') or n in {'tools/check.py','tools/source_bundle.py','tools/external_addons.py','tools/resource_references.py','docs/vanilla-resources.json'}
|
||||
assert n not in result
|
||||
assert (sha(R/n) if (R/n).exists() else None)==row['baseline_sha256'] and sha(P/n)==row['proposal_sha256']
|
||||
for n,row in rows.items():
|
||||
shutil.copyfile(P/n,R/n);assert sha(R/n)==row['proposal_sha256']
|
||||
result[n]={'before':row['baseline_sha256'],'after':sha(R/n),'proposal':str(P/n)}
|
||||
output.write_text(json.dumps(result,indent=2)+'\n');print('Integrated',len(rows),'files from',P)
|
||||
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"addons/core/Scripts/Game/ERR/00_Core/ERR_ProfileConfig.c": {
|
||||
"before": "ac28363fd5861523db278bb18aa5499f356fef69d35435d1f4ef547da704b67d",
|
||||
"after": "9df8ccf45fc2ed12f4b14d08270878696e8785760a3ae51fe032b6f3818fc0e6",
|
||||
"proposal": "/tmp/erri-config-review-1509/addons/core/Scripts/Game/ERR/00_Core/ERR_ProfileConfig.c"
|
||||
},
|
||||
"tests/test_profile_config.py": {
|
||||
"before": "088ea06a32a59711d8e02c426d5fdd4a14657cded725b831af312bd8eb5f133f",
|
||||
"after": "727dc330db23d744fca0c965474f834d0cb70432e58938f286fde28bd8415435",
|
||||
"proposal": "/tmp/erri-config-review-1509/tests/test_profile_config.py"
|
||||
},
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c": {
|
||||
"before": "1bfc1079961eaecee0c1ebb434570aaeb359c008f9f309033b33582092557b35",
|
||||
"after": "ca8eee2704e7758172e33014404bb1307c683f19b561b840d4592f6312051e62",
|
||||
"proposal": "/tmp/erri-ai-review-1509/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c"
|
||||
},
|
||||
"tests/test_infantry_resupply_planning.py": {
|
||||
"before": "20747ffda8754f81f3b9e9912b9f60a300c439f2ea2c473bb900302f61dd691f",
|
||||
"after": "9879a27816dbc6b9c4da19c4714407614b4c6e20b2dd831b2701e5f3500ede6a",
|
||||
"proposal": "/tmp/erri-ai-review-1509/tests/test_infantry_resupply_planning.py"
|
||||
},
|
||||
"tests/test_infantry_resupply_coordinator.py": {
|
||||
"before": "f9cf7d583a25a12cec9f5f80539b2590449560331f4ef34e33ea2db283c5d54a",
|
||||
"after": "a7eaa26e21f587fd8abde5dee6f7f8afc1e9f2f7ed0bcf40ed6a087a56908adc",
|
||||
"proposal": "/tmp/erri-ai-review-1509/tests/test_infantry_resupply_coordinator.py"
|
||||
},
|
||||
"tests/test_infantry_ammo_transfer.py": {
|
||||
"before": "0d2ebe4d5c18a4187745784013d07df621b8495967d0c01f39bd5a68ae574d26",
|
||||
"after": "18029a092262d0d1a309108a158597a174c1a05f58157eafd096c1c707fa0e29",
|
||||
"proposal": "/tmp/erri-ai-review-1509/tests/test_infantry_ammo_transfer.py"
|
||||
},
|
||||
"tools/resource_references.py": {
|
||||
"before": null,
|
||||
"after": "2e6080227bece7213fd67e58e7a4d27aba9847e610f8c000f6f2f65b623e567c",
|
||||
"proposal": "/tmp/erri-optional-identity-1509/tools/resource_references.py"
|
||||
},
|
||||
"tools/check.py": {
|
||||
"before": "d60357b1c6b0d61dfeb80148d4a6684121e468bd3a044a9adc8f76752f60a41a",
|
||||
"after": "fb6bf594dd6544abee60d4e172d1d28f34f223cae93678e2356156f34e653f00",
|
||||
"proposal": "/tmp/erri-optional-identity-1509/tools/check.py"
|
||||
},
|
||||
"tools/source_bundle.py": {
|
||||
"before": "e8b06f9340a8d67da992373f4642385a028acebe9aa1b3752f62cab95c8fce98",
|
||||
"after": "5d1d0150d8009f24a950ee85501d0da8b1f69d5fcbb5a7118b08957f14658f57",
|
||||
"proposal": "/tmp/erri-optional-identity-1509/tools/source_bundle.py"
|
||||
},
|
||||
"tests/test_external_addons.py": {
|
||||
"before": "4e2c3fa2c92661c49ea0c492648b736bebd54f24cd244f3fe27710a0c7a487ab",
|
||||
"after": "4b0eb867b3aec1bca906f68168948a4e42cdc0bced0bec2856a3ba68187a6e24",
|
||||
"proposal": "/tmp/erri-optional-identity-1509/tests/test_external_addons.py"
|
||||
},
|
||||
"docs/vanilla-resources.json": {
|
||||
"before": "588192d151f382b612ca6ce9a564193b57d4a9e7ce9a3918bf8ad2f7e877d1f4",
|
||||
"after": "e10f60ce74a743b4619b0c2f2cc7fefcf09a94ab3ca1cbb332f386d6fb0da387",
|
||||
"proposal": "/tmp/erri-optional-identity-1509/docs/vanilla-resources.json"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"native_check_started": false,
|
||||
"reason": "Read-only host preflight found an existing Arma Reforger game (PID1451030); left untouched. No launch, window, input, audio or process changes.",
|
||||
"compile_or_gameplay_proof": false,
|
||||
"prefix_process_check": "clear"
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"project_path": "/tmp/erri-reaper-native/first/addons/REAPER_CORE_5EB139459EBF5C16/addon.gproj",
|
||||
"project_sha256": "9a50e425661956163ef2d74336df656a3c62ad696253a83b3f0b51b9b56d8ee3",
|
||||
"rdb_path": "/tmp/erri-reaper-native/first/addons/REAPER_CORE_5EB139459EBF5C16/resourceDatabase.rdb",
|
||||
"rdb_sha256": "ef07f7be363b3857ca217cd0520fb851ce980f34fc5f121b8350f4c84ee6c414",
|
||||
"resource_path": "Prefabs/Characters/REAPER_SpectatorCameraHelper.et",
|
||||
"resource_guid": "574AA64002B8E308",
|
||||
"matching_records": 1,
|
||||
"assets_copied": false
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"docs/configuration.md": {
|
||||
"before": "3f6612dcb7366e2279b81a8b7b4b0e5f80bafeb94199633f55470ebde6acd253",
|
||||
"after": "5b94830326f8cfee366b131fd3a1fa7b5a74ebda808c2839929125e183417551"
|
||||
},
|
||||
"docs/infantry-resupply.md": {
|
||||
"before": "269d00c4397a04018c4366bf1c4be52bd290561b4484210442713ff641dfc74e",
|
||||
"after": "bb9c68e634ceb27c9501be1b8ed43e35229269d0889a5152360ebeb213004e7b"
|
||||
},
|
||||
"docs/current-status.md": {
|
||||
"before": "5d4494b599f9379ef137222230ae0ea79d579e7a032772aa97de0138138b319c",
|
||||
"after": "a1c648325198a83030b83b3684f94500548b289513e8f034266aa03432a5da91"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
from pathlib import Path
|
||||
import hashlib,json,importlib.util,shutil
|
||||
B=Path('/tmp/erri-gameplay-root-1509');R=Path('/home/jakub/devel/escapistsrereintroduced');D=R/'docs/evidence/config-supply-recovery-2026-10-03'
|
||||
sha=lambda p:hashlib.sha256(p.read_bytes()).hexdigest()
|
||||
r=json.loads((D/'review.json').read_text());assert not (D/'artifact-sha256.json').exists()
|
||||
assert len(r['archive_files'])==78 and all(sha(D/n)==h for n,h in r['archive_files'].items())
|
||||
assert sha(D/'archive.py')=='ab8e51ac288a529ead61c498d6286d0e19b408cefaeaf42a609c2634c4f5813a'
|
||||
assert all(sha(R/n)==v['after'] for n,v in json.loads((B/'integration.json').read_text()).items())
|
||||
recovery={'reason':'Archive copies and directory rename completed, but local candidate-manifest variable seal shadowed seal() and prevented the final artifact index. Error cleanup also referred to already-renamed staging directory. No archived payload was lost. Documentation updates subsequently completed; attempted finalize refused the absent artifact index.','copied_payloads_verified':78,'production_inputs_unchanged':True,'original_failed_helper_preserved':'archive.py','correction':'Rename sealing function to seal_archive and check staging exists before error cleanup. Validate every copied payload before recovering initial seal; ordinary finalization independently verifies post-suite documentation delta and preservation.','native_or_test_failure':False}
|
||||
(D/'archive-recovery.json').write_text(json.dumps(recovery,indent=2)+'\n')
|
||||
shutil.copyfile(B/'archive.py',D/'root/archive-recovery.py')
|
||||
shutil.copyfile(Path(__file__),D/'root/recover-archive.py')
|
||||
spec=importlib.util.spec_from_file_location('recover',B/'archive.py');m=importlib.util.module_from_spec(spec);spec.loader.exec_module(m);m.seal_archive()
|
||||
print('Recovered artifact index after verifying all78 copied payloads; original failed helper retained')
|
||||
@@ -0,0 +1,35 @@
|
||||
from pathlib import Path
|
||||
import sys,hashlib,json,subprocess,importlib.util,time,traceback,os
|
||||
R=Path('/home/jakub/devel/escapistsrereintroduced');B=Path('/tmp/erri-gameplay-root-1509');sys.path.insert(0,str(R/'tools'))
|
||||
sha=lambda p:hashlib.sha256(p.read_bytes()).hexdigest()
|
||||
from source_manifest import addon_manifest
|
||||
def capture_inputs():
|
||||
result=addon_manifest(R)
|
||||
for folder in ['tests','tools','terrain-profiles','terrain-adapters','terrain-integrations']:
|
||||
result.update({str(p.relative_to(R)):sha(p) for p in (R/folder).rglob('*') if p.is_file() and '__pycache__' not in p.parts and p.suffix != '.pyc'})
|
||||
result.update({str(p.relative_to(R)):sha(p) for p in (R/'docs').iterdir() if p.is_file()})
|
||||
for name in ['README.md','.gitignore']: result[name]=sha(R/name)
|
||||
return result
|
||||
inputs=capture_inputs()
|
||||
(B/'suite-inputs.json').write_text(json.dumps(inputs,indent=2)+'\n')
|
||||
removed_overrides={key:os.environ.pop(key) for key in list(os.environ) if key.startswith('ERR_')}
|
||||
original=subprocess.run;programs=[]
|
||||
def track(args,*a,**kw):
|
||||
entry=None
|
||||
if isinstance(args,list) and len(args)>1 and str(args[1]).startswith(str(R/'tests')+'/'):
|
||||
entry={'path':str(Path(args[1]).relative_to(R)),'exit':None};programs.append(entry)
|
||||
try:result=original(args,*a,**kw)
|
||||
except subprocess.CalledProcessError as error:
|
||||
if entry is not None:entry['exit']=error.returncode
|
||||
raise
|
||||
if entry is not None:entry['exit']=result.returncode
|
||||
return result
|
||||
subprocess.run=track
|
||||
spec=importlib.util.spec_from_file_location('repository_check',R/'tools/check.py');module=importlib.util.module_from_spec(spec);spec.loader.exec_module(module)
|
||||
code=0;started=time.monotonic()
|
||||
try:module.check()
|
||||
except Exception:traceback.print_exc();code=1
|
||||
unchanged=capture_inputs()==inputs;code=code or int(not unchanged)
|
||||
(B/'suite-result.json').write_text(json.dumps({'exit':code,'seconds':round(time.monotonic()-started,2),'inputs_unchanged':unchanged,'removed_override_names':sorted(removed_overrides),'regression_programs':len(programs),'programs':programs},indent=2)+'\n')
|
||||
print('Suite exit',code,'programs',len(programs),'unchanged',unchanged)
|
||||
raise SystemExit(code)
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,18 @@
|
||||
from pathlib import Path
|
||||
import json,hashlib
|
||||
R=Path('/home/jakub/devel/escapistsrereintroduced');B=Path('/tmp/erri-gameplay-root-1509')
|
||||
suite=json.loads((B/'suite-result.json').read_text());assert suite['exit']==0 and suite['inputs_unchanged']
|
||||
assert (R/'docs/evidence/config-supply-recovery-2026-10-03/README.md').is_file()
|
||||
sha=lambda p:hashlib.sha256(p.read_bytes()).hexdigest()
|
||||
changes={}
|
||||
p=R/'docs/configuration.md';old=p.read_text();needle='allows recovery from a damaged primary. Unsupported schema versions are kept\nread-only. Unknown fields and preferences for absent mods are retained.'
|
||||
assert old.count(needle)==1
|
||||
new=old.replace(needle,needle+'\n\nA malformed known section also prevents unrelated menu changes from being saved.\nThis preserves the last valid backup instead of replacing it with damaged data.\nRepair invalid sections while the mission is stopped; a valid replacement for the\nonly damaged section can also be saved through its existing menu. Successful repair\nkeeps the good backup, and subsequent ordinary saves resume normal backup rotation.\nMissing optional sections still use defaults, and unknown fields remain intact.',1)
|
||||
changes[str(p.relative_to(R))]={'before':sha(p)};p.write_text(new);changes[str(p.relative_to(R))]['after']=sha(p)
|
||||
p=R/'docs/infantry-resupply.md';old=p.read_text()
|
||||
append='''\n\n## Ordinary ammunition claims survive unresolved cancellation — 3 October 2026\n\nAn interrupted ordinary rifle-magazine trip now retains its exact recipient and\ntruck reservations while its existing transfer leaf reports an unresolved native\noperation. Previously only mine and launcher trips retained these claims, allowing\na later truck to reserve the same group while an accepted empty-magazine return\nwas still pending. Owned waypoints and the downlink are cleared immediately. The\nexisting polling path releases only matching claims when the leaf settles; stopped\nservices also continue this observation. No new submission, refund, replacement\nstock or late success is granted. The leaf's existing custody and callback rules\nare unchanged.\n\nThe recorded source regression checks cover delayed settlement, competing claims\nand cancellation. Native transfers, real convoy movement and multiplayer remain\nunverified for this change; an existing game prevented isolated engine checks.\n[Exact source and regression checkpoint](evidence/config-supply-recovery-2026-10-03/README.md).\n'''
|
||||
changes[str(p.relative_to(R))]={'before':sha(p)};p.write_text(old+append);changes[str(p.relative_to(R))]['after']=sha(p)
|
||||
p=R/'docs/current-status.md';old=p.read_text();head='# Current development status\n\n';assert old.startswith(head)
|
||||
text=f'''**3 October 2026 — configuration recovery and interrupted rifle resupply corrected:** changing one setting can no longer overwrite the only valid backup of another malformed section. Invalid recognized sections block unrelated saves before disk writes; repairing the damaged section preserves the good backup. Ordinary ammunition trips now retain their exact truck and recipient claims while an accepted native move remains unresolved, preventing a second supply job from racing the first. Existing finite stock, radio demand, deadlines and transfer rules remain in place.\n\nAll **{suite['regression_programs']} registered regression programs pass** on the recorded unchanged snapshot. Baseline failures and focused controls reproduce both bugs. Repository and source-bundle validation now recognize one audited optional resource-name comparison without adding a runtime dependency, and the existing vanilla character load has verified resource metadata. The initial validation failure remains archived. A separate bounded base-loop review found no new demonstrated defect in radio defence, extraction ordering, player identity or terminal cleanup. Native checks were deferred because an existing game was running; no window, input, audio or process changes were made. Native transfers, manual escape, multiplayer and FPS remain unqualified. The sealed development packages predate these source changes. [Implementation and evidence](evidence/config-supply-recovery-2026-10-03/README.md).\n\n'''
|
||||
changes[str(p.relative_to(R))]={'before':sha(p)};p.write_text(head+text+old[len(head):]);changes[str(p.relative_to(R))]['after']=sha(p)
|
||||
(B/'post-suite-docs.json').write_text(json.dumps(changes,indent=2)+'\n');print(json.dumps(changes,indent=2))
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"rdb_path": "/home/jakub/.local/share/Steam/steamapps/common/Arma Reforger/addons/data/resourceDatabase.rdb",
|
||||
"rdb_sha256": "c5344847875ab4c94cf3cda88c5f9cc60878b799f33b2137c8e4a18726c19b7c",
|
||||
"resource_path": "Prefabs/Characters/Core/Character_Base.et",
|
||||
"resource_guid": "37578B1666981FCE",
|
||||
"matching_records": 1,
|
||||
"assets_copied": false
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
check: /tmp/err-policy-y3myg15e/check.cpp:566: int main(): Assertion `!second.s.TryPlan(&first.recipient,&second.donor,&first.demand,&second.donorStatus,180001)' failed.
|
||||
Traceback (most recent call last):
|
||||
File "/tmp/erri-ai-review-1509/tests/test_infantry_resupply_planning.py", line 48, in <module>
|
||||
run(r'''
|
||||
~~~^^^^^
|
||||
#include <cassert>
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
...<252 lines>...
|
||||
}
|
||||
^
|
||||
''')
|
||||
^^^^
|
||||
File "/home/jakub/devel/escapistsrereintroduced/tests/policy_harness.py", line 14, in run
|
||||
subprocess.run([str(p/'check')],check=True)
|
||||
~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
File "/usr/lib/python3.14/subprocess.py", line 578, in run
|
||||
raise CalledProcessError(retcode, process.args,
|
||||
output=stdout, stderr=stderr)
|
||||
subprocess.CalledProcessError: Command '['/tmp/err-policy-y3myg15e/check']' died with <Signals.SIGABRT: 6>.
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c": {
|
||||
"working_sha256": "1bfc1079961eaecee0c1ebb434570aaeb359c008f9f309033b33582092557b35",
|
||||
"index_sha256": "966068555a6724e620a2c377b98d8dc02f141466c5cdd44636f86cb1cfe9ac78"
|
||||
},
|
||||
"tests/test_infantry_resupply_planning.py": {
|
||||
"working_sha256": "20747ffda8754f81f3b9e9912b9f60a300c439f2ea2c473bb900302f61dd691f",
|
||||
"index_sha256": "211e3d0ee20242f271afc46885e1ba7845ff2406d663bfe5118f40578cd5d709"
|
||||
},
|
||||
"tests/test_infantry_resupply_coordinator.py": {
|
||||
"working_sha256": "f9cf7d583a25a12cec9f5f80539b2590449560331f4ef34e33ea2db283c5d54a",
|
||||
"index_sha256": "65fa119778289175766ba7fdecd9e5685199736dffecc32056692121cbc6a682"
|
||||
},
|
||||
"tests/test_infantry_ammo_transfer.py": {
|
||||
"working_sha256": "0d2ebe4d5c18a4187745784013d07df621b8495967d0c01f39bd5a68ae574d26",
|
||||
"index_sha256": "e1172dda6350d2f8b89166ba63995cd1590435930ba220cd38b022307103a306"
|
||||
}
|
||||
}
|
||||
+592
@@ -0,0 +1,592 @@
|
||||
// HQ-owned ground rendezvous using delivered positions and existing finite cargo.
|
||||
class ERR_InfantryResupplyRules
|
||||
{
|
||||
static bool Fresh(ERR_HQWatchEntry entry, float now)
|
||||
{
|
||||
return entry && !entry.Closed && entry.Count > 0 && entry.Fit > 0
|
||||
&& ERR_ForceRules.Finite(now) && entry.ObservedAt >= 0 && now >= entry.ObservedAt
|
||||
&& now - entry.ObservedAt <= 120000 && ERR_ForceRules.FiniteVector(entry.Position);
|
||||
}
|
||||
static bool Need(ERR_HQWatchEntry entry, float now)
|
||||
{
|
||||
return Fresh(entry, now) && entry.AmmoState && entry.AmmoState.Valid(entry.Count)
|
||||
&& entry.AmmoState.Complete && entry.AmmoState.Members == entry.Count
|
||||
&& entry.AmmoState.SmallArmsMuzzles > 0
|
||||
&& entry.AmmoState.SmallArmsRounds + entry.AmmoState.SmallArmsChambers <= entry.Count * 30;
|
||||
}
|
||||
// Only positively sampled reloadable magazine-well muzzles establish launcher demand.
|
||||
static bool LauncherNeed(ERR_HQWatchEntry entry, float now)
|
||||
{
|
||||
return Fresh(entry, now) && entry.AmmoState && entry.AmmoState.Valid(entry.Count)
|
||||
&& entry.AmmoState.LauncherComplete && entry.AmmoState.Members == entry.Count
|
||||
&& entry.AmmoState.LauncherMuzzles > 0
|
||||
&& entry.AmmoState.LauncherRounds == 0 && entry.AmmoState.LauncherChambers == 0;
|
||||
}
|
||||
static bool LauncherPair(ERR_HQWatchEntry recipient, ERR_HQWatchEntry donor, float now)
|
||||
{
|
||||
return LauncherNeed(recipient, now) && Fresh(donor, now) && recipient.SourceId != donor.SourceId
|
||||
&& vector.DistanceXZ(recipient.Position, donor.Position) <= 200;
|
||||
}
|
||||
static bool MinePair(ERR_HQWatchEntry recipient, ERR_HQWatchEntry donor, float now)
|
||||
{
|
||||
return Fresh(recipient, now) && Fresh(donor, now) && recipient.SourceId != donor.SourceId
|
||||
&& recipient.AmmoState && recipient.AmmoState.Valid(recipient.Count)
|
||||
&& recipient.AmmoState.MineComplete && recipient.AmmoState.MineMembers == recipient.Count
|
||||
&& recipient.AmmoState.ReadyMines <= 1 && vector.DistanceXZ(recipient.Position, donor.Position) <= 200;
|
||||
}
|
||||
static bool Pair(ERR_HQWatchEntry recipient, ERR_HQWatchEntry donor, float now)
|
||||
{
|
||||
return Need(recipient, now) && Fresh(donor, now) && recipient.SourceId != donor.SourceId
|
||||
&& vector.DistanceXZ(recipient.Position, donor.Position) <= 200;
|
||||
}
|
||||
}
|
||||
|
||||
class ERR_InfantryResupply
|
||||
{
|
||||
protected ERR_HQ m_HQ;
|
||||
protected ERR_GameMode m_Mode;
|
||||
protected ERR_ConvoyTask m_Convoy;
|
||||
protected int m_ConvoySlot = -1;
|
||||
protected ERR_ConvoyVehicle m_Truck;
|
||||
protected ERR_HQUnit m_Recipient;
|
||||
protected ERR_HQUnit m_Donor;
|
||||
protected ref array<IEntity> m_Stock = {};
|
||||
protected ref array<IEntity> m_Spent = {};
|
||||
protected ref array<IEntity> m_MineStock = {};
|
||||
protected ref ERR_ConvoyMineStock m_MineBatch;
|
||||
protected bool m_MineStockCaptured;
|
||||
protected bool m_MineTrip;
|
||||
protected bool m_LauncherTrip;
|
||||
protected int m_MineRecipientSlot = -1;
|
||||
protected bool m_EmptyMineReplacement;
|
||||
protected int m_MinesDelivered;
|
||||
protected ref array<IEntity> m_Members = {};
|
||||
protected ref array<IEntity> m_Served = {};
|
||||
protected ref map<string, int> m_Consumed = new map<string, int>();
|
||||
protected ref map<string, float> m_NextAttempt = new map<string, float>();
|
||||
protected ref ERR_HQRoute m_Order;
|
||||
protected ref ERR_InfantryAmmoTransfer m_Move;
|
||||
protected ref ERR_InfantryMineTransfer m_MineMove;
|
||||
protected ref ERR_MountedResupply m_Mounted;
|
||||
protected IEntity m_Receiving;
|
||||
protected AIWaypoint m_MoveWaypoint;
|
||||
protected AIWaypoint m_HoldWaypoint;
|
||||
protected vector m_Rendezvous;
|
||||
protected int m_State; // 0 stock startup, 1 idle, 2 truck downlink, 3 stopped status, 4 infantry downlink, 5 transfer, 7 unresolved item custody
|
||||
protected int m_Trip;
|
||||
protected int m_Token;
|
||||
protected int m_ReportId;
|
||||
protected int m_Delivered;
|
||||
protected int m_TripDelivered;
|
||||
protected float m_Deadline;
|
||||
protected float m_StockDeadline = -1;
|
||||
protected float m_HeldAt;
|
||||
protected float m_NextTick;
|
||||
protected bool m_Stopped;
|
||||
protected string m_Reason;
|
||||
void ERR_InfantryResupply(ERR_HQ hq, ERR_GameMode mode) { m_HQ = hq; m_Mode = mode; }
|
||||
// Bind before startup; every coordinator retains its exact finite convoy identity.
|
||||
bool Bind(ERR_ConvoyTask task, int slot, map<string, int> consumed, map<string, float> nextAttempt)
|
||||
{
|
||||
if (!task || !consumed || !nextAttempt || !m_HQ || !m_HQ.Convoys() || slot < 0 || slot >= 20
|
||||
|| slot >= m_HQ.Convoys().Count() || m_HQ.Convoys().At(slot) != task) return false;
|
||||
if (m_Stopped || m_Convoy || m_ConvoySlot >= 0 || m_State != 0 || m_Trip != 0 || m_NextTick != 0
|
||||
|| m_StockDeadline >= 0 || !m_Stock.IsEmpty() || m_Move || m_Truck) return false;
|
||||
m_Convoy = task; m_ConvoySlot = slot; m_Consumed = consumed; m_NextAttempt = nextAttempt;
|
||||
return true;
|
||||
}
|
||||
ERR_ConvoyTask Task() { return m_Convoy; }
|
||||
int State()
|
||||
{
|
||||
if (m_Mounted && m_Mounted.Busy()) return 6;
|
||||
return m_State;
|
||||
}
|
||||
ERR_MountedResupply Mounted() { return m_Mounted; }
|
||||
bool Unresolved() { return (m_Move && m_Move.Unresolved()) || (m_MineMove && m_MineMove.Unresolved()) || (m_Mounted && m_Mounted.Unresolved()); }
|
||||
protected void PollTransfers(float now)
|
||||
{
|
||||
if (m_Mounted) m_Mounted.Tick(now);
|
||||
if (m_Move && !m_Move.Unresolved() && (m_State <= 1 || (m_State == 7 && m_LauncherTrip)))
|
||||
{
|
||||
m_Move = null;
|
||||
if (m_State == 7) Finish("launcher custody settled; original claims released without retry or refund");
|
||||
}
|
||||
if (m_MineMove && !m_MineMove.Unresolved() && (m_State <= 1 || m_State == 7))
|
||||
{
|
||||
m_MineMove = null;
|
||||
if (m_State == 7) Finish("mine custody settled; original claims released without retry or refund");
|
||||
}
|
||||
}
|
||||
int Delivered() { return m_Delivered; }
|
||||
int MinesDelivered() { return m_MinesDelivered; }
|
||||
int StockCount() { return m_Stock.Count(); }
|
||||
// Admission uses the existing array object so an already-created mounted
|
||||
// coordinator observes this exact finite addition without a replacement ledger.
|
||||
protected int m_DepotImports;
|
||||
protected int m_DepotMineImports;
|
||||
bool DepotCurrent()
|
||||
{
|
||||
return Current() && m_State == 1 && !m_Move && !m_MineMove && !Unresolved()
|
||||
&& (!m_Mounted || !m_Mounted.Busy()) && TruckValid(true);
|
||||
}
|
||||
bool DepotAvailable() { return DepotCurrent() && m_Stock.Count() < 96 && m_Spent.Count() < 96; }
|
||||
bool DepotNeeded()
|
||||
{
|
||||
if (!DepotAvailable()) return false;
|
||||
int committed;
|
||||
foreach (IEntity item : m_Spent)
|
||||
if (item && m_Stock.Contains(item)) committed++;
|
||||
return committed > m_DepotImports;
|
||||
}
|
||||
// Mine imports replace only proved outgoing original mine commitments.
|
||||
// Keep the startup batch binding and both lifetime identity/spent ceilings.
|
||||
bool DepotMineAvailable()
|
||||
{
|
||||
return DepotCurrent() && CaptureMines() && m_MineStock.Count() < 96 && m_Spent.Count() < 96;
|
||||
}
|
||||
bool DepotMineNeeded()
|
||||
{
|
||||
if (!DepotMineAvailable()) return false;
|
||||
int committed;
|
||||
foreach (IEntity item : m_Spent)
|
||||
if (item && m_MineStock.Contains(item)) committed++;
|
||||
return committed > m_DepotMineImports;
|
||||
}
|
||||
bool AdmitDepotMine(ERR_GroundDepotLoading job, IEntity item)
|
||||
{
|
||||
if (!job || !DepotMineNeeded() || !ERR_InfantryMineTransfer.ReadyMine(item)
|
||||
|| m_MineStock.Contains(item) || m_Stock.Contains(item) || m_Spent.Contains(item)) return false;
|
||||
if (!job.DeliveredTo(this, item, true) || !Contains(m_Truck.Entity, item)
|
||||
|| !ERR_InfantryAmmoTransfer.StoredUnder(item, m_Truck.Entity)) return false;
|
||||
InventoryItemComponent carried = InventoryItemComponent.Cast(item.FindComponent(InventoryItemComponent));
|
||||
if (!carried || !carried.GetParentSlot() || carried.GetParentSlot().GetAttachedEntity() != item) return false;
|
||||
m_MineStock.Insert(item); m_DepotMineImports++;
|
||||
Audit("one exact finite camp PMN4 admitted after proved physical courier delivery");
|
||||
return true;
|
||||
}
|
||||
ERR_ConvoyVehicle DepotTruck()
|
||||
{
|
||||
if (!DepotCurrent()) return null;
|
||||
return m_Truck;
|
||||
}
|
||||
bool AdmitDepot(ERR_GroundDepotLoading job, IEntity item)
|
||||
{
|
||||
if (!job || !DepotAvailable() || !item || m_Stock.Contains(item) || m_Spent.Contains(item)) return false;
|
||||
if (!job.DeliveredTo(this, item) || !Contains(m_Truck.Entity, item)) return false;
|
||||
m_Stock.Insert(item); m_DepotImports++; Audit("one exact finite camp magazine admitted after proved physical courier delivery");
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void Audit(string reason)
|
||||
{
|
||||
if (m_MineTrip) reason = "mine top-up: " + reason;
|
||||
if (m_LauncherTrip) reason = "depleted launcher magazine: " + reason;
|
||||
m_Reason = reason;
|
||||
m_HQ.Journal().Write("INFANTRY SUPPLY", string.Format("convoy-slot=%1 trip=%2 state=%3 moved=%4 spent=%5/%6; %7", m_ConvoySlot, m_Trip, m_State, m_Delivered, m_Spent.Count(), m_Stock.Count(), reason), m_ReportId);
|
||||
}
|
||||
protected bool Current()
|
||||
{
|
||||
return !m_Stopped && Replication.IsServer() && m_Mode && m_Mode == ERR_GameMode.Get() && m_Mode.Active();
|
||||
}
|
||||
protected bool Contains(IEntity owner, IEntity item)
|
||||
{
|
||||
if (!owner || !item) return false;
|
||||
InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(owner.FindComponent(InventoryStorageManagerComponent));
|
||||
if (!inventory) return false;
|
||||
array<IEntity> items = {}; ERR_Inventory.Items(inventory, items);
|
||||
return items.Count() <= 128 && items.Contains(item);
|
||||
}
|
||||
protected bool ConvoyCurrent()
|
||||
{
|
||||
if (!m_HQ || !m_Convoy) return false;
|
||||
if (m_ConvoySlot < 0) return m_HQ.ConvoyTask() == m_Convoy;
|
||||
return m_HQ.Convoys() && m_ConvoySlot < m_HQ.Convoys().Count() && m_HQ.Convoys().At(m_ConvoySlot) == m_Convoy;
|
||||
}
|
||||
protected bool TruckValid(bool allowArrived = false)
|
||||
{
|
||||
if (!m_Convoy || m_Convoy.Stopped || !m_Convoy.Ready || !m_Convoy.Receipt || !m_Convoy.Receipt.Consumed
|
||||
|| !ConvoyCurrent() || m_Convoy.Vehicles.Count() != 6 || m_Convoy.Vehicles[1] != m_Truck) return false;
|
||||
if (!m_Truck || m_Truck.Index != 1 || !m_Truck.Registered || m_Truck.Released || (m_Truck.Arrived && !allowArrived)
|
||||
|| !m_Truck.CrewValid(m_Mode) || ERR_ConvoyRules.Captured(m_Truck.Entity, m_Truck.Group)) return false;
|
||||
ERR_ForceRecord record = m_Mode.Forces().FindGroup(m_Truck.Group);
|
||||
return record && record.Physical && !record.Eliminated && record.Kind == ERR_ForceKind.CONVOY
|
||||
&& m_Convoy.Receipt.Records.Count() >= 6 && record.Id == m_Convoy.Receipt.Records[1];
|
||||
}
|
||||
protected bool Quiet(ERR_HQUnit unit)
|
||||
{
|
||||
return unit && unit.Group && unit.Utility && !unit.Group.IsSlave() && unit.Group.GetPlayerCount(true) == 0
|
||||
&& unit.Group.GetFaction() == m_Mode.EnemyFaction()
|
||||
&& (!unit.Utility.m_Perception || unit.Utility.m_Perception.m_aTargets.IsEmpty());
|
||||
}
|
||||
protected bool Roster()
|
||||
{
|
||||
if (!m_Recipient || !Quiet(m_Recipient) || !m_Recipient.StatusSampler.OwnsRoster(m_Recipient.Group)) return false;
|
||||
int strength = m_Recipient.StatusSampler.InitialStrength();
|
||||
if (strength < 1 || strength > 32) return false;
|
||||
array<AIAgent> agents = {}; m_Recipient.Group.GetAgents(agents);
|
||||
if (agents.IsEmpty() || agents.Count() > 32) return false;
|
||||
foreach (AIAgent agent : agents)
|
||||
if (!agent || !m_Members.Contains(agent.GetControlledEntity())) return false;
|
||||
bool living;
|
||||
foreach (IEntity actor : m_Members)
|
||||
{
|
||||
if (!actor || !ERR_Actors.Alive(actor)) continue;
|
||||
// Returning to the group cannot undo a sampler's permanent release of an
|
||||
// original slot after transfer or player control during this trip.
|
||||
bool attributed = false;
|
||||
for (int slot = 0; slot < strength; slot++)
|
||||
{
|
||||
if (m_Recipient.StatusSampler.InitialMember(slot) != actor) continue;
|
||||
attributed = m_Recipient.StatusSampler.CanAttribute(slot, actor);
|
||||
break;
|
||||
}
|
||||
if (!attributed) return false;
|
||||
if (ERR_Actors.Player(actor) || ERR_Actors.Group(actor) != m_Recipient.Group
|
||||
|| SCR_FactionManager.SGetFaction(actor) != m_Mode.EnemyFaction() || CompartmentAccessComponent.GetVehicleIn(actor)) return false;
|
||||
if (ERR_Actors.CanFight(actor)) living = true;
|
||||
}
|
||||
return living;
|
||||
}
|
||||
protected void Stock(float now)
|
||||
{
|
||||
if (!m_Convoy) m_Convoy = m_HQ.ConvoyTask();
|
||||
if (m_Convoy && !ConvoyCurrent()) { Stop(); return; }
|
||||
if (!m_Convoy || !m_Convoy.Ready || m_Convoy.Vehicles.Count() != 6) return;
|
||||
m_Truck = m_Convoy.Vehicles[1];
|
||||
if (!TruckValid()) { Stop(); return; }
|
||||
// Cargo has a later, separately bounded lifecycle than native crew admission.
|
||||
// Supply convoys first request faction weapons, then their matching magazines.
|
||||
if (m_StockDeadline < 0) m_StockDeadline = now + 90000;
|
||||
if (now >= m_StockDeadline) { Stop(); return; }
|
||||
if (!m_Convoy.CargoIssued) return;
|
||||
ERR_SupplyConvoyTask supply = ERR_SupplyConvoyTask.Cast(m_Convoy);
|
||||
if (supply && !supply.MagazinesIssued) return;
|
||||
if (supply) m_MineBatch = supply.MineStock;
|
||||
foreach (ERR_ConvoyCargoCallback operation : m_Convoy.Cargo)
|
||||
if (!operation.Finished) return;
|
||||
InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(m_Truck.Entity.FindComponent(InventoryStorageManagerComponent));
|
||||
if (!inventory) { Stop(); return; }
|
||||
array<IEntity> items = {}; ERR_Inventory.Items(inventory, items);
|
||||
if (items.Count() > 128) { Stop(); return; }
|
||||
foreach (IEntity item : items)
|
||||
{
|
||||
if (!item || !item.FindComponent(BaseMagazineComponent)) continue;
|
||||
if (m_Stock.Count() >= 96) { Stop(); return; }
|
||||
m_Stock.Insert(item);
|
||||
}
|
||||
m_State = 1; Audit("truck magazine identities captured once after startup; absent/looted stock is never replaced");
|
||||
}
|
||||
bool TryPlan(ERR_HQUnit recipient, ERR_HQUnit donor, ERR_HQWatchEntry demand, ERR_HQWatchEntry donorStatus, float now, bool mineTrip = false, bool launcherTrip = false)
|
||||
{
|
||||
if (!Current() || m_State != 1 || m_Move || m_MineMove || (m_Mounted && m_Mounted.Busy()) || m_Trip >= 128 || !TruckValid()) return false;
|
||||
if ((mineTrip && launcherTrip) || m_Truck.Combat.Held || m_Truck.SupplyToken > 0 || !recipient || !donor) return false;
|
||||
if (donor.Group != m_Truck.Group || recipient.HomeGuard || !Quiet(recipient) || !Quiet(donor)) return false;
|
||||
if (donor.Downlink || donor.PendingOrder || donor.PendingConvoyOrder) return false;
|
||||
if (mineTrip)
|
||||
{
|
||||
if (!ERR_InfantryResupplyRules.MinePair(demand, donorStatus, now)) return false;
|
||||
// Empty reports authorize only an original startup-designated engineer.
|
||||
// This reads retained entitlement, never live positions/inventory for planning.
|
||||
if (demand.AmmoState.ReadyMines == 0)
|
||||
{
|
||||
bool designated;
|
||||
for (int member = 0; member < recipient.StatusSampler.InitialStrength() && member < 32; member++)
|
||||
{
|
||||
IEntity original = recipient.StatusSampler.InitialMember(member);
|
||||
if (original && recipient.StatusSampler.CanAttribute(member, original)
|
||||
&& m_HQ.MineSupplyReady(recipient.Group, original, true)) { designated = true; break; }
|
||||
}
|
||||
if (!designated) return false;
|
||||
}
|
||||
}
|
||||
else if (launcherTrip)
|
||||
{
|
||||
if (!ERR_InfantryResupplyRules.LauncherPair(demand, donorStatus, now)) return false;
|
||||
}
|
||||
else if (!ERR_InfantryResupplyRules.Pair(demand, donorStatus, now)) return false;
|
||||
if (demand.SourceId != recipient.ForceSourceId || donorStatus.SourceId != donor.ForceSourceId) return false;
|
||||
if (demand.MessageId <= m_Consumed.Get(demand.SourceId) || now < m_NextAttempt.Get(demand.SourceId)) return false;
|
||||
bool available;
|
||||
if (mineTrip)
|
||||
{
|
||||
if (!CaptureMines()) return false;
|
||||
foreach (IEntity mine : m_MineStock)
|
||||
if (ERR_InfantryMineTransfer.ReadyMine(mine) && !m_Spent.Contains(mine) && Contains(m_Truck.Entity, mine)) { available = true; break; }
|
||||
}
|
||||
else if (launcherTrip) available = LauncherStock(recipient);
|
||||
else available = CompatibleStock(recipient, false);
|
||||
if (m_Spent.Count() >= 96) return false;
|
||||
if (!available) return false;
|
||||
m_Members.Clear();
|
||||
for (int i = 0; i < recipient.StatusSampler.InitialStrength(); i++)
|
||||
{
|
||||
IEntity actor = recipient.StatusSampler.InitialMember(i);
|
||||
if (actor && recipient.StatusSampler.CanAttribute(i, actor)) m_Members.Insert(actor);
|
||||
}
|
||||
m_Recipient = recipient; m_Donor = donor;
|
||||
if (!Roster()) { m_Recipient = null; m_Donor = null; return false; }
|
||||
// Disjoint bounded token range from the existing mortar courier's trip IDs.
|
||||
int slot = m_ConvoySlot;
|
||||
if (slot < 0) slot = 0; // Isolated legacy fixture uses the first convoy's range.
|
||||
int token = 100000 + slot * 128 + m_Trip + 1;
|
||||
if (!m_HQ.ReserveLogistics(recipient.Group, token)) { m_Recipient = null; m_Donor = null; return false; }
|
||||
m_MineTrip = mineTrip; m_LauncherTrip = launcherTrip; m_MineRecipientSlot = -1; m_Receiving = null; m_EmptyMineReplacement = false;
|
||||
m_Trip++; m_Token = token; m_Truck.SupplyToken = token; m_ReportId = demand.MessageId; m_TripDelivered = 0; m_Served.Clear();
|
||||
m_Consumed.Set(demand.SourceId, demand.MessageId); m_NextAttempt.Set(demand.SourceId, now + 180000);
|
||||
m_Deadline = Math.Min(now + 120000, demand.ObservedAt + 180000); m_State = 2;
|
||||
string purpose = "stop existing ammo truck and report position";
|
||||
if (mineTrip) purpose += "; one finite PMN4 top-up for an existing carrier";
|
||||
if (launcherTrip) purpose += "; finite compatible magazine for a reported depleted launcher";
|
||||
m_Order = m_HQ.Downlink(donor.Group, "INFANTRY SUPPLY HOLD", purpose, m_ReportId);
|
||||
if (!m_Order) Finish("truck radio downlink unavailable");
|
||||
else Audit("existing patrol reserved; truck hold awaits radio delivery");
|
||||
return true;
|
||||
}
|
||||
// Optional mine startup must never delay normal magazine readiness. Pin the
|
||||
// original batch during Stock(), then copy its closed exact identities once.
|
||||
protected bool CaptureMines()
|
||||
{
|
||||
ERR_SupplyConvoyTask supply = ERR_SupplyConvoyTask.Cast(m_Convoy);
|
||||
if (!supply || !m_MineBatch || supply.MineStock != m_MineBatch || !m_MineBatch.Complete()) return false;
|
||||
if (m_MineStockCaptured) return !m_MineStock.IsEmpty();
|
||||
m_MineStockCaptured = true;
|
||||
int count = m_MineBatch.Count();
|
||||
if (count < 0 || count > 2) return false;
|
||||
for (int index = 0; index < count; index++)
|
||||
{
|
||||
IEntity item = m_MineBatch.At(index);
|
||||
if (item && !m_MineStock.Contains(item)) m_MineStock.Insert(item);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// Compatibility-only preflight of original own carriers; HQ still uses the
|
||||
// delivered report for demand and positions. No item is reserved or moved here.
|
||||
protected bool CompatibleStock(ERR_HQUnit recipient, bool launcherMagazine)
|
||||
{
|
||||
if (!recipient || !recipient.StatusSampler || m_Stock.Count() > 96) return false;
|
||||
int strength = recipient.StatusSampler.InitialStrength();
|
||||
if (strength < 1 || strength > 32) return false;
|
||||
int checks;
|
||||
foreach (IEntity magazine : m_Stock)
|
||||
{
|
||||
if (!magazine || m_Spent.Contains(magazine) || !Contains(m_Truck.Entity, magazine)) continue;
|
||||
for (int slot = 0; slot < strength; slot++)
|
||||
{
|
||||
if (++checks > 96 * 32) return false;
|
||||
IEntity actor = recipient.StatusSampler.InitialMember(slot);
|
||||
if (!actor || !recipient.StatusSampler.CanAttribute(slot, actor) || !ERR_Actors.CanFight(actor)) continue;
|
||||
if (ERR_InfantryAmmoTransfer.Compatible(actor, magazine, launcherMagazine)) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
protected bool LauncherStock(ERR_HQUnit recipient)
|
||||
{
|
||||
return CompatibleStock(recipient, true);
|
||||
}
|
||||
bool TryPlanLauncher(ERR_HQUnit recipient, ERR_HQUnit donor, ERR_HQWatchEntry demand, ERR_HQWatchEntry donorStatus, float now)
|
||||
{
|
||||
return TryPlan(recipient, donor, demand, donorStatus, now, false, true);
|
||||
}
|
||||
bool TryPlanMines(ERR_HQUnit recipient, ERR_HQUnit donor, ERR_HQWatchEntry demand, ERR_HQWatchEntry donorStatus, float now)
|
||||
{
|
||||
return TryPlan(recipient, donor, demand, donorStatus, now, true);
|
||||
}
|
||||
// Share exact frozen inventory identities and global radio replay state.
|
||||
bool TryPlanMounted(ERR_HQUnit recipient, ERR_HQUnit donor, ERR_HQWatchEntry demand, ERR_HQWatchEntry donorStatus, float now)
|
||||
{
|
||||
if (!Current() || m_State != 1 || m_Move || m_MineMove || m_ConvoySlot < 0 || !TruckValid(true)) return false;
|
||||
if (m_Mounted && m_Mounted.Busy()) return false;
|
||||
if (!m_Mounted) m_Mounted = new ERR_MountedResupply(m_HQ, m_Mode, m_Convoy, m_ConvoySlot, m_Stock, m_Spent, m_Consumed, m_NextAttempt);
|
||||
return m_Mounted.Begin(recipient, donor, demand, donorStatus, now);
|
||||
}
|
||||
protected bool Waypoints()
|
||||
{
|
||||
m_MoveWaypoint = AIWaypoint.Cast(ERR_Actors.Spawn(ERR_Resources.MoveWaypoint(), ERR_Actors.Ground(m_Rendezvous)));
|
||||
m_HoldWaypoint = AIWaypoint.Cast(ERR_Actors.Spawn(ERR_Resources.DefendWaypoint(), ERR_Actors.Ground(m_Rendezvous)));
|
||||
if (!m_MoveWaypoint || !m_HoldWaypoint) return false;
|
||||
// The reported rendezvous is 3 m from the donor report. A 2 m move
|
||||
// radius allowed arrival 5 m away, beyond the transfer's physical reach.
|
||||
m_MoveWaypoint.SetCompletionRadius(0.5); m_HoldWaypoint.SetCompletionRadius(0.5);
|
||||
m_Recipient.Group.AddWaypointAt(m_HoldWaypoint, 0); m_Recipient.Group.AddWaypointAt(m_MoveWaypoint, 0);
|
||||
m_Recipient.Group.ActivateAI(); return true;
|
||||
}
|
||||
protected void ClearWaypoints()
|
||||
{
|
||||
if (m_MoveWaypoint) { if (m_Recipient && m_Recipient.Group) m_Recipient.Group.RemoveWaypoint(m_MoveWaypoint); ERR_Actors.DeleteSpawned(m_MoveWaypoint); }
|
||||
if (m_HoldWaypoint) { if (m_Recipient && m_Recipient.Group) m_Recipient.Group.RemoveWaypoint(m_HoldWaypoint); ERR_Actors.DeleteSpawned(m_HoldWaypoint); }
|
||||
m_MoveWaypoint = null; m_HoldWaypoint = null;
|
||||
}
|
||||
protected void Finish(string reason)
|
||||
{
|
||||
Audit(reason);
|
||||
if (m_Move) m_Move.Stop();
|
||||
if (m_MineMove) m_MineMove.Stop();
|
||||
ClearWaypoints();
|
||||
m_Order = null;
|
||||
// A late native move must not race another truck's newer report. Retain both
|
||||
// exact claims until this one submitted identity proves custody or deletion.
|
||||
if ((m_MineMove && m_MineMove.Unresolved()) || (m_LauncherTrip && m_Move && m_Move.Unresolved())) { m_State = 7; return; }
|
||||
if (m_Recipient) m_HQ.ReleaseLogistics(m_Recipient.Group, m_Token);
|
||||
if (m_Truck && m_Truck.SupplyToken == m_Token) { m_Truck.SupplyToken = 0; m_Truck.SupplyHeld = false; }
|
||||
m_Recipient = null; m_Donor = null; m_Order = null; m_Receiving = null; m_State = 1; m_MineTrip = false; m_LauncherTrip = false; m_MineRecipientSlot = -1;
|
||||
}
|
||||
protected void TransferMine(float now)
|
||||
{
|
||||
if (m_MineMove)
|
||||
{
|
||||
int result = m_MineMove.Tick(now);
|
||||
if (result == 0) return;
|
||||
if (result < 0) { Finish("native mine transfer failed or expired; exact submitted identity stays spent"); return; }
|
||||
m_MineMove = null; m_MinesDelivered++;
|
||||
Finish("one exact finite PMN4 confirmed in the original carrier inventory"); return;
|
||||
}
|
||||
if (!m_Receiving)
|
||||
{
|
||||
int strength = m_Recipient.StatusSampler.InitialStrength();
|
||||
for (int slot = 0; slot < strength && slot < 32; slot++)
|
||||
{
|
||||
IEntity actor = m_Recipient.StatusSampler.InitialMember(slot);
|
||||
if (!actor || !m_Members.Contains(actor) || !m_Recipient.StatusSampler.CanAttribute(slot, actor, false)) continue;
|
||||
if (!ERR_Actors.CanFight(actor) || vector.DistanceXZ(actor.GetOrigin(), m_Truck.Entity.GetOrigin()) > 4) continue;
|
||||
if (!m_HQ.MineSupplyReady(m_Recipient.Group, actor)) continue;
|
||||
IEntity carried;
|
||||
int count = ERR_InfantryMineTransfer.CarriedCount(actor, m_Recipient.Group, carried);
|
||||
if (count != 1 && (count != 0 || !m_HQ.MineSupplyReady(m_Recipient.Group, actor, true))) continue;
|
||||
m_EmptyMineReplacement = count == 0;
|
||||
m_Receiving = actor; m_MineRecipientSlot = slot; break;
|
||||
}
|
||||
if (!m_Receiving) return;
|
||||
}
|
||||
if (!m_HQ.MineSupplyReady(m_Recipient.Group, m_Receiving, m_EmptyMineReplacement)) return;
|
||||
IEntity carried;
|
||||
int count = ERR_InfantryMineTransfer.CarriedCount(m_Receiving, m_Recipient.Group, carried);
|
||||
if (!m_Recipient.StatusSampler.CanAttribute(m_MineRecipientSlot, m_Receiving, false)
|
||||
|| (m_EmptyMineReplacement && count != 0) || (!m_EmptyMineReplacement && count != 1))
|
||||
{ Finish("original mine recipient lost or its pinned zero/one stock changed"); return; }
|
||||
foreach (IEntity mine : m_MineStock)
|
||||
{
|
||||
if (!ERR_InfantryMineTransfer.ReadyMine(mine) || m_Spent.Contains(mine) || !Contains(m_Truck.Entity, mine)) continue;
|
||||
ERR_FiniteMagazineReservation reservation = new ERR_FiniteMagazineReservation(m_MineStock, m_Spent, mine);
|
||||
if (!reservation.Reserve()) continue;
|
||||
m_MineMove = new ERR_InfantryMineTransfer(m_Mode, m_Truck.Entity, m_Truck.Group, m_Receiving, m_Recipient.Group,
|
||||
mine, reservation, m_Recipient.StatusSampler, m_MineRecipientSlot, m_EmptyMineReplacement);
|
||||
m_MineMove.Tick(now);
|
||||
// The leaf commits before the one native move. Only an unsubmitted refusal
|
||||
// may release its tentative claim while the same carrier approaches/retries.
|
||||
if (m_MineMove.Submitted()) return;
|
||||
reservation.ReleaseUnsubmitted(); m_MineMove = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
protected void Transfer(float now)
|
||||
{
|
||||
if (m_Move)
|
||||
{
|
||||
int result = m_Move.Tick(now);
|
||||
if (result == 0) return;
|
||||
if (result < 0) { Finish("native transfer rejected, expired or lost authority; no item retry"); return; }
|
||||
m_Move = null; m_Delivered++; m_TripDelivered++; m_Served.Insert(m_Receiving); m_Receiving = null;
|
||||
Audit("exact finite magazine confirmed in original soldier inventory");
|
||||
if (m_TripDelivered >= 6) { Finish("six-magazine trip allowance reached"); return; }
|
||||
}
|
||||
foreach (IEntity actor : m_Members)
|
||||
{
|
||||
if (!ERR_Actors.CanFight(actor) || m_Served.Contains(actor) || vector.DistanceXZ(actor.GetOrigin(), m_Truck.Entity.GetOrigin()) > 4) continue;
|
||||
ERR_HQAmmoSnapshot local = new ERR_HQAmmoSnapshot(); local.Complete = true; local.LauncherComplete = true;
|
||||
ERR_HQAmmoSampler.Inspect(actor, m_Recipient.Group, local);
|
||||
if (m_LauncherTrip)
|
||||
{
|
||||
if (!local.Valid(1) || !local.LauncherComplete || local.Members != 1 || local.LauncherMuzzles <= 0
|
||||
|| local.LauncherRounds != 0 || local.LauncherChambers != 0) continue;
|
||||
}
|
||||
else if (!local.Complete || local.SmallArmsMuzzles <= 0 || local.SmallArmsRounds + local.SmallArmsChambers > 30) continue;
|
||||
foreach (IEntity magazine : m_Stock)
|
||||
{
|
||||
if (!magazine || m_Spent.Contains(magazine) || !Contains(m_Truck.Entity, magazine) || !ERR_InfantryAmmoTransfer.Compatible(actor, magazine, m_LauncherTrip)) continue;
|
||||
ERR_FiniteMagazineReservation reservation = new ERR_FiniteMagazineReservation(m_Stock, m_Spent, magazine);
|
||||
if (!reservation.Reserve()) continue;
|
||||
m_Receiving = actor;
|
||||
m_Move = new ERR_InfantryAmmoTransfer(m_Mode, m_Truck.Entity, m_Truck.Group, actor, m_Recipient.Group, magazine, !m_LauncherTrip, m_LauncherTrip);
|
||||
m_Move.Tick(now);
|
||||
if (m_Move.Submitted()) { reservation.Commit(); return; }
|
||||
// No native operation exists yet: approach geometry, stopped state or
|
||||
// capacity may improve while the same bounded rendezvous remains valid.
|
||||
// Keep every submitted identity spent, including a synchronous rejection.
|
||||
reservation.ReleaseUnsubmitted(); m_Move = null; m_Receiving = null;
|
||||
break; // At most one unsubmitted preflight per member on this slow tick.
|
||||
}
|
||||
}
|
||||
}
|
||||
void Tick(float now)
|
||||
{
|
||||
if (!ERR_ForceRules.Finite(now) || now < 0) return;
|
||||
// Stopped services retain uncertain leaf refs until exact late proof settles.
|
||||
if (m_Stopped) { PollTransfers(now); return; }
|
||||
if (!Current() || now < m_NextTick) return;
|
||||
m_NextTick = now + 1000;
|
||||
PollTransfers(now);
|
||||
if (m_Mounted && m_Mounted.Busy()) return;
|
||||
if (m_State == 7) return;
|
||||
if (m_State == 0) { Stock(now); return; }
|
||||
if (m_State == 1)
|
||||
{
|
||||
if (m_Move && !m_Move.Unresolved()) m_Move = null;
|
||||
return;
|
||||
}
|
||||
if (now >= m_Deadline || !TruckValid() || !Quiet(m_Donor) || !Roster() || m_Truck.Combat.Held
|
||||
|| m_HQ.LogisticsToken(m_Recipient.Group) != m_Token)
|
||||
{ Finish("rendezvous expired, contact appeared or original ownership changed"); return; }
|
||||
if (m_Truck.SupplyToken != m_Token) { Finish("truck hold authority lost"); return; }
|
||||
if (m_State == 2)
|
||||
{
|
||||
int delivered = m_Order.Advance(now, m_HQ.Journal());
|
||||
if (delivered == 0) return;
|
||||
if (delivered < 0 || m_Truck.SupplyToken != m_Token) { Finish("truck hold downlink interrupted or reservation lost"); return; }
|
||||
m_Truck.SupplyHeld = true; m_Truck.ClearOrder(); m_HeldAt = -1;
|
||||
m_Order = null; m_State = 3; Audit("truck received stop; waiting for delivered stopped-position report"); return;
|
||||
}
|
||||
if (m_State == 3)
|
||||
{
|
||||
// The delivered hold asks the original crew to report only after physically stopping.
|
||||
if (m_HeldAt < 0)
|
||||
{
|
||||
Physics physics = m_Truck.Entity.GetPhysics();
|
||||
if (!physics) return;
|
||||
float speed = physics.GetVelocity().Length();
|
||||
float angular = physics.GetAngularVelocity().Length();
|
||||
if (!(speed >= 0 && speed <= 0.25 && angular >= 0 && angular <= 0.1)) return;
|
||||
m_HeldAt = now; m_Donor.NextStatus = now; return;
|
||||
}
|
||||
ERR_HQWatchEntry stopped = m_HQ.Watch().Find(m_Donor.ForceSourceId);
|
||||
if (!ERR_InfantryResupplyRules.Fresh(stopped, now) || stopped.ObservedAt < m_HeldAt) return;
|
||||
m_Rendezvous = stopped.Position + "3 0 0";
|
||||
m_Order = m_HQ.Downlink(m_Recipient.Group, "INFANTRY SUPPLY RENDEZVOUS", string.Format("walk to reported stopped ammo truck at %1", m_Rendezvous), m_ReportId);
|
||||
if (!m_Order) { Finish("infantry radio downlink unavailable"); return; }
|
||||
m_State = 4; return;
|
||||
}
|
||||
if (m_State == 4)
|
||||
{
|
||||
int delivered = m_Order.Advance(now, m_HQ.Journal());
|
||||
if (delivered == 0) return;
|
||||
if (delivered < 0 || !Waypoints()) { Finish("infantry order interrupted or native waypoint creation failed"); return; }
|
||||
m_Order = null; m_State = 5; Audit("infantry received reported rendezvous; native movement and physical transfer required");
|
||||
}
|
||||
if (m_State == 5)
|
||||
{
|
||||
if (m_MineTrip) TransferMine(now);
|
||||
else Transfer(now);
|
||||
}
|
||||
}
|
||||
string Status()
|
||||
{
|
||||
string detail = string.Format("Ground supply: state=%1 trips=%2 infantry moved=%3 stock=%4 spent=%5", State(), m_Trip, m_Delivered, m_Stock.Count(), m_Spent.Count());
|
||||
return detail + string.Format("; mines moved=%1 allowance=%2; %3", m_MinesDelivered, m_MineStock.Count(), m_Reason);
|
||||
}
|
||||
void Stop()
|
||||
{
|
||||
if (m_Stopped) return;
|
||||
if (m_Mounted) m_Mounted.Stop();
|
||||
Finish("service stopped; original forces and all remaining cargo retained"); m_Stopped = true;
|
||||
}
|
||||
}
|
||||
+353
@@ -0,0 +1,353 @@
|
||||
"""Execute the actual finite native magazine transaction; engine behavior remains separate."""
|
||||
from pathlib import Path
|
||||
import os,re
|
||||
from policy_harness import ROOT,run,body
|
||||
from test_finite_magazine_reservation import translated_reservation
|
||||
p=Path(os.environ.get('ERR_INFANTRY_TRANSFER_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoTransfer.c'))
|
||||
s=p.read_text()
|
||||
for forbidden in ('TrySpawn','DeleteEntity','SetOrigin','SetTransform','TryInsert','TryRemove','SetAmmoCount'):
|
||||
assert forbidden not in s,forbidden
|
||||
callback=s[s.index('class ERR_InfantryAmmoCallback'):s.index('// One exact physical')]
|
||||
code=s[s.index('class ERR_InfantryAmmoTransfer\n'):]
|
||||
code=re.sub(r'//[^\n]*','',code).replace('protected ','').replace('class ','struct ')
|
||||
for src,dst in {
|
||||
'm_Donor.FindComponent(VehicleHelicopterSimulation)':'m_Donor->helicopter',
|
||||
'InventoryItemComponent.Cast(loaded.GetOwner().FindComponent(InventoryItemComponent))':'loaded->GetOwner()->item',
|
||||
'BaseMagazineComponent.Cast(exactMagazine.FindComponent(BaseMagazineComponent))':'exactMagazine->magazine',
|
||||
'BaseWeaponManagerComponent.Cast(actor.FindComponent(BaseWeaponManagerComponent))':'actor->weapons',
|
||||
'BaseWeaponComponent.Cast(rifle.FindComponent(BaseWeaponComponent))':'rifle->weapon',
|
||||
'InventoryItemComponent.Cast(entity.FindComponent(InventoryItemComponent))':'entity->item',
|
||||
'InventoryItemComponent.Cast(m_Magazine.FindComponent(InventoryItemComponent))':'m_Magazine->item',
|
||||
'InventoryItemComponent.Cast(exact.FindComponent(InventoryItemComponent))':'exact->item',
|
||||
'InventoryItemComponent.Cast(candidate.FindComponent(InventoryItemComponent))':'candidate->item',
|
||||
'BaseMagazineComponent.Cast(m_Magazine.FindComponent(BaseMagazineComponent))':'m_Magazine->magazine',
|
||||
'BaseMagazineComponent.Cast(candidate.FindComponent(BaseMagazineComponent))':'candidate->magazine',
|
||||
'SCR_AIVehicleUsageComponent.Cast(m_Donor.FindComponent(SCR_AIVehicleUsageComponent))':'m_Donor->usage',
|
||||
'InventoryStorageManagerComponent.Cast(m_Donor.FindComponent(InventoryStorageManagerComponent))':'m_Donor->inventory',
|
||||
'InventoryStorageManagerComponent.Cast(m_Recipient.FindComponent(InventoryStorageManagerComponent))':'m_Recipient->inventory',
|
||||
}.items():code=code.replace(src,dst)
|
||||
code=code.replace('SCR_MuzzleInMagComponent.Cast(muzzle)', '(muzzle->inMag ? muzzle : null)')
|
||||
code=code.replace('ref ERR_InfantryAmmoCallback','ERR_InfantryAmmoCallback*').replace('array<','Array<').replace('foreach (','for (').replace('null','nullptr')
|
||||
code=re.sub(r'\bERR_GameMode (?=\w)','ERR_GameMode* ',code)
|
||||
code=code.replace('void ERR_InfantryAmmoTransfer(','ERR_InfantryAmmoTransfer(').replace('EWeaponType kind','int kind').replace('EMuzzleType muzzleKind','int muzzleKind')
|
||||
for name in ('ERR_InfantryAmmoTransferState','ERR_InfantryAmmoAccess','ERR_GameMode','ERR_EnemyEquipmentRules','ERR_ForceRules','Replication','SCR_Global','ERR_Actors','SCR_FactionManager','ERR_ConvoyRules','CompartmentAccessComponent','EWeaponType','EMuzzleType','EStoragePurpose','vector'):
|
||||
code=code.replace(name+'.',name+'::')
|
||||
for name in ('m_Mode','m_Donor','m_DonorGroup','m_Recipient','m_RecipientGroup','m_Source','m_Destination','m_Storage','m_OriginalSlot','m_Callback','magazine','reloadable','loaded','loadedItem','loadedSlot','manager','weapon','muzzle','entity','item','storage','inventory','incoming','empty','source','destination','m_ReturnCallback','donorRecord','recipientRecord','utility','usage','physics'):
|
||||
code=re.sub(r'\b'+name+r'\.',name+'->',code)
|
||||
code=code.replace('GetMagazineWell().','GetMagazineWell()->').replace('GetParentSlot().','GetParentSlot()->').replace('Forces().','Forces()->').replace('m_VehicleMgr.','m_VehicleMgr->').replace('GetPilotCompartmentSlot().','GetPilotCompartmentSlot()->')
|
||||
code=re.sub(r'\b(bool|int|Vehicle|IEntity|SCR_AIGroup|ERR_ForceRecord|InventoryStorageSlot|InventoryStorageManagerComponent|BaseInventoryStorageComponent|ERR_GameMode\*|ERR_InfantryAmmoCallback\*) (\w+);',r'\1 \2{};',code)
|
||||
code=code.replace('\n}\n','\n};\n')
|
||||
callback=callback.replace('class ERR_InfantryAmmoCallback : ScriptedInventoryOperationCallback','').strip()[1:-1]
|
||||
callbacks=[]
|
||||
for name in ('OnComplete','OnFailed','OnAllComplete','OnAllFailed'):
|
||||
m=re.search(r'protected override void '+name+r'\(\) (\{[^\n]+\})',callback)
|
||||
callbacks.append('void ERR_InfantryAmmoCallback::'+name+'() '+m[1].replace('Transfer.','Transfer->'))
|
||||
# Integrate the actual coordinator transfer selector with this actual leaf.
|
||||
coordinator_path=Path(os.environ.get('ERR_INFANTRY_RESUPPLY_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c'))
|
||||
transfer=body(coordinator_path,'protected void Transfer(float now)').replace('protected ','').replace('null','nullptr').replace('foreach (','for (')
|
||||
transfer=transfer.replace('ERR_HQAmmoSnapshot local','ERR_HQAmmoSnapshot* local')
|
||||
for name in ('ERR_Actors','ERR_HQAmmoSampler','ERR_InfantryAmmoTransfer','vector'):
|
||||
transfer=transfer.replace(name+'.',name+'::')
|
||||
transfer=transfer.replace('ERR_FiniteMagazineReservation reservation', 'ERR_FiniteMagazineReservation* reservation').replace('new ERR_FiniteMagazineReservation(m_Stock, m_Spent,', 'new ERR_FiniteMagazineReservation(&m_Stock, &m_Spent,')
|
||||
for name in ('m_Move','actor','m_Truck','m_Recipient','local','reservation'):
|
||||
transfer=transfer.replace(name+'.',name+'->')
|
||||
transfer=transfer.replace('Entity.GetOrigin()', 'Entity->GetOrigin()')
|
||||
pre=r'''
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <functional>
|
||||
using string=std::string;
|
||||
template<class T>struct Array:std::vector<T>{using std::vector<T>::vector;int Count(){return this->size();}bool IsEmpty(){return this->empty();}void Insert(T t){this->push_back(t);}void RemoveItem(T t){this->erase(std::remove(this->begin(),this->end(),t),this->end());}bool Contains(T t){return std::find(this->begin(),this->end(),t)!=this->end();}};
|
||||
struct vector{float x=0,y=0,z=0;float Length(){return std::sqrt(x*x+y*y+z*z);}static float DistanceXZ(vector a,vector b){return std::hypot(a.x-b.x,a.z-b.z);}static float Distance(vector a,vector b){return vector{a.x-b.x,a.y-b.y,a.z-b.z}.Length();}};
|
||||
struct Entity;struct Group;struct Inventory;struct Storage;struct Item;struct Slot;struct Magazine;struct Weapon;struct Muzzle;struct Manager;struct Utility;struct Usage;struct Physics_;struct Record;
|
||||
using IEntity=Entity*;using Vehicle=Entity*;using SCR_AIGroup=Group*;using ERR_ForceRecord=Record*;
|
||||
using InventoryStorageSlot=Slot*;using InventoryStorageManagerComponent=Inventory*;using BaseInventoryStorageComponent=Storage*;using InventoryItemComponent=Item*;using BaseMagazineComponent=Magazine*;
|
||||
using BaseWeaponManagerComponent=Manager*;using BaseWeaponComponent=Weapon*;using BaseMuzzleComponent=Muzzle*;using SCR_MuzzleInMagComponent=Muzzle*;
|
||||
using SCR_AIGroupUtilityComponent=Utility*;using SCR_AIVehicleUsageComponent=Usage*;using Physics=Physics_*;
|
||||
enum ERR_InfantryAmmoTransferState{FAILED=-1,PENDING,SUCCEEDED};
|
||||
struct ERR_InfantryAmmoTransfer;
|
||||
struct ScriptedInventoryOperationCallback{virtual void OnComplete(){}virtual void OnFailed(){}virtual void OnAllComplete(){}virtual void OnAllFailed(){}virtual ~ScriptedInventoryOperationCallback()=default;};
|
||||
struct ERR_InfantryAmmoCallback:ScriptedInventoryOperationCallback{ERR_InfantryAmmoTransfer*Transfer=nullptr;bool Returning=false;void OnComplete()override;void OnFailed()override;void OnAllComplete()override;void OnAllFailed()override;};
|
||||
struct EWeaponType{static const int WT_RIFLE=1,WT_SNIPERRIFLE=2,WT_MACHINEGUN=3,WT_HANDGUN=4,WT_GRENADELAUNCHER=5,WT_ROCKETLAUNCHER=6;};
|
||||
struct EMuzzleType{static const int MT_BaseMuzzle=0,MT_UGLMuzzle=1,MT_RPGMuzzle=2;};struct EStoragePurpose{static const int PURPOSE_DEPOSIT=1;};
|
||||
struct Well{int type=1,parent=0;int Type(){return type;}bool IsInherited(int t){return type==t||parent==t;}};
|
||||
struct Magazine{IEntity owner=nullptr;IEntity GetOwner(){return owner;}Well*well=nullptr;int rounds=30,capacity=30;bool used=false;bool IsUsed(){return used;}Well*GetMagazineWell(){return well;}int GetAmmoCount(){return rounds;}int GetMaxAmmoCount(){return capacity;}};
|
||||
struct Muzzle{bool inMag=false,canReload=true;bool CanBeReloaded(){return canReload;}bool disposable=false;bool IsDisposable(){return disposable;}Magazine*loaded=nullptr;Magazine*GetMagazine(){return loaded;}Well*well=nullptr;int kind=0;Well*GetMagazineWell(){return well;}int GetMuzzleType(){return kind;}};
|
||||
struct Weapon{IEntity owner=nullptr;Array<Muzzle*>muzzles;int kind=1;IEntity GetOwner(){return owner;}int GetWeaponType(){return kind;}void GetMuzzlesList(Array<Muzzle*>&a){a=muzzles;}};
|
||||
struct Manager{Array<IEntity>weapons;void GetWeaponsList(Array<IEntity>&a){a=weapons;}};
|
||||
struct Storage{IEntity owner=nullptr;IEntity GetOwner(){return owner;}};
|
||||
struct Slot{Storage*storage=nullptr;IEntity occupant=nullptr;Muzzle*container=nullptr;IEntity attached=nullptr;Muzzle*GetParentContainer(){return container;}IEntity GetAttachedEntity(){return attached;}Storage*GetStorage(){return storage;}IEntity GetOccupant(){return occupant;}};
|
||||
struct Item{Slot*slot=nullptr;Slot*GetParentSlot(){return slot;}};
|
||||
struct Physics_{vector velocity,angular;vector GetVelocity(){return velocity;}vector GetAngularVelocity(){return angular;}};
|
||||
struct Usage{Slot*pilot=nullptr;Slot*GetPilotCompartmentSlot(){return pilot;}};
|
||||
struct VehicleManager{IEntity vehicle=nullptr;IEntity FindVehicle(IEntity v){return vehicle==v?v:nullptr;}};
|
||||
struct Utility{VehicleManager*m_VehicleMgr=nullptr;bool military=true;bool IsMilitary(){return military;}};
|
||||
struct Group{int faction=1,players=0;bool slave=false;Utility*utility=nullptr;int GetPlayerCount(bool){return players;}int GetFaction(){return faction;}bool IsSlave(){return slave;}Utility*GetGroupUtilityComponent(){return utility;}};
|
||||
struct Entity{bool helicopter=false;bool alive=true,awake=true,player=false,captured=false;int faction=1;Group*group=nullptr;IEntity vehicle=nullptr,parent=nullptr;
|
||||
Inventory*inventory=nullptr;Magazine*magazine=nullptr;Manager*weapons=nullptr;Weapon*weapon=nullptr;Item*item=nullptr;Usage*usage=nullptr;Physics_*physics=nullptr;vector position;
|
||||
IEntity GetParent(){return parent;}Physics_*GetPhysics(){return physics;}vector GetOrigin(){return position;}};
|
||||
struct Record{SCR_AIGroup Group=nullptr;bool Physical=true,Eliminated=false;};
|
||||
struct Ledger{Array<Record*>records;Record*FindGroup(SCR_AIGroup g){for(auto*r:records)if(r->Group==g)return r;return nullptr;}};
|
||||
struct ERR_GameMode{inline static ERR_GameMode*current=nullptr;bool active=true;Ledger*ledger=nullptr;static ERR_GameMode*Get(){return current;}bool Active(){return active;}Ledger*Forces(){return ledger;}int EnemyFaction(){return 1;}};
|
||||
struct Replication{inline static bool server=true;static bool IsServer(){return server;}};
|
||||
struct SCR_Global{inline static bool editor=false;static bool IsEditMode(){return editor;}};
|
||||
struct ERR_Actors{static bool CanFight(IEntity a){return a&&a->alive&&a->awake;}static bool Alive(IEntity a){return a&&a->alive;}};
|
||||
struct SCR_FactionManager{static int SGetFaction(IEntity a){return a?a->faction:-1;}};
|
||||
struct CompartmentAccessComponent{static IEntity GetVehicleIn(IEntity a){return a?a->vehicle:nullptr;}};
|
||||
struct ERR_ConvoyRules{static bool Captured(Vehicle v,SCR_AIGroup g){return v->captured||g->players>0;}static bool PartOf(IEntity a,IEntity root){return a==root;}};
|
||||
struct ERR_EnemyEquipmentRules{static bool Eligible(ERR_GameMode*m,SCR_AIGroup g,IEntity a){return m&&g&&a&&a->alive&&a->awake&&!a->player&&a->group==g&&g->players==0&&g->faction==m->EnemyFaction()&&g->utility&&g->utility->military;}};
|
||||
struct ERR_ForceRules{static bool Finite(float n){return std::isfinite(n);}};
|
||||
struct ERR_InfantryAmmoAccess{static inline bool clear=true;static inline int checks=0;static bool Clear(Vehicle donor,IEntity recipient){assert(donor&&recipient);checks++;return clear;}};
|
||||
struct Inventory{IEntity owner=nullptr;Array<IEntity>items;Array<Storage*>storages;Storage*selected=nullptr;bool allow=true,accept=true;int calls=0,callback=0;ScriptedInventoryOperationCallback*last=nullptr;std::function<void()> effect;
|
||||
IEntity GetOwner(){return owner;}void GetItems(Array<IEntity>&a,int purpose){assert(purpose==1);a=items;}void GetStorages(Array<Storage*>&a,int purpose){assert(purpose==1);a=storages;}
|
||||
Storage*FindStorageForItem(IEntity,int purpose){assert(purpose==1);return selected;}
|
||||
bool CanMoveItemToStorage(IEntity,Storage*,int slot){assert(slot==-1);return allow;}
|
||||
bool TryMoveItemToStorage(IEntity,Storage*,int slot,ScriptedInventoryOperationCallback*cb){assert(slot==-1);calls++;last=cb;if(effect)effect();if(callback==1){cb->OnComplete();}if(callback==2){cb->OnFailed();}return accept;}};
|
||||
'''
|
||||
main=r'''
|
||||
struct Fixture{ERR_GameMode mode;Ledger ledger;Group donorGroup,recipientGroup,otherGroup;Record donorRecord,recipientRecord;Entity truck,recipient,driver,spareDriver,magEntity,rifle,foreign;
|
||||
VehicleManager vehicleManager;Utility donorUtility,recipientUtility;Physics_ physics;Usage usage;Slot pilot,fromSlot,toSlot;Storage sourceStorage,targetStorage;Inventory source,destination;Item item;Magazine magazine;Manager weapons;Weapon weapon;Muzzle muzzle;Well well;
|
||||
Fixture(){ERR_GameMode::current=&mode;mode.ledger=&ledger;donorRecord.Group=&donorGroup;recipientRecord.Group=&recipientGroup;ledger.records={&donorRecord,&recipientRecord};
|
||||
donorGroup.utility=&donorUtility;recipientGroup.utility=&recipientUtility;donorUtility.m_VehicleMgr=&vehicleManager;vehicleManager.vehicle=&truck;
|
||||
truck.physics=&physics;truck.usage=&usage;usage.pilot=&pilot;pilot.occupant=&driver;driver.group=&donorGroup;driver.vehicle=&truck;spareDriver.group=&donorGroup;spareDriver.vehicle=&truck;
|
||||
recipient.group=&recipientGroup;recipient.position.x=4;truck.inventory=&source;source.owner=&truck;recipient.inventory=&destination;destination.owner=&recipient;
|
||||
sourceStorage.owner=&truck;targetStorage.owner=&recipient;source.storages={&sourceStorage};destination.storages={&targetStorage};destination.selected=&targetStorage;
|
||||
source.items={&magEntity};magEntity.item=&item;item.slot=&fromSlot;fromSlot.storage=&sourceStorage;fromSlot.attached=&magEntity;toSlot.storage=&targetStorage;magEntity.magazine=&magazine;magazine.well=&well;
|
||||
recipient.weapons=&weapons;weapons.weapons={&rifle};rifle.weapon=&weapon;weapon.owner=&rifle;weapon.muzzles={&muzzle};muzzle.well=&well;}
|
||||
ERR_InfantryAmmoTransfer Job(){return ERR_InfantryAmmoTransfer(&mode,&truck,&donorGroup,&recipient,&recipientGroup,&magEntity,true);}
|
||||
void Move(){source.items.RemoveItem(&magEntity);destination.items.Insert(&magEntity);item.slot=&toSlot;}
|
||||
};
|
||||
struct EmptyFixture:Fixture{
|
||||
Entity empty,secondEmpty;Magazine emptyMag;Item emptyItem,secondItem;Slot emptyFrom,emptyTo;
|
||||
EmptyFixture(){emptyMag.well=&well;emptyMag.rounds=0;empty.magazine=&emptyMag;empty.item=&emptyItem;
|
||||
emptyFrom.storage=&targetStorage;emptyTo.storage=&sourceStorage;emptyItem.slot=&emptyFrom;
|
||||
secondEmpty.magazine=&emptyMag;secondEmpty.item=&secondItem;secondItem.slot=&emptyFrom;
|
||||
destination.items={&empty,&secondEmpty};destination.selected=nullptr;source.selected=&sourceStorage;}
|
||||
void Return(bool capacity=true){destination.items.RemoveItem(&empty);source.items.Insert(&empty);emptyItem.slot=&emptyTo;if(capacity)destination.selected=&targetStorage;}
|
||||
};
|
||||
struct ERR_HQAmmoSnapshot{bool Complete=true,LauncherComplete=true;int Members=1,LauncherMuzzles=1,LauncherMagazines=1,LauncherRounds=0,LauncherChambers=0;bool Valid(int n){return n==Members;}int SmallArmsMuzzles=1,SmallArmsRounds=0,SmallArmsChambers=0;};
|
||||
struct ERR_HQAmmoSampler{static void Inspect(IEntity actor,SCR_AIGroup group,ERR_HQAmmoSnapshot* stock){assert(actor&&actor->group==group&&stock);}};
|
||||
struct SupplyTruck{IEntity Entity;SCR_AIGroup Group;};
|
||||
struct SupplyRecipient{SCR_AIGroup Group;};
|
||||
struct Coordinator{bool m_LauncherTrip=false;ERR_GameMode* m_Mode;SupplyTruck* m_Truck;SupplyRecipient* m_Recipient;
|
||||
ERR_InfantryAmmoTransfer* m_Move=nullptr;Array<IEntity>m_Members,m_Stock,m_Spent,m_Served;IEntity m_Receiving=nullptr;
|
||||
int m_Delivered=0,m_TripDelivered=0,finishes=0,audits=0;
|
||||
void Finish(string){finishes++;if(m_Move)m_Move->Stop();}
|
||||
void Audit(string){audits++;}
|
||||
bool Contains(IEntity owner,IEntity item){return owner&&owner->inventory&&owner->inventory->items.Count()<=128&&owner->inventory->items.Contains(item);}
|
||||
'''+transfer+r'''
|
||||
};
|
||||
struct SupplyFixture:Fixture{SupplyTruck supplyTruck;SupplyRecipient supplyRecipient;Coordinator c;
|
||||
SupplyFixture():supplyTruck{&truck,&donorGroup},supplyRecipient{&recipientGroup}{
|
||||
c.m_Mode=&mode;c.m_Truck=&supplyTruck;c.m_Recipient=&supplyRecipient;c.m_Members={&recipient};c.m_Stock={&magEntity};}
|
||||
};
|
||||
struct LauncherFixture:SupplyFixture{Entity loaded;Magazine empty;Item loadedItem;Slot loadedSlot;
|
||||
LauncherFixture(){c.m_LauncherTrip=true;weapon.kind=EWeaponType::WT_GRENADELAUNCHER;muzzle.kind=EMuzzleType::MT_UGLMuzzle;
|
||||
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());
|
||||
if(bad!=0)f.source.last->OnFailed();
|
||||
if(bad==1)f.item.slot=nullptr;
|
||||
if(bad==2)f.fromSlot.attached=nullptr;
|
||||
if(bad==3)f.sourceStorage.owner=&f.foreign;
|
||||
if(bad==4)f.destination.items.Insert(&f.magEntity);
|
||||
if(bad==5)f.truck.inventory=&f.destination;
|
||||
if(bad==6)f.source.items.RemoveItem(&f.magEntity);
|
||||
assert(f.c.m_Move->Unresolved());f.c.m_Move->Stop();assert(f.c.m_Move->Unresolved());}
|
||||
|
||||
{LauncherFixture f;f.muzzle.loaded=nullptr;assert(ERR_InfantryAmmoTransfer::Compatible(&f.recipient,&f.magEntity,true));f.c.Transfer(0);assert(f.source.calls==1&&f.c.m_Move->Submitted());}
|
||||
|
||||
{LauncherFixture f;assert(!ERR_InfantryAmmoTransfer::Compatible(&f.recipient,&f.magEntity));assert(ERR_InfantryAmmoTransfer::Compatible(&f.recipient,&f.magEntity,true));
|
||||
f.c.Transfer(0);assert(f.c.m_Move&&f.c.m_Move->Submitted()&&f.c.m_Spent.Count()==1&&f.source.calls==1);
|
||||
f.Move();f.source.last->OnComplete();f.c.Transfer(1000);f.c.Transfer(2000);assert(f.c.m_Delivered==1&&f.source.calls==1&&f.c.m_Served.Count()==1);}
|
||||
for(int bad=0;bad<8;bad++){LauncherFixture f;if(bad==0)f.magazine.used=true;if(bad==1)f.muzzle.well=nullptr;if(bad==2)f.muzzle.disposable=true;if(bad==3)f.empty.well=nullptr;if(bad==4)f.loadedSlot.attached=nullptr;if(bad==5)f.rifle.parent=nullptr;if(bad==6)f.empty.capacity=0;if(bad==7){f.muzzle.inMag=true;f.muzzle.canReload=false;}
|
||||
f.c.Transfer(0);assert(!f.c.m_Move&&f.source.calls==0&&f.c.m_Spent.IsEmpty());}
|
||||
{LauncherFixture f;f.source.accept=false;f.c.Transfer(0);assert(f.c.m_Move&&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.Move();f.source.last->OnComplete();assert(!f.c.m_Move->Unresolved());}
|
||||
{LauncherFixture f;auto t=ERR_InfantryAmmoTransfer(&f.mode,&f.truck,&f.donorGroup,&f.recipient,&f.recipientGroup,&f.magEntity,false,true);
|
||||
f.source.effect=[&](){t.Stop();f.Move();};f.source.callback=1;assert(t.Tick(0)==FAILED&&!t.Unresolved()&&f.source.calls==1);assert(t.Tick(1)==FAILED);}
|
||||
|
||||
// A capacity recovery uses one exact unused empty, separately proving both native operations.
|
||||
{Fixture f;Entity empty;Magazine emptyMag;Item emptyItem;Slot emptyFrom{&f.targetStorage},emptyTo{&f.sourceStorage};
|
||||
emptyMag.well=&f.well;emptyMag.rounds=0;empty.magazine=&emptyMag;empty.item=&emptyItem;emptyItem.slot=&emptyFrom;
|
||||
f.destination.items={&empty};f.destination.selected=nullptr;f.source.selected=&f.sourceStorage;
|
||||
auto t=f.Job();assert(t.Tick(0)==PENDING&&t.Submitted()&&t.Unresolved()&&f.destination.calls==1&&f.source.calls==0);
|
||||
auto returning=f.destination.last;returning->OnComplete();assert(t.Tick(1)==PENDING&&f.source.calls==0&&t.Unresolved());
|
||||
f.destination.items.clear();f.source.items.Insert(&empty);emptyItem.slot=&emptyTo;f.destination.selected=&f.targetStorage;
|
||||
assert(t.Tick(2)==PENDING&&!t.Unresolved()&&f.source.calls==0);assert(t.Tick(3)==PENDING&&f.source.calls==1&&t.Unresolved());
|
||||
returning->OnAllComplete();returning->OnFailed();assert(t.Tick(4)==PENDING&&t.Unresolved());
|
||||
f.Move();assert(t.Tick(5)==PENDING);f.source.last->OnComplete();assert(t.Tick(6)==SUCCEEDED&&!t.Unresolved());
|
||||
assert(f.destination.calls==1&&f.source.calls==1);}
|
||||
// Ground coordinator reserves the incoming identity as soon as reverse native movement is submitted.
|
||||
// A failed/ambiguous return never releases it to try a second empty or another incoming magazine.
|
||||
for(int outcome=0;outcome<3;outcome++){EmptyFixture f;SupplyTruck truck{&f.truck,&f.donorGroup};SupplyRecipient recipient{&f.recipientGroup};Coordinator c;
|
||||
c.m_Mode=&f.mode;c.m_Truck=&truck;c.m_Recipient=&recipient;c.m_Members={&f.recipient};c.m_Stock={&f.magEntity};
|
||||
if(outcome==0){f.destination.accept=false;}
|
||||
c.Transfer(0);assert(c.m_Move&&c.m_Move->Submitted()&&c.m_Spent.Count()==1&&c.m_Receiving==&f.recipient&&c.m_Delivered==0);
|
||||
if(outcome==1){f.Return(false);f.destination.last->OnComplete();c.Transfer(1000);}
|
||||
c.Transfer(outcome==2?8000:2000);assert(c.finishes==1&&c.m_Spent.Contains(&f.magEntity)&&c.m_Delivered==0&&f.destination.calls==1&&f.source.calls==0);
|
||||
assert(c.m_Move->Unresolved()==(outcome==2));}
|
||||
{EmptyFixture f;SupplyTruck truck{&f.truck,&f.donorGroup};SupplyRecipient recipient{&f.recipientGroup};Coordinator c;
|
||||
c.m_Mode=&f.mode;c.m_Truck=&truck;c.m_Recipient=&recipient;c.m_Members={&f.recipient};c.m_Stock={&f.magEntity};
|
||||
c.Transfer(0);f.Return();f.destination.last->OnComplete();c.Transfer(1000);assert(c.m_Delivered==0&&f.source.calls==0);
|
||||
c.Transfer(2000);assert(c.m_Delivered==0&&f.source.calls==1);f.Move();f.source.last->OnComplete();c.Transfer(3000);c.Transfer(4000);
|
||||
assert(c.m_Delivered==1&&c.m_Served.Count()==1&&c.m_Spent.Count()==1&&f.source.calls==1&&f.destination.calls==1&&f.source.items.Contains(&f.empty));}
|
||||
// Default callers (including air delivery) retain the original one-way behavior.
|
||||
{EmptyFixture f;ERR_InfantryAmmoTransfer t(&f.mode,&f.truck,&f.donorGroup,&f.recipient,&f.recipientGroup,&f.magEntity);
|
||||
assert(t.Tick(0)==FAILED&&!t.Submitted()&&f.destination.calls==0&&f.source.calls==0);}
|
||||
// No return when capacity already exists, even with carried empties.
|
||||
{EmptyFixture f;f.destination.selected=&f.targetStorage;auto t=f.Job();assert(t.Tick(0)==PENDING&&f.source.calls==1&&f.destination.calls==0);}
|
||||
// Unused, zero-round, exact-well, exclusive recipient storage ownership and donor space are required.
|
||||
for(int invalid=0;invalid<12;invalid++){EmptyFixture f;f.destination.items={&f.empty};Well other;other.type=2;
|
||||
if(invalid==0)f.emptyMag.used=true;if(invalid==1)f.emptyMag.rounds=1;if(invalid==2)f.emptyMag.rounds=-1;
|
||||
if(invalid==3)f.emptyMag.capacity=0;if(invalid==4)f.emptyMag.well=&other;if(invalid==5)f.emptyMag.well=nullptr;
|
||||
if(invalid==6)f.emptyItem.slot=&f.emptyTo;if(invalid==7)f.source.items.Insert(&f.empty);
|
||||
if(invalid==8)f.source.selected=nullptr;if(invalid==9)f.destination.allow=false;
|
||||
if(invalid==10){for(int i=0;i<129;i++)f.destination.items.Insert(&f.empty);}if(invalid==11)ERR_InfantryAmmoAccess::clear=false;
|
||||
auto t=f.Job();assert(t.Tick(0)==FAILED&&!t.Submitted()&&!t.Unresolved()&&f.destination.calls==0&&f.source.calls==0);
|
||||
ERR_InfantryAmmoAccess::clear=true;}
|
||||
// Return proof needs exact destination slot as well as callback; no second candidate is ever moved.
|
||||
{EmptyFixture f;auto t=f.Job();t.Tick(0);f.Return();f.emptyItem.slot=&f.emptyFrom;f.destination.last->OnComplete();
|
||||
assert(t.Tick(1)==PENDING&&t.Unresolved()&&f.source.calls==0&&f.destination.calls==1);
|
||||
f.emptyItem.slot=&f.emptyTo;assert(t.Tick(2)==PENDING&&!t.Unresolved());assert(t.Tick(3)==PENDING&&f.source.calls==1&&f.destination.calls==1);}
|
||||
// Inline success callbacks override a false API result for the reverse operation, but require physical proof.
|
||||
{EmptyFixture f;f.destination.accept=false;f.destination.callback=1;f.destination.effect=[&](){f.Return();};auto t=f.Job();
|
||||
assert(t.Tick(0)==PENDING&&t.Submitted()&&!t.Unresolved());assert(t.Tick(1)==PENDING&&f.source.calls==0);
|
||||
f.source.accept=false;f.source.callback=1;f.source.effect=[&](){f.Move();};assert(t.Tick(2)==SUCCEEDED&&f.source.calls==1&&f.destination.calls==1);}
|
||||
// Every attempted reverse move burns the incoming identity, including synchronous rejection.
|
||||
for(int failure=0;failure<3;failure++){EmptyFixture f;if(failure==0)f.destination.accept=false;if(failure==1)f.destination.callback=2;
|
||||
auto t=f.Job();assert(t.Tick(0)==PENDING&&t.Submitted()&&f.destination.calls==1&&f.source.calls==0);
|
||||
assert(t.Tick(failure==2?8000:1)==FAILED);assert(t.Unresolved()==(failure==2));
|
||||
for(int i=0;i<3;i++){t.Tick(9000+i);}assert(f.destination.calls==1&&f.source.calls==0);}
|
||||
// Stop before, during, or after confirmed return can never launch the incoming move.
|
||||
for(int stopAt=0;stopAt<3;stopAt++){EmptyFixture f;auto t=f.Job();if(stopAt==0){t.Stop();assert(t.Tick(0)==FAILED&&!t.Submitted());continue;}
|
||||
t.Tick(0);if(stopAt==2){f.Return();f.destination.last->OnComplete();assert(t.Tick(1)==PENDING&&!t.Unresolved());}
|
||||
t.Stop();assert(t.Tick(2)==FAILED&&t.Submitted()&&f.source.calls==0);if(stopAt==1){assert(t.Unresolved());f.Return();f.destination.last->OnAllComplete();}
|
||||
assert(!t.Unresolved()&&t.Tick(3)==FAILED&&f.source.calls==0&&f.destination.calls==1);}
|
||||
// Confirmed return cannot trigger a second empty or bypass revalidated incoming custody/capacity/access.
|
||||
for(int changed=0;changed<6;changed++){EmptyFixture f;auto t=f.Job();t.Tick(0);f.Return(changed!=0);f.destination.last->OnComplete();assert(t.Tick(1)==PENDING);
|
||||
if(changed==1)f.source.items.RemoveItem(&f.magEntity);if(changed==2)f.destination.items.Insert(&f.magEntity);
|
||||
if(changed==3)f.truck.captured=true;if(changed==4)f.recipient.player=true;if(changed==5)ERR_InfantryAmmoAccess::clear=false;
|
||||
assert(t.Tick(2)==FAILED&&t.Submitted()&&!t.Unresolved()&&f.source.calls==0&&f.destination.calls==1);
|
||||
assert(t.Tick(3)==FAILED&&f.destination.calls==1);ERR_InfantryAmmoAccess::clear=true;}
|
||||
// Original owner/driver/ledger loss while a return is accepted quarantines that exact operation.
|
||||
for(int changed=0;changed<4;changed++){EmptyFixture f;auto t=f.Job();t.Tick(0);
|
||||
if(changed==0)f.truck.captured=true;if(changed==1)f.recipient.player=true;if(changed==2)f.pilot.occupant=&f.spareDriver;if(changed==3)f.donorRecord.Eliminated=true;
|
||||
assert(t.Tick(1)==FAILED&&t.Unresolved());f.destination.last->OnFailed();assert(!t.Unresolved()&&f.source.calls==0&&f.destination.calls==1);}
|
||||
// Both native phases are bounded independently, with no renewal while waiting for callbacks.
|
||||
{EmptyFixture f;auto t=f.Job();t.Tick(0);f.Return();f.destination.last->OnComplete();assert(t.Tick(7999)==PENDING);
|
||||
assert(t.Tick(8000)==PENDING&&f.source.calls==1);assert(t.Tick(15999)==FAILED&&t.Unresolved());}
|
||||
// XZ approach can precede valid vertical reach, stopped state, capacity or clear access.
|
||||
// None of those no-submission outcomes consumes cargo or ends the trip; the same exact item can later submit once.
|
||||
for(int obstruction=0;obstruction<5;obstruction++){SupplyFixture f;
|
||||
if(obstruction==0){f.recipient.position.y=3;}if(obstruction==1){f.physics.velocity.x=1;}
|
||||
if(obstruction==2){f.destination.selected=nullptr;}if(obstruction==3){f.source.allow=false;}
|
||||
if(obstruction==4){ERR_InfantryAmmoAccess::clear=false;}
|
||||
for(int tick=0;tick<3;tick++){f.c.Transfer(tick*1000);assert(f.source.calls==0&&f.c.m_Spent.IsEmpty()&&!f.c.m_Move&&!f.c.m_Receiving&&f.c.finishes==0);}
|
||||
f.recipient.position.y=0;f.physics.velocity.x=0;f.destination.selected=&f.targetStorage;f.source.allow=true;ERR_InfantryAmmoAccess::clear=true;
|
||||
f.c.Transfer(3000);assert(f.source.calls==1&&f.c.m_Spent.Count()==1&&f.c.m_Move&&f.c.m_Move->Submitted());
|
||||
f.Move();f.source.last->OnComplete();f.c.Transfer(4000);assert(f.c.m_Delivered==1&&f.c.m_Served.Contains(&f.recipient)&&f.source.calls==1&&f.c.m_Spent.Count()==1);
|
||||
}
|
||||
// A capacity-blocked first member cannot prevent another original member from receiving this magazine.
|
||||
{SupplyFixture f;Fixture second;ERR_GameMode::current=&f.mode;
|
||||
second.recipient.group=&f.recipientGroup;second.recipientRecord.Group=&f.recipientGroup;
|
||||
f.c.m_Members.Insert(&second.recipient);f.destination.selected=nullptr;
|
||||
f.c.Transfer(0);assert(f.source.calls==1&&f.c.m_Receiving==&second.recipient&&f.c.m_Spent.Count()==1&&f.c.finishes==0);
|
||||
f.source.items.clear();second.destination.items={&f.magEntity};f.item.slot=&second.toSlot;f.source.last->OnComplete();
|
||||
f.c.Transfer(1000);assert(f.c.m_Delivered==1&&f.c.m_Served.Contains(&second.recipient)&&!f.c.m_Served.Contains(&f.recipient));}
|
||||
// A native API may complete both physical movement and callback inline. Account once on the next slow tick.
|
||||
{SupplyFixture f;f.source.callback=1;f.source.effect=[&](){f.Move();};f.c.Transfer(0);
|
||||
assert(f.source.calls==1&&f.c.m_Move&&f.c.m_Move->Submitted()&&f.c.m_Delivered==0&&f.c.m_Spent.Count()==1);
|
||||
f.c.Transfer(1000);f.c.Transfer(2000);assert(f.c.m_Delivered==1&&f.c.m_Served.Count()==1&&f.source.calls==1&&f.c.finishes==0);}
|
||||
// Crossing the native submission boundary burns the exact identity even if native refusal is synchronous.
|
||||
for(int refusal=0;refusal<2;refusal++){SupplyFixture f;if(refusal==0){f.source.accept=false;}else{f.source.callback=2;}
|
||||
f.c.Transfer(0);assert(f.source.calls==1&&f.c.m_Spent.Count()==1&&f.c.m_Move->Submitted());
|
||||
f.c.Transfer(1000);assert(f.c.finishes==1&&f.c.m_Spent.Count()==1&&f.source.calls==1);
|
||||
}
|
||||
// Accepted but unresolved loss stays retained/spent; changing geometry cannot cause a second native move.
|
||||
{SupplyFixture f;f.c.Transfer(0);f.recipient.position.x=8;f.c.Transfer(1000);
|
||||
assert(f.c.finishes==1&&f.c.m_Move&&f.c.m_Move->Unresolved()&&f.c.m_Spent.Count()==1&&f.source.calls==1);}
|
||||
// Several equivalent magazines do not multiply a blocked actor's expensive preflight work on one slow tick.
|
||||
{SupplyFixture f;Entity another=f.magEntity;f.source.items.Insert(&another);f.c.m_Stock.Insert(&another);
|
||||
ERR_InfantryAmmoAccess::clear=false;ERR_InfantryAmmoAccess::checks=0;f.c.Transfer(0);
|
||||
assert(ERR_InfantryAmmoAccess::checks==1&&f.source.calls==0&&f.c.m_Spent.IsEmpty());ERR_InfantryAmmoAccess::clear=true;}
|
||||
// A blocked native access check happens before submission and is terminal.
|
||||
{Fixture f;auto t=f.Job();ERR_InfantryAmmoAccess::clear=false;ERR_InfantryAmmoAccess::checks=0;
|
||||
assert(t.Tick(0)==FAILED&&!t.Submitted()&&!t.Unresolved()&&f.source.calls==0&&ERR_InfantryAmmoAccess::checks==1);
|
||||
ERR_InfantryAmmoAccess::clear=true;assert(t.Tick(1)==FAILED&&f.source.calls==0&&ERR_InfantryAmmoAccess::checks==1);}
|
||||
// Once native move is accepted, later geometry cannot cause a second operation or pretend cancellation.
|
||||
{Fixture f;auto t=f.Job();ERR_InfantryAmmoAccess::checks=0;assert(t.Tick(0)==PENDING&&ERR_InfantryAmmoAccess::checks==1);
|
||||
ERR_InfantryAmmoAccess::clear=false;assert(t.Tick(1)==PENDING&&t.Unresolved()&&f.source.calls==1&&ERR_InfantryAmmoAccess::checks==1);
|
||||
f.Move();f.source.last->OnComplete();assert(t.Tick(2)==SUCCEEDED);ERR_InfantryAmmoAccess::clear=true;}
|
||||
// Read-only selection follows the native inherited-well direction, excluding launcher muzzles and weapons.
|
||||
{Fixture f;assert(ERR_InfantryAmmoTransfer::Compatible(&f.recipient,&f.magEntity));Well derived;derived.type=2;derived.parent=1;f.magazine.well=&derived;assert(ERR_InfantryAmmoTransfer::Compatible(&f.recipient,&f.magEntity));
|
||||
f.magazine.well=&f.well;f.muzzle.well=&derived;assert(!ERR_InfantryAmmoTransfer::Compatible(&f.recipient,&f.magEntity));
|
||||
f.muzzle.well=&f.well;f.muzzle.kind=EMuzzleType::MT_UGLMuzzle;assert(!ERR_InfantryAmmoTransfer::Compatible(&f.recipient,&f.magEntity));
|
||||
f.muzzle.kind=0;f.weapon.kind=EWeaponType::WT_ROCKETLAUNCHER;assert(!ERR_InfantryAmmoTransfer::Compatible(&f.recipient,&f.magEntity));}
|
||||
// Exactly one source move; neither a callback alone nor physical movement alone is a successful transaction.
|
||||
{Fixture f;auto t=f.Job();assert(t.Tick(100)==PENDING&&f.source.calls==1&&t.Unresolved());f.source.last->OnComplete();assert(t.Tick(101)==PENDING&&t.Unresolved());
|
||||
f.Move();assert(t.Tick(102)==SUCCEEDED&&!t.Unresolved());t.Stop();assert(t.Tick(103)==SUCCEEDED&&f.source.calls==1);}
|
||||
{Fixture f;auto t=f.Job();t.Tick(100);f.Move();assert(t.Tick(101)==PENDING&&t.Unresolved());f.source.last->OnAllComplete();assert(t.Tick(102)==SUCCEEDED);}
|
||||
// Exact destination slot and known donor absence are mandatory even after success callback.
|
||||
{Fixture f;auto t=f.Job();t.Tick(100);f.Move();f.item.slot=&f.fromSlot;f.source.last->OnComplete();assert(t.Tick(101)==PENDING&&t.Unresolved());
|
||||
f.item.slot=&f.toSlot;for(int i=0;i<513;i++)f.source.items.Insert(&f.foreign);assert(t.Tick(102)==PENDING&&t.Unresolved());}
|
||||
// Late callbacks resolve retained reservations after Stop without Tick or further operations; the stopped task stays failed.
|
||||
{Fixture f;auto t=f.Job();t.Tick(0);t.Stop();assert(t.Unresolved());f.Move();f.source.last->OnAllComplete();assert(!t.Unresolved());assert(t.Tick(2)==FAILED&&f.source.calls==1);}
|
||||
{Fixture f;auto t=f.Job();t.Tick(0);t.Stop();f.source.last->OnAllFailed();assert(!t.Unresolved());assert(t.Tick(1)==FAILED&&f.source.calls==1);}
|
||||
{Fixture f;auto t=f.Job();t.Tick(0);f.source.last->OnComplete();f.source.last->OnFailed();assert(t.Unresolved());f.Move();assert(!t.Unresolved()&&t.Tick(1)==SUCCEEDED);}
|
||||
// Failure/rejection and the 8s deadline never submit a second move.
|
||||
for(int failure=0;failure<3;failure++){Fixture f;if(failure==0)f.source.accept=false;if(failure==1)f.source.callback=2;auto t=f.Job();t.Tick(100);
|
||||
if(failure==2){assert(t.Tick(8100)==FAILED&&t.Unresolved());}else assert(t.Tick(101)==FAILED&&!t.Unresolved());
|
||||
for(int i=0;i<10;i++)t.Tick(8200+i);assert(f.source.calls==1);}
|
||||
// Invalid physical state before submission spends no native action; the terminal object cannot revive.
|
||||
for(int invalid=0;invalid<25;invalid++){Fixture f;auto t=f.Job();
|
||||
if(invalid==0)Replication::server=false;if(invalid==1)SCR_Global::editor=true;if(invalid==2)f.mode.active=false;
|
||||
if(invalid==3)f.truck.alive=false;if(invalid==4)f.recipient.alive=false;if(invalid==5)f.recipient.awake=false;if(invalid==6)f.recipient.player=true;
|
||||
if(invalid==7)f.recipient.vehicle=&f.truck;if(invalid==8)f.truck.captured=true;if(invalid==9)f.donorGroup.players=1;
|
||||
if(invalid==10)f.recipient.group=&f.otherGroup;if(invalid==11)f.donorRecord.Physical=false;if(invalid==12)f.recipientRecord.Eliminated=true;
|
||||
if(invalid==13)f.vehicleManager.vehicle=&f.foreign;if(invalid==14)f.driver.alive=false;if(invalid==15)f.driver.vehicle=nullptr;
|
||||
if(invalid==16)f.physics.velocity.x=.251f;if(invalid==17)f.physics.angular.x=.101f;if(invalid==18)f.recipient.position.x=4.001f;
|
||||
if(invalid==19)f.truck.faction=2;if(invalid==20)f.driver.faction=2;if(invalid==21)f.recipientGroup.slave=true;
|
||||
if(invalid==22)f.magazine.rounds=0;if(invalid==23)f.magazine.rounds=31;if(invalid==24)f.physics.velocity.x=std::numeric_limits<float>::quiet_NaN();
|
||||
assert(t.Tick(100)==FAILED&&f.source.calls==0&&!t.Unresolved());Replication::server=true;SCR_Global::editor=false;assert(t.Tick(200)==FAILED&&f.source.calls==0);}
|
||||
// Native stock/storage identity and capacity guards reject shared, foreign, oversized and inaccessible inventory.
|
||||
for(int invalid=0;invalid<9;invalid++){Fixture f;auto t=f.Job();if(invalid==0)f.source.items.clear();if(invalid==1)f.destination.items={&f.magEntity};
|
||||
if(invalid==2)f.fromSlot.storage=&f.targetStorage;if(invalid==3)f.sourceStorage.owner=&f.foreign;if(invalid==4)f.destination.selected=nullptr;
|
||||
if(invalid==5)f.targetStorage.owner=&f.foreign;if(invalid==6)f.source.allow=false;if(invalid==7)f.destination.storages.clear();if(invalid==8){for(int i=0;i<65;i++)f.destination.storages.Insert(&f.targetStorage);}
|
||||
assert(t.Tick(0)==FAILED&&f.source.calls==0);}
|
||||
// Conditions and original native driver/ledger identities remain strict while an accepted move is pending.
|
||||
for(int changed=0;changed<4;changed++){Fixture f;auto t=f.Job();t.Tick(100);Record replacement=f.recipientRecord;
|
||||
if(changed==0)f.pilot.occupant=&f.spareDriver;if(changed==1)f.ledger.records[1]=&replacement;if(changed==2)f.physics.velocity.x=1;if(changed==3)f.recipient.position.x=8;
|
||||
assert(t.Tick(101)==FAILED&&t.Unresolved());f.source.last->OnFailed();assert(!t.Unresolved()&&f.source.calls==1);}
|
||||
{Fixture f;auto t=f.Job();t.Tick(100);assert(t.Tick(99)==FAILED&&t.Unresolved());}
|
||||
// Clothing storage ownership follows native inventory slots and bounds cycles.
|
||||
{Fixture f;Entity vest;Item vestItem;Slot vestSlot;Storage body;body.owner=&f.recipient;vestSlot.storage=&body;vestItem.slot=&vestSlot;vest.item=&vestItem;f.targetStorage.owner=&vest;
|
||||
auto t=f.Job();assert(t.Tick(0)==PENDING);f.Move();f.source.last->OnComplete();assert(t.Tick(1)==SUCCEEDED);
|
||||
vestSlot.storage=&f.targetStorage;assert(!ERR_InfantryAmmoTransfer::StoredUnder(&vest,&f.recipient));}
|
||||
}
|
||||
'''
|
||||
# Brace tiny fixture statements to retain -Werror without suppressing useful compiler diagnostics.
|
||||
main=re.sub(r'if\((invalid|changed|failure)==(\d+)\)([^;{}]+);',r'if(\1==\2){\3;}',main)
|
||||
main=main.replace('for(int i=0;i<10;i++)t.Tick(8200+i);','for(int i=0;i<10;i++){t.Tick(8200+i);}')
|
||||
run(pre+translated_reservation()+code+'\n'.join(callbacks)+main)
|
||||
print('PASS: actual bounded empty-return and finite delivery; phase-isolated callbacks, exact ownership proof, stop quarantine and original actor/vehicle boundaries')
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
"""Actual coordinator decisions/transitions with native boundaries doubled; no engine proof."""
|
||||
import os,re,sys
|
||||
from pathlib import Path
|
||||
REPO=Path(os.environ.get('ERR_REPO','/home/jakub/devel/escapistsrereintroduced'))
|
||||
sys.path.insert(0,str(REPO/'tests'))
|
||||
from policy_harness import body,run
|
||||
SOURCE=Path(os.environ.get('ERR_INFANTRY_RESUPPLY_SOURCE',REPO/'addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c'))
|
||||
def method(signature):
|
||||
s=body(SOURCE,signature).replace('protected ','').replace('null','nullptr')
|
||||
s=s.replace('vector.DistanceXZ','Vec::DistanceXZ').replace('ERR_ForceRules.','ERR_ForceRules::').replace('ERR_InfantryResupplyRules.','ERR_InfantryResupplyRules::').replace('ERR_Actors.','ERR_Actors::')
|
||||
s=s.replace(' + "3 0 0"',' + Vec{3,0,0}')
|
||||
s=re.sub(r'string\.Format\("walk to reported stopped ammo truck at %1", m_Rendezvous\)', '"rendezvous"', s)
|
||||
for kind in ['ERR_HQWatchEntry','Physics']:
|
||||
s=re.sub(r'\b'+kind+r' (\w+)',kind+r'* \1',s)
|
||||
# Enforce native entity/reference member access becomes C++ pointer member access.
|
||||
for name in ['entry','recipient','donor','stopped','m_HQ','m_Move','m_MineMove','m_Mounted','m_Recipient','m_Donor','m_Truck','m_Order','physics']:
|
||||
s=s.replace(name+'.',name+'->')
|
||||
for name in ['AmmoState','Group','Combat','Entity']:
|
||||
s=s.replace(name+'.',name+'->')
|
||||
s=s.replace('Watch().','Watch()->').replace('GetVelocity().','GetVelocity().').replace('GetAngularVelocity().','GetAngularVelocity().')
|
||||
return s
|
||||
rules='\n'.join(method(x) for x in ['static bool Fresh','static bool Need','static bool Pair'])
|
||||
methods='\n'.join(method(x) for x in ['protected void PollTransfers','protected void ClearWaypoints','protected void Finish','void Tick(float now)','void Stop()'])
|
||||
code=r'''
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
using string=std::string;
|
||||
struct Vec {float x=0,y=0,z=0; float Length(){return std::sqrt(x*x+y*y+z*z);} static float DistanceXZ(Vec a,Vec b){return std::hypot(a.x-b.x,a.z-b.z);} Vec operator+(Vec b){return {x+b.x,y+b.y,z+b.z};} string ToString(){return "position";}};
|
||||
struct ERR_ForceRules {static bool Finite(float n){return std::isfinite(n);} static bool FiniteVector(Vec v){return Finite(v.x)&&Finite(v.y)&&Finite(v.z);}};
|
||||
struct Ammo {bool Complete=true,valid=true;int Members=2,SmallArmsMuzzles=2,SmallArmsRounds=60,SmallArmsChambers=0;bool Valid(int){return valid;}};
|
||||
struct ERR_HQWatchEntry {bool Closed=false;int Count=2,Fit=2,SourceId=1;float ObservedAt=0;Vec Position;Ammo* AmmoState=nullptr;};
|
||||
struct ERR_InfantryResupplyRules {
|
||||
RULES
|
||||
};
|
||||
struct Waypoint {int id;};
|
||||
struct Group {std::vector<Waypoint*> points;void RemoveWaypoint(Waypoint* p){points.erase(std::remove(points.begin(),points.end(),p),points.end());}};
|
||||
struct ERR_Actors {static inline int deleted=0;static void DeleteSpawned(Waypoint*){deleted++;}};
|
||||
struct Physics {Vec linear,angular;Vec GetVelocity(){return linear;} Vec GetAngularVelocity(){return angular;}};
|
||||
struct Entity {Physics* physics=nullptr;Physics* GetPhysics(){return physics;}};
|
||||
struct Combat {bool Held=false;};
|
||||
struct Truck {int SupplyToken=7,clears=0;bool SupplyHeld=false;struct Combat* Combat=nullptr;struct Entity* Entity=nullptr;void ClearOrder(){clears++;}};
|
||||
struct Unit {struct Group* Group=nullptr;int ForceSourceId=1;float NextStatus=-1;};
|
||||
struct Leaf {int stops=0;bool unresolved=true;void Stop(){stops++;}bool Unresolved(){return unresolved;}};
|
||||
struct Mounted{bool busy=false;int ticks=0,stops=0;bool Busy(){return busy;}void Tick(float){ticks++;}void Stop(){stops++;}};
|
||||
struct Route {int result=0,advances=0;int Advance(float,int){advances++;return result;}};
|
||||
struct Watch {ERR_HQWatchEntry* entry=nullptr;ERR_HQWatchEntry* Find(int){return entry;}};
|
||||
struct HQ {int token=7,releases=0,downlinks=0;struct Watch watch;Route* next=nullptr;int Journal(){return 0;}int LogisticsToken(Group*){return token;}void ReleaseLogistics(Group*,int owned){releases++;if(token==owned)token=0;}struct Watch* Watch(){return &watch;} Route* Downlink(Group*,string,string,int){downlinks++;return next;}};
|
||||
struct Service {
|
||||
HQ* m_HQ;Truck* m_Truck;Unit* m_Recipient;Unit* m_Donor;Leaf* m_Move=nullptr;Leaf*m_MineMove=nullptr;bool m_MineTrip=false,m_LauncherTrip=false;int m_MineRecipientSlot=-1;Mounted*m_Mounted=nullptr;Route* m_Order=nullptr;Entity* m_Receiving=nullptr;
|
||||
Waypoint* m_MoveWaypoint=nullptr;Waypoint* m_HoldWaypoint=nullptr;Vec m_Rendezvous;int m_State=2,m_Token=7,m_ReportId=11;
|
||||
float m_NextTick=0,m_Deadline=200000,m_HeldAt=-1;bool m_Stopped=false,valid=true,quiet=true,roster=true,waypoints=true;int audits=0,transfers=0,waypointCalls=0,stocks=0;
|
||||
bool Current(){return !m_Stopped;}bool TruckValid(){return valid;}bool Quiet(Unit*){return quiet;}bool Roster(){return roster;}void Audit(string){audits++;}void Stock(float){stocks++;}bool Waypoints(){waypointCalls++;return waypoints;}void Transfer(float){transfers++;}int mineTransfers=0;void TransferMine(float){mineTransfers++;}
|
||||
METHODS
|
||||
};
|
||||
struct Fixture {Physics physics;Entity entity{&physics};Combat combat;Truck truck;Group group,donorGroup;Unit recipient{&group},donor{&donorGroup};HQ hq;Route order,next;Service s;
|
||||
Fixture(){truck.Combat=&combat;truck.Entity=&entity;s.m_HQ=&hq;s.m_Truck=&truck;s.m_Recipient=&recipient;s.m_Donor=&donor;s.m_Order=ℴhq.next=&next;}
|
||||
};
|
||||
int main(){
|
||||
{Fixture f;Leaf leaf;f.s.m_Move=&leaf;f.s.m_LauncherTrip=true;f.truck.SupplyHeld=true;f.s.Stop();assert(f.s.m_State==7&&f.hq.token==7&&f.truck.SupplyHeld);
|
||||
f.s.Tick(200000);assert(f.s.m_State==7&&f.hq.token==7&&f.s.transfers==0);leaf.unresolved=false;f.s.Tick(201000);assert(f.s.m_State==1&&f.hq.token==0&&!f.truck.SupplyHeld&&!f.s.m_Move);}
|
||||
|
||||
{Fixture f;Leaf leaf;f.s.m_MineMove=&leaf;f.s.m_MineTrip=true;f.truck.SupplyHeld=true;f.s.Stop();assert(f.s.m_State==7&&f.hq.token==7&&f.truck.SupplyHeld&&f.s.m_Recipient);
|
||||
f.s.Tick(200000);assert(f.hq.token==7&&f.s.m_State==7&&f.s.transfers==0&&f.s.mineTransfers==0);leaf.unresolved=false;f.s.Tick(201000);assert(f.hq.token==0&&!f.truck.SupplyHeld&&f.s.m_State==1&&!f.s.m_MineMove);}
|
||||
{Fixture f;f.s.m_State=5;f.s.m_MineTrip=true;f.s.Tick(0);assert(f.s.mineTransfers==1&&f.s.transfers==0);}
|
||||
|
||||
Ammo ammo;ERR_HQWatchEntry demand,donor;demand.AmmoState=&ammo;donor.SourceId=2;donor.Position={200,500,0};
|
||||
assert(ERR_InfantryResupplyRules::Need(&demand,120000));assert(ERR_InfantryResupplyRules::Pair(&demand,&donor,120000));
|
||||
assert(!ERR_InfantryResupplyRules::Fresh(&demand,120001));assert(!ERR_InfantryResupplyRules::Fresh(nullptr,0));
|
||||
demand.ObservedAt=1;assert(!ERR_InfantryResupplyRules::Fresh(&demand,0));demand.ObservedAt=0;
|
||||
ammo.SmallArmsChambers=1;assert(!ERR_InfantryResupplyRules::Need(&demand,0));ammo.SmallArmsChambers=0;
|
||||
ammo.Complete=false;assert(!ERR_InfantryResupplyRules::Need(&demand,0));ammo.Complete=true;
|
||||
ammo.Members=1;assert(!ERR_InfantryResupplyRules::Need(&demand,0));ammo.Members=2;
|
||||
ammo.valid=false;assert(!ERR_InfantryResupplyRules::Need(&demand,0));ammo.valid=true;
|
||||
donor.SourceId=1;assert(!ERR_InfantryResupplyRules::Pair(&demand,&donor,0));donor.SourceId=2;donor.Position.x=201;assert(!ERR_InfantryResupplyRules::Pair(&demand,&donor,0));
|
||||
demand.Position.x=std::numeric_limits<float>::quiet_NaN();assert(!ERR_InfantryResupplyRules::Need(&demand,0));demand.Position.x=0;
|
||||
{Fixture f;f.s.Tick(0);assert(f.s.m_State==2&&!f.truck.SupplyHeld&&f.truck.clears==0&&f.s.waypointCalls==0);f.order.result=1;f.s.Tick(1000);assert(f.s.m_State==3&&f.truck.SupplyHeld&&f.truck.clears==1&&f.s.m_Order==nullptr);f.physics.linear.x=1;f.s.Tick(2000);assert(f.s.m_HeldAt==-1&&f.donor.NextStatus==-1);f.physics.linear.x=0;f.s.Tick(3000);assert(f.s.m_HeldAt==3000&&f.donor.NextStatus==3000);ERR_HQWatchEntry report;report.Position={20,0,5};report.ObservedAt=2999;f.hq.watch.entry=&report;f.s.Tick(4000);assert(f.hq.downlinks==0);report.ObservedAt=3000;f.s.Tick(5000);assert(f.s.m_State==4&&f.hq.downlinks==1&&f.s.m_Rendezvous.x==23);f.s.Tick(6000);assert(f.s.m_State==4&&f.s.waypointCalls==0&&f.s.transfers==0);f.next.result=1;f.s.Tick(7000);assert(f.s.m_State==5&&f.s.waypointCalls==1&&f.s.transfers==1);}
|
||||
{Fixture f;f.order.result=-1;f.s.Tick(0);assert(f.s.m_State==1&&f.hq.token==0&&f.truck.SupplyToken==0&&!f.truck.SupplyHeld&&f.truck.clears==0);}
|
||||
{Fixture f;f.s.m_State=4;f.order.result=-1;f.s.Tick(0);assert(f.s.waypointCalls==0&&f.s.transfers==0&&f.hq.token==0);}
|
||||
{Fixture f;f.hq.token=99;f.truck.SupplyToken=99;f.truck.SupplyHeld=true;f.s.Tick(0);assert(f.s.m_State==1&&f.hq.token==99&&f.truck.SupplyToken==99&&f.truck.SupplyHeld);}
|
||||
{Fixture f;Waypoint own1{1},own2{2},other{3};f.group.points={&own1,&other,&own2};f.s.m_MoveWaypoint=&own1;f.s.m_HoldWaypoint=&own2;Leaf leaf;f.s.m_Move=&leaf;f.truck.SupplyHeld=true;f.s.Stop();assert(f.group.points.size()==1&&f.group.points[0]==&other&&leaf.stops==1&&f.s.m_Move==&leaf&&f.hq.token==0&&!f.truck.SupplyHeld&&f.s.m_Stopped);int audits=f.s.audits;f.s.Stop();f.s.Tick(5000);assert(f.s.audits==audits&&leaf.stops==1);}
|
||||
{Fixture f;Leaf leaf;f.s.m_Move=&leaf;f.s.Finish("timeout");f.s.Tick(0);assert(f.s.m_Move==&leaf);leaf.unresolved=false;f.s.Tick(1000);assert(f.s.m_Move==nullptr);}
|
||||
{Fixture f;f.s.m_State=3;f.physics.linear.x=std::numeric_limits<float>::quiet_NaN();f.s.Tick(0);assert(f.s.m_HeldAt==-1&&f.donor.NextStatus==-1);}
|
||||
{Fixture f;f.s.m_State=3;f.physics.angular.x=std::numeric_limits<float>::quiet_NaN();f.s.Tick(0);assert(f.s.m_HeldAt==-1&&f.donor.NextStatus==-1);}
|
||||
{Fixture f;f.s.m_Deadline=0;f.s.Tick(0);assert(f.s.m_State==1&&f.order.advances==0&&f.hq.token==0);}
|
||||
// Waiting for physical transfer never extends the original bounded rendezvous deadline.
|
||||
{Fixture f;f.s.m_State=5;f.s.m_Deadline=1000;f.s.Tick(0);assert(f.s.transfers==1&&f.s.m_State==5);
|
||||
f.s.Tick(1000);assert(f.s.transfers==1&&f.s.m_State==1&&f.hq.token==0&&!f.truck.SupplyHeld);}
|
||||
|
||||
{Fixture f;f.s.quiet=false;f.order.result=1;f.s.Tick(0);assert(f.s.m_State==1&&f.order.advances==0&&!f.truck.SupplyHeld);}
|
||||
{Fixture f;f.s.m_State=4;f.order.result=1;f.s.waypoints=false;f.s.Tick(0);assert(f.s.m_State==1&&f.s.waypointCalls==1&&f.s.transfers==0&&f.hq.token==0);}
|
||||
{Fixture f;f.s.m_State=3;f.s.m_HeldAt=100;ERR_HQWatchEntry report;report.ObservedAt=100;f.hq.watch.entry=&report;f.hq.next=nullptr;f.s.Tick(1000);assert(f.s.m_State==1&&f.hq.downlinks==1&&f.s.waypointCalls==0&&f.hq.token==0);}
|
||||
|
||||
}
|
||||
'''.replace('RULES',rules).replace('METHODS',methods)
|
||||
run(code)
|
||||
print('infantry resupply actual rules, radio transitions, owned cleanup and unresolved-operation tests passed')
|
||||
|
||||
# Recheck permanent initial-roster eligibility during an active trip.
|
||||
src=SOURCE
|
||||
s=body(src,'protected bool Roster()').replace('protected ','')
|
||||
s=s.replace('array<AIAgent> agents = {};','Array<Agent*> agents;')
|
||||
s=s.replace('foreach (AIAgent agent : agents)','for (Agent* agent : agents)').replace('foreach (IEntity actor : m_Members)','for (Actor* actor : m_Members)')
|
||||
for x in ['m_Recipient','agent']:s=s.replace(x+'.',x+'->')
|
||||
s=s.replace('StatusSampler.','StatusSampler->').replace('Group.','Group->')
|
||||
for x in ['ERR_Actors','SCR_FactionManager','CompartmentAccessComponent']:s=s.replace(x+'.',x+'::')
|
||||
s=s.replace('m_Mode.','m_Mode->').replace('bool living;', 'bool living = false;')
|
||||
run(r'''
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
template<class T> struct Array:std::vector<T>{using std::vector<T>::vector;bool IsEmpty(){return this->empty();}int Count(){return this->size();}bool Contains(T a){return std::find(this->begin(),this->end(),a)!=this->end();}};
|
||||
struct Group;
|
||||
struct Actor{bool alive=true,player=false,fight=true;Group* group=nullptr;int faction=1;};
|
||||
struct Agent{Actor* actor;Actor* GetControlledEntity(){return actor;}};
|
||||
struct Group{Array<Agent*> agents;void GetAgents(Array<Agent*>& out){out=agents;}};
|
||||
struct Sampler{Group* group;bool released=false;int strength=1;Array<Actor*> original;int InitialStrength(){return strength;}Actor* InitialMember(int slot){return slot>=0&&slot<(int)original.size()?original[slot]:nullptr;}bool OwnsRoster(Group* g){return g==group;}bool CanAttribute(int,Actor*){return !released;}};
|
||||
struct Unit{struct Group* Group;Sampler* StatusSampler;};
|
||||
struct Mode{int EnemyFaction(){return 1;}};
|
||||
struct ERR_Actors{static bool Alive(Actor* a){return a->alive;}static bool Player(Actor* a){return a->player;}static struct Group* Group(Actor* a){return a->group;}static bool CanFight(Actor* a){return a->fight;}};
|
||||
struct SCR_FactionManager{static int SGetFaction(Actor* a){return a->faction;}};
|
||||
struct CompartmentAccessComponent{static bool GetVehicleIn(Actor*){return false;}};
|
||||
struct Service{Unit* m_Recipient;Mode* m_Mode;Array<Actor*> m_Members;bool Quiet(Unit*){return true;}
|
||||
METHOD
|
||||
};
|
||||
int main(){
|
||||
Group group;Actor soldier;soldier.group=&group;Agent agent{&soldier};group.agents={&agent};Sampler sampler{&group,false,1,{&soldier}};Unit unit{&group,&sampler};Mode mode;Service service{&unit,&mode,{&soldier}};assert(service.Roster());sampler.released=true;assert(!sampler.CanAttribute(0,&soldier));
|
||||
// Permanent sampler release survives returning to the physical group.
|
||||
assert(!service.Roster());sampler.released=false;assert(service.Roster());
|
||||
sampler.strength=33;assert(!service.Roster());sampler.strength=0;assert(!service.Roster());sampler.strength=1;
|
||||
Actor foreign;foreign.group=&group;sampler.original={&foreign};assert(!service.Roster());
|
||||
// Initial roster order, not current GetAgents order, determines the slot.
|
||||
sampler.strength=2;sampler.original={&foreign,&soldier};assert(service.Roster());
|
||||
soldier.player=true;assert(!service.Roster());soldier.player=false;
|
||||
soldier.group=nullptr;assert(!service.Roster());soldier.group=&group;
|
||||
soldier.alive=false;assert(!service.Roster());soldier.alive=true;
|
||||
Agent extra{&foreign};group.agents.push_back(&extra);assert(!service.Roster());
|
||||
}
|
||||
'''.replace('METHOD',s))
|
||||
print('PASS: actual resupply Roster preserves permanent release, original slot mapping and bounded ownership')
|
||||
+290
@@ -0,0 +1,290 @@
|
||||
"""Execute real finite-stock/planning/reservation bodies; native inventory/group APIs are doubles."""
|
||||
import os,re
|
||||
from pathlib import Path
|
||||
from policy_harness import ROOT,body,run
|
||||
P=Path(os.environ.get('ERR_INFANTRY_RESUPPLY_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c'))
|
||||
A=Path(os.environ.get('ERR_INFANTRY_TRANSFER_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoTransfer.c'))
|
||||
I=ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_Inventory.c'
|
||||
H=Path(os.environ.get('ERR_HQ_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_HQ.c'))
|
||||
def cpp(s):
|
||||
s=s.replace('protected ','').replace('notnull ','').replace('null','nullptr')
|
||||
s=s.replace('map<string, int>', 'Map<int>*').replace('map<string, float>', 'Map<float>*')
|
||||
s=s.replace('array<IEntity> items = {};','Array<IEntity> items;').replace('array<IEntity> raw = {};','Array<IEntity> raw;').replace('array<AIAgent> agents = {};','Array<AIAgent> agents;')
|
||||
s=s.replace('out array<IEntity> items','Array<IEntity>& items').replace('array<IEntity> items','Array<IEntity>& items')
|
||||
s=re.sub(r'foreach \((\w+) (\w+) : ([^)]+)\)',r'for (\1 \2 : \3)',s)
|
||||
for typ in ('InventoryStorageManagerComponent','ERR_ForceRecord','ERR_SupplyConvoyTask'):
|
||||
s=re.sub(r'\b'+typ+r' (?=\w)',typ+'* ',s)
|
||||
for name in ('ERR_ForceRules','ERR_InfantryResupplyRules','ERR_InfantryMineTransfer','ERR_InfantryAmmoTransfer','ERR_ConvoyRules','ERR_ForceKind','ERR_ConvoyResources','ERR_Inventory','ERR_Actors','SCR_FactionManager','CompartmentAccessComponent','Replication','Math'):
|
||||
s=s.replace(name+'.',name+'::')
|
||||
s=s.replace('ERR_SupplyConvoyTask.Cast','ERR_SupplyConvoyTask::Cast').replace('FindComponent(BaseMagazineComponent)','HasMagazine()')
|
||||
s=s.replace('vector.DistanceXZ','Vec::DistanceXZ').replace('InventoryStorageManagerComponent.Cast','InventoryStorageManagerComponent::Cast').replace('FindComponent(InventoryStorageManagerComponent)','FindComponent()')
|
||||
for name in ('m_Mode','m_HQ','m_Convoy','m_Truck','m_Recipient','m_Donor','m_Move','m_MineMove','m_MineBatch','m_Mounted','recipient','donor','demand','donorStatus','entry','operation','inventory','item','owner','record','actor','agent','unit','m_MoveWaypoint','m_HoldWaypoint','magazine','supply','m_Consumed','m_NextAttempt'):
|
||||
s=s.replace(name+'.',name+'->')
|
||||
for name in ('Receipt','Entity','Group','Utility','StatusSampler','AmmoState','Combat','m_Perception'):
|
||||
s=s.replace(name+'.',name+'->')
|
||||
for name in ('Forces()','GetPrefabData()','Convoys()'):s=s.replace(name+'.',name+'->')
|
||||
s=s.replace('ERR_SupplyConvoyTask* supply', 'Convoy* supply')
|
||||
s=s.replace('bool designated;','bool designated=false;')
|
||||
s=s.replace('int checks;', 'int checks=0;')
|
||||
s=s.replace('bool available;','bool available=false;').replace('bool living;','bool living=false;')
|
||||
return s
|
||||
rules='\n'.join(cpp(body(P,x)) for x in ('static bool Fresh(', 'static bool Need(', 'static bool Pair(', 'static bool MinePair(', 'static bool LauncherNeed(', 'static bool LauncherPair('))
|
||||
stock_method=('protected bool CompatibleStock(',) if 'protected bool CompatibleStock(' in P.read_text() else ()
|
||||
methods='\n'.join(cpp(body(P,x)) for x in stock_method+('bool Bind(', 'ERR_ConvoyTask Task(', 'protected bool ConvoyCurrent(', 'protected bool Contains(', 'protected bool TruckValid(', 'protected bool Quiet(', 'protected bool Roster(', 'protected void Stock(', 'protected bool CaptureMines(', 'protected bool LauncherStock(', 'bool TryPlanLauncher(', 'bool TryPlanMines(', 'bool TryPlan(', 'protected void ClearWaypoints(', 'protected void Finish(', 'void Stop('))
|
||||
reserve=cpp(body(H,'bool ReserveLogistics('))+cpp(body(H,'void ReleaseLogistics('))
|
||||
unique=cpp(body(I,'static int AppendUnique('))+cpp(body(I,'static int Items('))
|
||||
compatible=body(A,'static bool Compatible(')
|
||||
for a,b in {
|
||||
'BaseMagazineComponent.Cast(exactMagazine.FindComponent(BaseMagazineComponent))':'exactMagazine->ammoComp',
|
||||
'BaseWeaponManagerComponent.Cast(actor.FindComponent(BaseWeaponManagerComponent))':'actor->weapons',
|
||||
'BaseWeaponComponent.Cast(rifle.FindComponent(BaseWeaponComponent))':'rifle->weapon',
|
||||
'InventoryItemComponent.Cast(loaded.GetOwner().FindComponent(InventoryItemComponent))':'loaded->GetOwner()->item',
|
||||
'SCR_MuzzleInMagComponent.Cast(muzzle)':'(muzzle->inMag ? muzzle : nullptr)',
|
||||
}.items():compatible=compatible.replace(a,b)
|
||||
compatible=compatible.replace('array<','Array<').replace('foreach (','for (').replace('EWeaponType kind','int kind').replace('EMuzzleType muzzleKind','int muzzleKind')
|
||||
for a in ['EWeaponType','EMuzzleType']:compatible=compatible.replace(a+'.',a+'::')
|
||||
for a in ['magazine','manager','weapon','muzzle','reloadable','loaded','loadedItem','loadedSlot']:compatible=compatible.replace(a+'.',a+'->')
|
||||
compatible=compatible.replace('GetMagazineWell().','GetMagazineWell()->')
|
||||
run(r'''
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
using string=std::string;
|
||||
template<class T>struct Array:std::vector<T>{using std::vector<T>::vector;int Count(){return this->size();}bool IsEmpty(){return this->empty();}void Clear(){this->clear();}void Insert(T v){this->push_back(v);}bool Contains(T v){return std::find(this->begin(),this->end(),v)!=this->end();}};
|
||||
template<class V>struct Map{std::map<string,V>data;V Get(string k){auto it=data.find(k);return it==data.end()?V{}:it->second;}void Set(string k,V v){data[k]=v;}};
|
||||
struct Vec{float x=0,y=0,z=0;static float DistanceXZ(Vec a,Vec b){return std::hypot(a.x-b.x,a.z-b.z);}};
|
||||
struct ERR_ForceRules{static bool Finite(float f){return std::isfinite(f);}static bool FiniteVector(Vec v){return Finite(v.x)&&Finite(v.y)&&Finite(v.z);}};
|
||||
struct Math{static float Min(float a,float b){return std::min(a,b);}};
|
||||
struct Replication{static inline bool server=true;static bool IsServer(){return server;}};
|
||||
struct Entity;using IEntity=Entity*;
|
||||
struct Magazine;struct Manager;struct Weapon;struct Muzzle;struct Item;struct Slot;
|
||||
using BaseMagazineComponent=Magazine*;using BaseWeaponManagerComponent=Manager*;using BaseWeaponComponent=Weapon*;using BaseMuzzleComponent=Muzzle*;using SCR_MuzzleInMagComponent=Muzzle*;using InventoryItemComponent=Item*;using InventoryStorageSlot=Slot*;
|
||||
struct EWeaponType{static const int WT_RIFLE=1,WT_SNIPERRIFLE=2,WT_MACHINEGUN=3,WT_HANDGUN=4,WT_GRENADELAUNCHER=5,WT_ROCKETLAUNCHER=6;};
|
||||
struct EMuzzleType{static const int MT_BaseMuzzle=0,MT_UGLMuzzle=1,MT_RPGMuzzle=2;};
|
||||
struct Well{int type=1,parent=0;int Type(){return type;}bool IsInherited(int t){return type==t||parent==t;}};
|
||||
struct Magazine{IEntity owner=nullptr;Well*well=nullptr;int rounds=30,capacity=30;bool used=false;IEntity GetOwner(){return owner;}Well*GetMagazineWell(){return well;}int GetAmmoCount(){return rounds;}int GetMaxAmmoCount(){return capacity;}bool IsUsed(){return used;}};
|
||||
struct Muzzle{bool inMag=true,canReload=true,disposable=false;Magazine*loaded=nullptr;Well*well=nullptr;int kind=0;bool CanBeReloaded(){return canReload;}bool IsDisposable(){return disposable;}Magazine*GetMagazine(){return loaded;}Well*GetMagazineWell(){return well;}int GetMuzzleType(){return kind;}};
|
||||
struct Weapon{IEntity owner=nullptr;Array<Muzzle*>muzzles;int kind=1;IEntity GetOwner(){return owner;}int GetWeaponType(){return kind;}void GetMuzzlesList(Array<Muzzle*>&a){a=muzzles;}};
|
||||
struct Manager{Array<IEntity>weapons;void GetWeaponsList(Array<IEntity>&a){a=weapons;}};
|
||||
struct Slot{Muzzle*container=nullptr;IEntity attached=nullptr;Muzzle*GetParentContainer(){return container;}IEntity GetAttachedEntity(){return attached;}};
|
||||
struct Item{Slot*slot=nullptr;Slot*GetParentSlot(){return slot;}};
|
||||
struct InventoryStorageManagerComponent{Array<IEntity>items;void GetItems(Array<IEntity>& out){out=items;}static auto Cast(InventoryStorageManagerComponent* p){return p;}};
|
||||
struct Prefab{string name="magazine";string GetPrefabName(){return name;}};
|
||||
struct Group;using SCR_AIGroup=Group*;
|
||||
struct Entity{Magazine*ammoComp=nullptr;Manager*weapons=nullptr;Weapon*weapon=nullptr;Item*item=nullptr;IEntity parent=nullptr;Prefab prefab;bool readyMine=false,magazine=true,hasPrefab=true,alive=true,player=false,fight=true,aboard=false,captured=false,released=false;int faction=1;Group* group=nullptr;InventoryStorageManagerComponent* inventory=nullptr;bool HasMagazine(){return magazine;}Prefab* GetPrefabData(){return hasPrefab?&prefab:nullptr;}InventoryStorageManagerComponent* FindComponent(){return inventory;}};
|
||||
struct Agent{IEntity actor;IEntity GetControlledEntity(){return actor;}};using AIAgent=Agent*;
|
||||
struct Waypoint{};
|
||||
struct Group{Array<AIAgent>agents;bool slave=false;int players=0,faction=1;bool IsSlave(){return slave;}int GetPlayerCount(bool){return players;}int GetFaction(){return faction;}void GetAgents(Array<AIAgent>& out){out=agents;}void RemoveWaypoint(Waypoint*){}};
|
||||
struct ERR_Actors{static bool Alive(IEntity a){return a&&a->alive;}static bool Player(IEntity a){return a&&a->player;}static SCR_AIGroup Group(IEntity a){return a->group;}static bool CanFight(IEntity a){return a&&a->alive&&a->fight;}static void DeleteSpawned(Waypoint*){}};
|
||||
struct SCR_FactionManager{static int SGetFaction(IEntity a){return a->faction;}};
|
||||
struct CompartmentAccessComponent{static bool GetVehicleIn(IEntity a){return a->aboard;}};
|
||||
struct ERR_Inventory{
|
||||
'''+unique+r'''
|
||||
};
|
||||
struct Ammo{bool LauncherComplete=true;int LauncherMuzzles=1,LauncherMagazines=1,LauncherRounds=0,LauncherChambers=0;bool MineComplete=true;int MineMembers=2,ReadyMines=1;bool Complete=true;int Members=2,SmallArmsMuzzles=2,SmallArmsRounds=60,SmallArmsChambers=0;bool Valid(int n){return Members==n;}};
|
||||
struct Entry{bool Closed=false;int Count=2,Fit=2,MessageId=1;float ObservedAt=0;Vec Position;string SourceId;Ammo* AmmoState=nullptr;};using ERR_HQWatchEntry=Entry*;
|
||||
struct ERR_InfantryResupplyRules{
|
||||
'''+rules+r'''
|
||||
};
|
||||
namespace ERR_ForceKind{const int CONVOY=3;}
|
||||
struct ERR_ForceRecord{bool Physical=true,Eliminated=false;int Kind=3,Id=2;};
|
||||
struct Ledger{Group* owned=nullptr;ERR_ForceRecord record;ERR_ForceRecord* FindGroup(Group* g){return g==owned?&record:nullptr;}};
|
||||
struct Mode{Ledger ledger;Ledger* Forces(){return &ledger;}int EnemyFaction(){return 1;}};
|
||||
struct Perception{Array<int>m_aTargets;};
|
||||
struct Utility{Perception* m_Perception=nullptr;};
|
||||
struct Sampler{Group* group;Array<IEntity>original;int InitialStrength(){return original.Count();}IEntity InitialMember(int i){return original[i];}bool CanAttribute(int i,IEntity a){return original[i]==a&&!a->released;}bool OwnsRoster(Group* g){return g==group;}};
|
||||
struct Unit{struct Group* Group=nullptr;struct Utility* Utility=nullptr;Sampler* StatusSampler=nullptr;string ForceSourceId;bool HomeGuard=false,eligible=true;int LogisticsReservation=0;void* Downlink=nullptr;void* PendingOrder=nullptr;void* PendingConvoyOrder=nullptr;void* Radio=this;void* Assignment=nullptr;void* Waypoint=nullptr;bool Eligible(Mode*){return eligible&&LogisticsReservation==0;}};using ERR_HQUnit=Unit*;
|
||||
struct Combat{bool Held=false;};
|
||||
struct Truck{int Index=1,SupplyToken=0;bool Registered=true,Released=false,Arrived=false,SupplyHeld=false,crew=true;struct Entity* Entity=nullptr;struct Group* Group=nullptr;struct Combat* Combat=nullptr;bool CrewValid(Mode*){return crew;}};
|
||||
struct Receipt{bool Consumed=true;Array<int>Records={1,2,3,4,5,6};};
|
||||
struct Cargo{bool Finished=true;};using ERR_ConvoyCargoCallback=Cargo*;
|
||||
struct MineBatch{bool complete=true;Array<IEntity>items;bool Complete(){return complete;}int Count(){return items.Count();}IEntity At(int i){return items[i];}};
|
||||
struct Convoy{MineBatch*MineStock=nullptr;bool supply=false,MagazinesIssued=true,CargoIssued=true,Stopped=false,Ready=true;struct Receipt* Receipt=nullptr;Array<Truck*>Vehicles;Array<struct Cargo*>Cargo;float Deadline=30000;};
|
||||
using ERR_ConvoyTask=Convoy*;
|
||||
struct ConvoyService{Array<Convoy*>tasks;int Count(){return tasks.Count();}Convoy* At(int index){return index>=0&&index<Count()?tasks[index]:nullptr;}};
|
||||
struct ERR_SupplyConvoyTask:Convoy{static Convoy* Cast(Convoy* task){return task&&task->supply?task:nullptr;}};
|
||||
struct ERR_ConvoyRules{static bool Captured(Entity* e,Group*){return e->captured;}};
|
||||
struct ERR_ConvoyResources{static string Magazine(){return "magazine";}};
|
||||
struct ERR_InfantryMineTransfer{static bool ReadyMine(IEntity x){return x&&x->readyMine;}};
|
||||
struct Route{};struct Leaf{bool unresolved=false;void Stop(){}bool Unresolved(){return unresolved;}};struct Mounted{bool busy=false;bool Busy(){return busy;}void Stop(){}};
|
||||
struct HQ{Mode* m_Mode;Array<ERR_HQUnit>m_Units;Convoy* convoy=nullptr;ConvoyService convoys;ConvoyService* Convoys(){return &convoys;}Route route;bool active=true,routeAvailable=true;int downlinks=0;bool MissionActive(){return active;}Convoy* ConvoyTask(){return convoy;}
|
||||
bool designated=false;bool MineSupplyReady(Group*,IEntity,bool replacement=false){return !replacement||designated;}
|
||||
Route* Downlink(Group*,string,string,int){downlinks++;return routeAvailable?&route:nullptr;}
|
||||
'''+reserve+r'''
|
||||
};
|
||||
struct ERR_InfantryAmmoTransfer{static bool StoredUnder(IEntity item,IEntity actor){return item&&item->parent==actor;}
|
||||
'''+compatible+r'''
|
||||
};
|
||||
struct Service{HQ* m_HQ;Mode* m_Mode;Convoy* m_Convoy=nullptr;Truck* m_Truck=nullptr;Unit* m_Recipient=nullptr;Unit* m_Donor=nullptr;Leaf* m_Move=nullptr;Leaf*m_MineMove=nullptr;MineBatch*m_MineBatch=nullptr;bool m_LauncherTrip=false,m_MineTrip=false,m_MineStockCaptured=false,m_EmptyMineReplacement=false;int m_MineRecipientSlot=-1;Mounted*m_Mounted=nullptr;Route* m_Order=nullptr;IEntity m_Receiving=nullptr;
|
||||
Array<IEntity>m_Stock,m_MineStock,m_Spent,m_Members,m_Served;Map<int>*m_Consumed=new Map<int>();Map<float>*m_NextAttempt=new Map<float>();int m_ConvoySlot=-1;float m_NextTick=0;int m_State=0,m_Trip=0,m_Token=0,m_ReportId=0,m_TripDelivered=0;float m_Deadline=0,m_StockDeadline=-1;bool m_Stopped=false;
|
||||
Waypoint* m_MoveWaypoint=nullptr;Waypoint* m_HoldWaypoint=nullptr;string reason;bool Current(){return !m_Stopped&&Replication::IsServer()&&m_HQ->active;}void Audit(string why){reason=why;}
|
||||
'''+methods+r'''
|
||||
};
|
||||
struct Fixture{Mode mode;HQ hq;Service s;InventoryStorageManagerComponent inventory;Entity vehicle;std::array<Entity,140>items;std::array<Magazine,140>magazines;Entity rifle,launcher;Manager weapons;Weapon rifleWeapon,launcherWeapon;Muzzle rifleMuzzle,launcherMuzzle;Well well,wrongWell{2,0};Entity one,two;Agent a{&one},b{&two};Group recipients,donors;Utility recipientUtility,donorUtility;Sampler sampler;Unit recipient,donor;Combat combat;Truck truck;Receipt receipt;Cargo cargo;Convoy convoy;Ammo ammo;Entry demand,donorStatus;
|
||||
Fixture():sampler{&recipients,{&one,&two}}{
|
||||
hq.m_Mode=&mode;hq.convoy=&convoy;hq.convoys.tasks={&convoy};s.m_HQ=&hq;s.m_Mode=&mode;
|
||||
one.weapons=&weapons;two.weapons=&weapons;weapons.weapons={&rifle,&launcher};rifle.weapon=&rifleWeapon;rifleWeapon.owner=&rifle;rifleWeapon.muzzles={&rifleMuzzle};rifleMuzzle.well=&well;
|
||||
launcher.weapon=&launcherWeapon;launcherWeapon.owner=&launcher;launcherWeapon.kind=EWeaponType::WT_ROCKETLAUNCHER;launcherWeapon.muzzles={&launcherMuzzle};launcherMuzzle.well=&well;launcherMuzzle.kind=EMuzzleType::MT_RPGMuzzle;launcher.parent=&one;
|
||||
for(int i=0;i<140;i++){items[i].ammoComp=&magazines[i];magazines[i].owner=&items[i];magazines[i].well=&well;}
|
||||
vehicle.inventory=&inventory;vehicle.group=&donors;truck.Entity=&vehicle;truck.Group=&donors;truck.Combat=&combat;
|
||||
mode.ledger.owned=&donors;convoy.Receipt=&receipt;convoy.Vehicles={&truck,&truck,&truck,&truck,&truck,&truck};convoy.Cargo={&cargo};
|
||||
one.group=&recipients;two.group=&recipients;recipients.agents={&a,&b};recipient.Group=&recipients;recipient.Utility=&recipientUtility;recipient.StatusSampler=&sampler;recipient.ForceSourceId="recipient";
|
||||
donor.Group=&donors;donor.Utility=&donorUtility;donor.ForceSourceId="donor";hq.m_Units={&recipient,&donor};
|
||||
demand.SourceId="recipient";demand.AmmoState=&ammo;donorStatus.SourceId="donor";donorStatus.AmmoState=&ammo;
|
||||
for(int i=0;i<48;i++)inventory.items.Insert(&items[i]);
|
||||
}
|
||||
bool Plan(float now=0){return s.TryPlan(&recipient,&donor,&demand,&donorStatus,now);}
|
||||
void Refresh(float now,int id){demand.ObservedAt=now;donorStatus.ObservedAt=now;demand.MessageId=id;}
|
||||
void Unchanged(){assert(s.m_Trip==0&&s.m_Consumed->Get("recipient")==0&&s.m_NextAttempt->Get("recipient")==0&&recipient.LogisticsReservation==0&&truck.SupplyToken==0&&hq.downlinks==0&&!truck.SupplyHeld&&!convoy.Stopped&&!s.m_Recipient&&!s.m_Donor);}
|
||||
};
|
||||
int main(){
|
||||
// Actual Compatible must reject wrong-well, empty or malformed stock before
|
||||
// any report/cooldown consumption, reservation, downlink or convoy hold.
|
||||
for(int bad=0;bad<5;bad++){Fixture f;for(auto&mag:f.magazines){if(bad==0)mag.well=&f.wrongWell;if(bad==1)mag.rounds=0;if(bad==2)mag.capacity=0;if(bad==3)mag.rounds=31;if(bad==4)mag.well=nullptr;}f.s.Stock(0);assert(!f.Plan());f.Unchanged();}
|
||||
{Fixture f;f.s.Stock(0);f.rifleMuzzle.well=&f.wrongWell;assert(!f.Plan());f.Unchanged();f.rifleMuzzle.well=&f.well;assert(f.Plan());}
|
||||
// Same delivered recipient report remains available to a later compatible
|
||||
// truck sharing the real per-source consumption/cooldown maps.
|
||||
{Fixture first,second;Map<int> consumed;Map<float> cooldown;second.hq.convoys.tasks={&first.convoy,&second.convoy};second.hq.convoy=&first.convoy;second.hq.m_Units={&first.recipient,&second.donor};
|
||||
assert(first.s.Bind(&first.convoy,0,&consumed,&cooldown));assert(second.s.Bind(&second.convoy,1,&consumed,&cooldown));
|
||||
for(auto&mag:first.magazines){mag.well=&first.wrongWell;}first.s.Stock(0);second.s.Stock(0);assert(!first.Plan());first.Unchanged();
|
||||
assert(second.s.TryPlan(&first.recipient,&second.donor,&first.demand,&second.donorStatus,0));assert(consumed.Get("recipient")==1&&cooldown.Get("recipient")==180000&&first.recipient.LogisticsReservation==100129&&second.hq.downlinks==1&&first.hq.downlinks==0);}
|
||||
// A usable compatible item must still be a surviving unspent frozen identity.
|
||||
{Fixture f;for(auto&mag:f.magazines)mag.rounds=0;f.magazines[48].rounds=30;f.s.Stock(0);f.inventory.items.Insert(&f.items[48]);assert(!f.Plan());f.Unchanged();f.magazines[0].rounds=30;f.s.m_Spent.Insert(&f.items[0]);assert(!f.Plan());f.Unchanged();f.s.m_Spent.Clear();assert(f.Plan());}
|
||||
// Hard 32 original carriers and 96 captured magazines remain fail-closed.
|
||||
{Fixture f;f.s.Stock(0);f.sampler.original.resize(33,&f.one);assert(!f.Plan());f.Unchanged();}
|
||||
{Fixture f;f.s.Stock(0);for(int i=48;i<97;i++){f.s.m_Stock.Insert(&f.items[i]);f.inventory.items.Insert(&f.items[i]);}assert(!f.Plan());f.Unchanged();}
|
||||
{Fixture f;for(int i=48;i<96;i++)f.inventory.items.Insert(&f.items[i]);for(int i=0;i<95;i++)f.magazines[i].well=&f.wrongWell;f.s.Stock(0);assert(f.Plan());}
|
||||
// Small-arms demand cannot borrow launcher compatibility, but the dedicated
|
||||
// launcher path still supports its real empty reloadable muzzle and rejects disposables.
|
||||
{Fixture f;f.weapons.weapons={&f.launcher};f.s.Stock(0);assert(!f.Plan());f.Unchanged();assert(f.s.TryPlanLauncher(&f.recipient,&f.donor,&f.demand,&f.donorStatus,0));}
|
||||
{Fixture f;f.weapons.weapons={&f.launcher};f.launcherMuzzle.disposable=true;f.s.Stock(0);assert(!f.s.TryPlanLauncher(&f.recipient,&f.donor,&f.demand,&f.donorStatus,0));f.Unchanged();}
|
||||
{Fixture f;for(int i=48;i<96;i++)f.inventory.items.Insert(&f.items[i]);f.s.Stock(0);
|
||||
for(int i=0;i<95;i++)f.magazines[i].well=&f.wrongWell;
|
||||
assert(f.s.TryPlanLauncher(&f.recipient,&f.donor,&f.demand,&f.donorStatus,0));
|
||||
assert(f.s.m_LauncherTrip);}
|
||||
|
||||
{Fixture f;f.s.Stock(0);for(auto&mag:f.magazines)mag.well=&f.wrongWell;assert(!f.s.TryPlanLauncher(&f.recipient,&f.donor,&f.demand,&f.donorStatus,0)&&f.truck.SupplyToken==0);}
|
||||
|
||||
{Fixture f;f.s.Stock(0);f.ammo.SmallArmsRounds=999;f.ammo.LauncherMagazines=0;assert(!f.Plan());assert(f.s.TryPlanLauncher(&f.recipient,&f.donor,&f.demand,&f.donorStatus,0));assert(f.s.m_LauncherTrip&&!f.s.m_MineTrip);}
|
||||
for(int bad=0;bad<7;bad++){Fixture f;f.s.Stock(0);f.ammo.SmallArmsRounds=999;if(bad==0)f.ammo.LauncherComplete=false;if(bad==1)f.ammo.LauncherMuzzles=0;if(bad==2)f.ammo.LauncherRounds=1;if(bad==3)f.ammo.LauncherChambers=1;if(bad==4)f.ammo.Members=1;if(bad==5)f.demand.ObservedAt=-1;if(bad==6)f.demand.ObservedAt=1;
|
||||
assert(!f.s.TryPlanLauncher(&f.recipient,&f.donor,&f.demand,&f.donorStatus,0));assert(f.s.m_State==1&&f.truck.SupplyToken==0);}
|
||||
|
||||
// Additional mounted stock callbacks belong to the same initial freeze barrier.
|
||||
{Fixture f;Cargo mounted;mounted.Finished=false;f.convoy.supply=true;f.convoy.Cargo.Insert(&mounted);
|
||||
f.s.Stock(0);assert(f.s.m_State==0&&f.s.m_Stock.IsEmpty());
|
||||
mounted.Finished=true;f.inventory.items.Insert(&f.items[48]);f.s.Stock(1000);
|
||||
assert(f.s.m_State==1&&f.s.m_Stock.Count()==49&&f.s.m_Stock.Contains(&f.items[48]));}
|
||||
// Bind accepts only an exact current slot and non-null shared demand histories.
|
||||
{Fixture f;Map<int> consumed;Map<float> cooldown;Convoy other;
|
||||
assert(!f.s.Bind(nullptr,0,&consumed,&cooldown));assert(!f.s.Bind(&f.convoy,-1,&consumed,&cooldown));
|
||||
assert(!f.s.Bind(&f.convoy,20,&consumed,&cooldown));assert(!f.s.Bind(&f.convoy,1,&consumed,&cooldown));
|
||||
assert(!f.s.Bind(&other,0,&consumed,&cooldown));assert(!f.s.Bind(&f.convoy,0,nullptr,&cooldown));assert(!f.s.Bind(&f.convoy,0,&consumed,nullptr));
|
||||
assert(f.s.Bind(&f.convoy,0,&consumed,&cooldown));assert(f.s.Task()==&f.convoy);assert(!f.s.Bind(&f.convoy,0,&consumed,&cooldown));}
|
||||
// Any prior startup/stock/trip/stop refuses late binding.
|
||||
for(int began=0;began<6;began++){Fixture f;Map<int> consumed;Map<float> cooldown;
|
||||
if(began==0){f.s.Stock(0);}if(began==1){f.s.m_NextTick=1000;}if(began==2){f.s.m_Trip=1;}
|
||||
if(began==3){f.s.m_StockDeadline=90000;}if(began==4){f.s.m_Stopped=true;}if(began==5){f.s.m_State=1;}
|
||||
assert(!f.s.Bind(&f.convoy,0,&consumed,&cooldown));}
|
||||
// Second convoy remains valid independently of canonical first, but never follows replacement/reordering.
|
||||
for(int mutation=0;mutation<3;mutation++){Fixture f;Convoy first,replacement;Map<int> consumed;Map<float> cooldown;
|
||||
f.hq.convoy=&first;f.hq.convoys.tasks={&first,&f.convoy};assert(f.s.Bind(&f.convoy,1,&consumed,&cooldown));
|
||||
f.s.Stock(0);assert(f.s.TruckValid()&&f.s.Task()==&f.convoy&&f.s.m_Stock.Count()==48);
|
||||
if(mutation==0)f.hq.convoys.tasks[1]=&replacement;
|
||||
if(mutation==1)std::swap(f.hq.convoys.tasks[0],f.hq.convoys.tasks[1]);
|
||||
if(mutation==2)f.hq.convoys.tasks.resize(1);
|
||||
assert(!f.s.TruckValid()&&!f.Plan()&&f.s.Task()==&f.convoy);}
|
||||
// Canonical legacy startup also pins its first identity before readiness.
|
||||
{Fixture f;Convoy replacement;f.convoy.Ready=false;f.s.Stock(0);assert(f.s.Task()==&f.convoy);
|
||||
f.hq.convoy=&replacement;f.s.Stock(1000);assert(f.s.m_Stopped&&f.s.Task()==&f.convoy);}
|
||||
// Every bound slot owns a disjoint 128-trip token range, including its last allowed trip.
|
||||
for(int slot=0;slot<20;slot++){Fixture f;Map<int> consumed;Map<float> cooldown;
|
||||
f.hq.convoys.tasks.resize(slot+1,nullptr);f.hq.convoys.tasks[slot]=&f.convoy;assert(f.s.Bind(&f.convoy,slot,&consumed,&cooldown));
|
||||
f.s.Stock(0);assert(f.Plan());assert(f.s.m_Token==100000+slot*128+1);f.s.Finish("test released");
|
||||
f.s.m_Trip=127;f.Refresh(180000,2);assert(f.Plan(180000));assert(f.s.m_Token==100000+(slot+1)*128);
|
||||
f.s.Finish("test released");f.Refresh(360000,3);assert(!f.Plan(360000));}
|
||||
// Separate convoys share report consumption and failed-attempt cooldowns for the same recipient source.
|
||||
{Fixture first,second;Map<int> consumed;Map<float> cooldown;
|
||||
second.hq.convoys.tasks={&first.convoy,&second.convoy};second.hq.convoy=&first.convoy;
|
||||
assert(first.s.Bind(&first.convoy,0,&consumed,&cooldown));assert(second.s.Bind(&second.convoy,1,&consumed,&cooldown));
|
||||
first.s.Stock(0);second.s.Stock(0);first.hq.routeAvailable=false;assert(first.Plan());
|
||||
assert(consumed.Get("recipient")==1&&cooldown.Get("recipient")==180000);
|
||||
second.Refresh(180000,1);assert(!second.Plan(180000));second.Refresh(179999,2);assert(!second.Plan(179999));
|
||||
second.Refresh(180000,2);assert(second.Plan(180000));assert(first.s.m_Consumed->Get("recipient")==2&&first.s.m_NextAttempt->Get("recipient")==360000);}
|
||||
// Actual inventory aggregation collapses repeated native storage references, not distinct identical-prefab magazines.
|
||||
{Fixture f;f.inventory.items.Insert(&f.items[0]);f.inventory.items.Insert(nullptr);f.s.Stock(0);assert(f.s.m_State==1&&!f.s.m_Stopped&&f.s.m_Stock.Count()==48);assert(f.s.m_Stock[0]!=f.s.m_Stock[1]);}
|
||||
// Malformed/non-magazine items never become spendable stock; native startup partial cargo stays partial.
|
||||
{Fixture f;f.inventory.items={&f.items[0],&f.items[1],&f.items[2],nullptr};f.items[1].magazine=false;f.items[2].magazine=false;f.items[2].prefab.name="rifle";f.s.Stock(0);assert(f.s.m_Stock.Count()==1&&f.s.m_State==1);}
|
||||
{Fixture f;f.cargo.Finished=false;f.s.Stock(0);assert(f.s.m_State==0&&f.s.m_Stock.IsEmpty());f.s.Stock(89999);assert(!f.s.m_Stopped&&f.s.m_Stock.IsEmpty());f.s.Stock(90000);assert(f.s.m_Stopped&&f.s.m_Stock.IsEmpty());}
|
||||
{Fixture f;f.cargo.Finished=false;f.s.Stock(0);f.cargo.Finished=true;f.inventory.items={&f.items[0]};f.s.Stock(1000);assert(f.s.m_Stock.Count()==1&&!f.s.m_Stopped);}
|
||||
{Fixture f;for(int i=48;i<97;i++)f.inventory.items.Insert(&f.items[i]);f.s.Stock(0);assert(f.s.m_Stopped&&!f.Plan());f.Unchanged();}
|
||||
{Fixture f;for(auto& item:f.items)f.inventory.items.Insert(&item);f.s.Stock(0);assert(f.s.m_Stopped&&f.s.m_Stock.IsEmpty());}
|
||||
{Fixture f;f.vehicle.inventory=nullptr;f.s.Stock(0);assert(f.s.m_Stopped&&!f.Plan());}
|
||||
{Fixture f;f.convoy.Ready=false;f.s.Stock(0);assert(f.s.m_State==0&&f.s.m_Stock.IsEmpty());}
|
||||
{Fixture f;f.receipt.Consumed=false;f.s.Stock(0);assert(f.s.m_Stopped&&f.s.m_Stock.IsEmpty());}
|
||||
// Supply weapons settle after crew deadline; matching ammo must be issued and settled before snapshot.
|
||||
{Fixture f;f.convoy.supply=true;f.convoy.MagazinesIssued=false;f.s.Stock(25000);assert(f.s.m_State==0&&f.s.m_Stock.IsEmpty());
|
||||
f.s.Stock(31000);assert(!f.s.m_Stopped&&f.s.m_State==0);f.convoy.MagazinesIssued=true;f.cargo.Finished=false;
|
||||
f.s.Stock(32000);assert(f.s.m_State==0&&f.s.m_Stock.IsEmpty());f.cargo.Finished=true;
|
||||
f.items[0].prefab.name="NATO_556_STANAG";f.s.Stock(33000);assert(f.s.m_State==1&&!f.s.m_Stopped&&f.s.m_Stock.Contains(&f.items[0]));}
|
||||
// Earliest admission: producer may finish weapons only at original Deadline+30000.
|
||||
{Fixture f;f.convoy.supply=true;f.convoy.MagazinesIssued=false;f.cargo.Finished=false;f.s.Stock(0);
|
||||
f.s.Stock(59999);assert(!f.s.m_Stopped&&f.s.m_Stock.IsEmpty());
|
||||
f.convoy.MagazinesIssued=true;f.s.Stock(60000);assert(!f.s.m_Stopped&&f.s.m_State==0);
|
||||
f.cargo.Finished=true;f.items[0].prefab.name="NATO_556_STANAG";f.s.Stock(89000);
|
||||
assert(!f.s.m_Stopped&&f.s.m_State==1&&f.s.m_Stock.Contains(&f.items[0]));}
|
||||
// Missing first-phase submission and missing second phase are bounded by one immutable deadline.
|
||||
for(int phase=0;phase<2;phase++){Fixture f;f.convoy.supply=true;f.convoy.CargoIssued=phase!=0;f.convoy.MagazinesIssued=false;
|
||||
f.s.Stock(25000);f.s.Stock(114999);assert(!f.s.m_Stopped&&f.s.m_StockDeadline==115000&&f.s.m_Stock.IsEmpty());
|
||||
f.s.Stock(115000);assert(f.s.m_Stopped&&f.s.m_Stock.IsEmpty());}
|
||||
// Faction catalogs may yield 96 distinct magazine identities; weapons are excluded.
|
||||
{Fixture f;for(int i=48;i<96;i++)f.inventory.items.Insert(&f.items[i]);f.items[0].prefab.name="NATO_556_STANAG";
|
||||
f.items[96].magazine=false;f.inventory.items.Insert(&f.items[96]);f.s.Stock(0);
|
||||
assert(!f.s.m_Stopped&&f.s.m_State==1&&f.s.m_Stock.Count()==96&&f.s.m_Stock.Contains(&f.items[0])&&!f.s.m_Stock.Contains(&f.items[96]));}
|
||||
// Detached known-zero demand also requires settled original designation; unknown never authorizes.
|
||||
{Fixture f;MineBatch batch;f.convoy.supply=true;f.convoy.MineStock=&batch;f.items[48].readyMine=true;batch.items={&f.items[48]};f.inventory.items.Insert(&f.items[48]);f.s.Stock(0);
|
||||
for(int n: {0,2,3}){f.ammo.ReadyMines=n;assert(!f.s.TryPlanMines(&f.recipient,&f.donor,&f.demand,&f.donorStatus,0));}
|
||||
f.ammo.ReadyMines=0;f.hq.designated=true;f.one.released=f.two.released=true;assert(!f.s.TryPlanMines(&f.recipient,&f.donor,&f.demand,&f.donorStatus,0));f.one.released=f.two.released=false;assert(f.s.TryPlanMines(&f.recipient,&f.donor,&f.demand,&f.donorStatus,0));f.s.Finish("reset");f.s.m_Consumed->data.clear();f.s.m_NextAttempt->data.clear();f.hq.designated=false;
|
||||
f.ammo.ReadyMines=1;f.ammo.MineComplete=false;assert(!f.s.TryPlanMines(&f.recipient,&f.donor,&f.demand,&f.donorStatus,0));f.ammo.MineComplete=true;
|
||||
batch.complete=false;assert(!f.s.TryPlanMines(&f.recipient,&f.donor,&f.demand,&f.donorStatus,0));batch.complete=true;
|
||||
assert(f.s.TryPlanMines(&f.recipient,&f.donor,&f.demand,&f.donorStatus,0));assert(f.s.m_MineTrip&&f.s.m_MineStock.Count()==1);}
|
||||
// A submitted unknown mine retains the real HQ claim across a newer delivered
|
||||
// report and expired shared cooldown; a second truck cannot race the same actor.
|
||||
{Fixture first,second;Leaf leaf;leaf.unresolved=true;first.s.Stock(0);assert(first.Plan());first.s.m_MineMove=&leaf;first.s.m_MineTrip=true;first.s.Finish("unknown native move");
|
||||
assert(first.s.m_State==7&&first.recipient.LogisticsReservation==100001&&first.truck.SupplyToken==100001);
|
||||
second.s.Stock(0);second.s.m_HQ=&first.hq;first.hq.convoy=&second.convoy;first.hq.convoys.tasks={&second.convoy};second.s.m_Consumed=first.s.m_Consumed;second.s.m_NextAttempt=first.s.m_NextAttempt;
|
||||
first.Refresh(180001,2);second.donorStatus.ObservedAt=180001;
|
||||
assert(!second.s.TryPlan(&first.recipient,&second.donor,&first.demand,&second.donorStatus,180001));assert(first.recipient.LogisticsReservation==100001);
|
||||
leaf.unresolved=false;first.s.Finish("settled");assert(first.recipient.LogisticsReservation==0);
|
||||
assert(second.s.TryPlan(&first.recipient,&second.donor,&first.demand,&second.donorStatus,180001));}
|
||||
// Removed stock is unavailable; a different magazine added after capture does not replace its identity.
|
||||
{Fixture f;f.s.Stock(0);f.inventory.items={&f.items[48]};assert(!f.Plan());f.Unchanged();f.inventory.items.Insert(&f.items[0]);assert(f.Plan());assert(f.s.m_Stock.Count()==48&&!f.s.m_Stock.Contains(&f.items[48]));}
|
||||
{Fixture f;f.s.Stock(0);f.s.m_Spent=f.s.m_Stock;assert(!f.Plan());f.Unchanged();}
|
||||
// A delivered report is tied to exact original source identities and original still-owned members.
|
||||
{Fixture f;f.s.Stock(0);f.demand.SourceId="foreign";assert(!f.Plan());f.Unchanged();}
|
||||
{Fixture f;f.s.Stock(0);f.donorStatus.SourceId="foreign";assert(!f.Plan());f.Unchanged();}
|
||||
{Fixture f;f.s.Stock(0);f.one.released=true;assert(!f.Plan());f.Unchanged();assert(!f.s.m_Recipient&&!f.s.m_Donor);}
|
||||
{Fixture f;f.s.Stock(0);Entity foreign;foreign.group=&f.recipients;Agent extra{&foreign};f.recipients.agents.Insert(&extra);assert(!f.Plan());f.Unchanged();}
|
||||
// Real HQ force reservation refuses busy/support-ineligible or silent-radio recipients without consuming the demand.
|
||||
for(int refusal=0;refusal<5;refusal++){Fixture f;f.s.Stock(0);void* owned=&f;
|
||||
if(refusal==0){f.recipient.Assignment=owned;}if(refusal==1){f.recipient.Downlink=owned;}if(refusal==2){f.recipient.Waypoint=owned;}if(refusal==3){f.recipient.Radio=nullptr;}if(refusal==4){f.recipient.eligible=false;}
|
||||
assert(!f.Plan());f.Unchanged();assert(!f.s.m_Recipient&&!f.s.m_Donor);
|
||||
f.recipient.Assignment=nullptr;f.recipient.Downlink=nullptr;f.recipient.Waypoint=nullptr;f.recipient.Radio=&f;f.recipient.eligible=true;
|
||||
assert(f.Plan());assert(f.s.m_Trip==1&&f.s.m_Consumed->Get("recipient")==1&&f.recipient.LogisticsReservation==100001);}
|
||||
{Fixture f;f.s.Stock(0);f.recipient.LogisticsReservation=7;assert(!f.Plan());assert(f.recipient.LogisticsReservation==7&&f.s.m_Trip==0&&f.hq.downlinks==0);}
|
||||
// Failed truck downlink is still a consumed planning attempt; cleanup preserves all cargo and other ownership.
|
||||
{Fixture f;f.s.Stock(0);f.hq.routeAvailable=false;assert(f.Plan());assert(f.s.m_State==1&&f.s.m_Trip==1&&f.s.m_Consumed->Get("recipient")==1&&f.recipient.LogisticsReservation==0&&f.truck.SupplyToken==0&&f.inventory.items.Count()==48);
|
||||
f.hq.routeAvailable=true;f.Refresh(180000,1);assert(!f.Plan(180000)); // same consumed message cannot replay after cooldown
|
||||
f.Refresh(179999,2);assert(!f.Plan(179999));f.Refresh(180000,2);assert(f.Plan(180000));assert(f.s.m_Trip==2&&f.s.m_Deadline==300000);}
|
||||
// A stale-but-still-admissible demand gets only the remaining evidence horizon, never a new full lifetime.
|
||||
{Fixture f;f.s.Stock(0);assert(f.Plan(120000));assert(f.s.m_Deadline==180000);assert(!f.Plan(120000)&&f.hq.downlinks==1);}
|
||||
// Independent guarded failures do not leak reservations or acquire replacement force identities.
|
||||
for(int refusal=0;refusal<7;refusal++){Fixture f;f.s.Stock(0);
|
||||
if(refusal==0){f.recipient.HomeGuard=true;}if(refusal==1){f.truck.Combat->Held=true;}if(refusal==2){f.vehicle.captured=true;}if(refusal==3){f.mode.ledger.record.Eliminated=true;}if(refusal==4){f.donor.PendingConvoyOrder=&f;}if(refusal==5){f.ammo.Complete=false;}if(refusal==6){f.demand.Position.x=201;}
|
||||
assert(!f.Plan());f.Unchanged();}
|
||||
}
|
||||
''')
|
||||
print('PASS: actual Compatible and bounded stock preflight before report/claim consumption, later compatible truck, launcher controls, convoy binding, finite identities, disjoint tokens, shared report replay/cooldown, original recipients and HQ cleanup')
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"finding": "Ordinary rifle cleanup releases shared recipient and truck claims while an accepted native magazine move or empty return remains unresolved. A newer delivered report after shared180000ms cooldown admits another original truck; the actual unchanged leaf can then submit the same still-carried empty to a different donor storage.",
|
||||
"historical_scope": "Existing test_infantry_resupply_coordinator explicitly expected ordinary rifle Stop to release the claims. Mine and launcher quarantine increments preserved rifle behavior by scope; docs/evidence/rifle-transfer-cancellation-2026-10-02 and docs/infantry-resupply.md explicitly left uncertainty behavior unchanged. No documented cross-truck exclusion guarantee was found that makes the released recipient claim safe.",
|
||||
"change": "Only existing ERR_InfantryResupply Finish and PollTransfers conditions generalize state7 to every unresolved magazine leaf; audit wording describes existing leaf settlement. No change to transfer leaf, stock ledger, negative callback semantics, native operation, retries or refunds.",
|
||||
"proof": {
|
||||
"planning": "Actual Bind/TryPlan/Finish/HQ ReserveLogistics/ReleaseLogistics; two convoy slots0/1, tokens100001/100129, fresh report2 at180001ms after report1/cooldown180000. Baseline compiles then fails second-truck refusal; proposal keeps report2 untouched until settlement then admits it.",
|
||||
"interference": "Unchanged actual transfer leaf executes two accepted empty-return submissions with the same original empty identity and distinct original donor storage. Original operation is stopped before second submission at180001ms. One physical completion proves only first donor custody, leaving the competing submitted operation unresolved.",
|
||||
"cleanup": "Actual Stop/PollTransfers keeps original claims, clears only owned waypoints, then releases exactly once after leaf settlement; stopped service performs no new work."
|
||||
},
|
||||
"limits": [
|
||||
"Native inventory and radio/group boundaries are doubles; no physical reproduction, native compilation, multiplayer or performance qualification.",
|
||||
"Rifle Unresolved remains acceptance-based and a terminal negative callback retains its existing settlement semantics; this does not add launcher-style RefusedAtSource proof.",
|
||||
"Unknown accepted operation can retain force claims indefinitely as existing mine/launcher quarantine does; no unsafe timeout release."
|
||||
],
|
||||
"target_and_original_untouched": true
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
--- a/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c
|
||||
+++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c
|
||||
@@ -106,10 +106,10 @@
|
||||
protected void PollTransfers(float now)
|
||||
{
|
||||
if (m_Mounted) m_Mounted.Tick(now);
|
||||
- if (m_Move && !m_Move.Unresolved() && (m_State <= 1 || (m_State == 7 && m_LauncherTrip)))
|
||||
+ if (m_Move && !m_Move.Unresolved() && (m_State <= 1 || m_State == 7))
|
||||
{
|
||||
m_Move = null;
|
||||
- if (m_State == 7) Finish("launcher custody settled; original claims released without retry or refund");
|
||||
+ if (m_State == 7) Finish("magazine custody settled; original claims released without retry or refund");
|
||||
}
|
||||
if (m_MineMove && !m_MineMove.Unresolved() && (m_State <= 1 || m_State == 7))
|
||||
{
|
||||
@@ -425,8 +425,8 @@
|
||||
ClearWaypoints();
|
||||
m_Order = null;
|
||||
// A late native move must not race another truck's newer report. Retain both
|
||||
- // exact claims until this one submitted identity proves custody or deletion.
|
||||
- if ((m_MineMove && m_MineMove.Unresolved()) || (m_LauncherTrip && m_Move && m_Move.Unresolved())) { m_State = 7; return; }
|
||||
+ // exact claims until the existing transfer leaf reports that its operation has settled.
|
||||
+ if ((m_MineMove && m_MineMove.Unresolved()) || (m_Move && m_Move.Unresolved())) { m_State = 7; return; }
|
||||
if (m_Recipient) m_HQ.ReleaseLogistics(m_Recipient.Group, m_Token);
|
||||
if (m_Truck && m_Truck.SupplyToken == m_Token) { m_Truck.SupplyToken = 0; m_Truck.SupplyHeld = false; }
|
||||
m_Recipient = null; m_Donor = null; m_Order = null; m_Receiving = null; m_State = 1; m_MineTrip = false; m_LauncherTrip = false; m_MineRecipientSlot = -1;
|
||||
--- a/tests/test_infantry_resupply_planning.py
|
||||
+++ b/tests/test_infantry_resupply_planning.py
|
||||
@@ -251,6 +251,20 @@
|
||||
f.ammo.ReadyMines=1;f.ammo.MineComplete=false;assert(!f.s.TryPlanMines(&f.recipient,&f.donor,&f.demand,&f.donorStatus,0));f.ammo.MineComplete=true;
|
||||
batch.complete=false;assert(!f.s.TryPlanMines(&f.recipient,&f.donor,&f.demand,&f.donorStatus,0));batch.complete=true;
|
||||
assert(f.s.TryPlanMines(&f.recipient,&f.donor,&f.demand,&f.donorStatus,0));assert(f.s.m_MineTrip&&f.s.m_MineStock.Count()==1);}
|
||||
+ // An accepted unresolved rifle move keeps both original claims across a new
|
||||
+ // report after the shared180s cooldown. Distinct convoy slots own distinct tokens.
|
||||
+ {Fixture first,second;Leaf leaf;leaf.unresolved=true;Map<int> consumed;Map<float> cooldown;
|
||||
+ first.hq.convoys.tasks={&first.convoy,&second.convoy};first.hq.m_Units={&first.recipient,&first.donor,&second.donor};second.s.m_HQ=&first.hq;
|
||||
+ assert(first.s.Bind(&first.convoy,0,&consumed,&cooldown));assert(second.s.Bind(&second.convoy,1,&consumed,&cooldown));
|
||||
+ first.s.Stock(0);second.s.Stock(0);assert(first.Plan());first.s.m_Move=&leaf;first.s.Finish("accepted native rifle move remains unresolved");
|
||||
+ assert(first.s.m_Move==&leaf&&leaf.Unresolved());
|
||||
+ first.Refresh(180001,2);second.donorStatus.ObservedAt=180001;
|
||||
+ assert(!second.s.TryPlan(&first.recipient,&second.donor,&first.demand,&second.donorStatus,180001));
|
||||
+ assert(first.s.m_State==7&&first.recipient.LogisticsReservation==100001&&first.truck.SupplyToken==100001);
|
||||
+ assert(consumed.Get("recipient")==1&&cooldown.Get("recipient")==180000&&second.s.m_Trip==0);
|
||||
+ leaf.unresolved=false;first.s.Finish("settled");assert(first.recipient.LogisticsReservation==0);
|
||||
+ assert(second.s.TryPlan(&first.recipient,&second.donor,&first.demand,&second.donorStatus,180001));
|
||||
+ assert(first.recipient.LogisticsReservation==100129&&second.truck.SupplyToken==100129&&first.truck.SupplyToken==0);}
|
||||
// A submitted unknown mine retains the real HQ claim across a newer delivered
|
||||
// report and expired shared cooldown; a second truck cannot race the same actor.
|
||||
{Fixture first,second;Leaf leaf;leaf.unresolved=true;first.s.Stock(0);assert(first.Plan());first.s.m_MineMove=&leaf;first.s.m_MineTrip=true;first.s.Finish("unknown native move");
|
||||
--- a/tests/test_infantry_resupply_coordinator.py
|
||||
+++ b/tests/test_infantry_resupply_coordinator.py
|
||||
@@ -81,7 +81,7 @@
|
||||
{Fixture f;f.order.result=-1;f.s.Tick(0);assert(f.s.m_State==1&&f.hq.token==0&&f.truck.SupplyToken==0&&!f.truck.SupplyHeld&&f.truck.clears==0);}
|
||||
{Fixture f;f.s.m_State=4;f.order.result=-1;f.s.Tick(0);assert(f.s.waypointCalls==0&&f.s.transfers==0&&f.hq.token==0);}
|
||||
{Fixture f;f.hq.token=99;f.truck.SupplyToken=99;f.truck.SupplyHeld=true;f.s.Tick(0);assert(f.s.m_State==1&&f.hq.token==99&&f.truck.SupplyToken==99&&f.truck.SupplyHeld);}
|
||||
- {Fixture f;Waypoint own1{1},own2{2},other{3};f.group.points={&own1,&other,&own2};f.s.m_MoveWaypoint=&own1;f.s.m_HoldWaypoint=&own2;Leaf leaf;f.s.m_Move=&leaf;f.truck.SupplyHeld=true;f.s.Stop();assert(f.group.points.size()==1&&f.group.points[0]==&other&&leaf.stops==1&&f.s.m_Move==&leaf&&f.hq.token==0&&!f.truck.SupplyHeld&&f.s.m_Stopped);int audits=f.s.audits;f.s.Stop();f.s.Tick(5000);assert(f.s.audits==audits&&leaf.stops==1);}
|
||||
+ {Fixture f;Waypoint own1{1},own2{2},other{3};f.group.points={&own1,&other,&own2};f.s.m_MoveWaypoint=&own1;f.s.m_HoldWaypoint=&own2;Leaf leaf;f.s.m_Move=&leaf;f.truck.SupplyHeld=true;f.s.Stop();assert(f.group.points.size()==1&&f.group.points[0]==&other&&leaf.stops==1&&f.s.m_Move==&leaf&&f.hq.token==7&&f.truck.SupplyHeld&&f.s.m_State==7&&f.s.m_Stopped);int audits=f.s.audits;f.s.Stop();f.s.Tick(5000);assert(f.s.audits==audits&&leaf.stops==1);leaf.unresolved=false;f.s.Tick(6000);assert(f.hq.token==0&&!f.truck.SupplyHeld&&f.s.m_State==1&&!f.s.m_Move);}
|
||||
{Fixture f;Leaf leaf;f.s.m_Move=&leaf;f.s.Finish("timeout");f.s.Tick(0);assert(f.s.m_Move==&leaf);leaf.unresolved=false;f.s.Tick(1000);assert(f.s.m_Move==nullptr);}
|
||||
{Fixture f;f.s.m_State=3;f.physics.linear.x=std::numeric_limits<float>::quiet_NaN();f.s.Tick(0);assert(f.s.m_HeldAt==-1&&f.donor.NextStatus==-1);}
|
||||
{Fixture f;f.s.m_State=3;f.physics.angular.x=std::numeric_limits<float>::quiet_NaN();f.s.Tick(0);assert(f.s.m_HeldAt==-1&&f.donor.NextStatus==-1);}
|
||||
--- a/tests/test_infantry_ammo_transfer.py
|
||||
+++ b/tests/test_infantry_ammo_transfer.py
|
||||
@@ -150,6 +150,24 @@
|
||||
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(){
|
||||
+
|
||||
+ // The shared force claim is necessary: independent rifle leaves can otherwise
|
||||
+ // submit the same still-carried empty to two different trucks. Native acceptance
|
||||
+ // is delayed here; this proves submission interference, not an engine outcome.
|
||||
+ {EmptyFixture first;Fixture second;ERR_GameMode::current=&first.mode;
|
||||
+ first.ledger.records.Insert(&second.donorRecord);second.source.selected=&second.sourceStorage;
|
||||
+ auto old=first.Job();assert(old.Tick(0)==PENDING&&old.Unresolved());
|
||||
+ assert(old.m_ReturnMagazine==&first.empty&&old.m_ReturnStorage==&first.sourceStorage);
|
||||
+ old.Stop();assert(old.Unresolved()&&old.Tick(180001)==FAILED);
|
||||
+ ERR_InfantryAmmoTransfer next(&first.mode,&second.truck,&second.donorGroup,&first.recipient,&first.recipientGroup,&second.magEntity,true);
|
||||
+ assert(next.Tick(180001)==PENDING&&next.Unresolved());
|
||||
+ assert(first.destination.calls==2&&next.m_ReturnMagazine==old.m_ReturnMagazine);
|
||||
+ assert(next.m_ReturnStorage==&second.sourceStorage&&next.m_ReturnStorage!=old.m_ReturnStorage);
|
||||
+ assert(first.destination.items.Contains(&first.empty)&&first.source.calls==0&&second.source.calls==0);
|
||||
+ // No duplicate object is invented: one physical completion can settle only its
|
||||
+ // original donor proof; the competing outstanding submission remains unknown.
|
||||
+ first.Return();old.m_ReturnCallback->OnComplete();assert(!old.Unresolved()&&next.Unresolved());
|
||||
+ assert(old.Tick(180002)==FAILED&&first.source.calls==0&&second.source.calls==0);}
|
||||
// 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();
|
||||
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"approved": true,
|
||||
"review_type": "Independent read-only source, actual-method harness and preserved result review; no test/compiler/native rerun.",
|
||||
"files": {
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c": {
|
||||
"baseline_sha256": "1bfc1079961eaecee0c1ebb434570aaeb359c008f9f309033b33582092557b35",
|
||||
"proposal_sha256": "ca8eee2704e7758172e33014404bb1307c683f19b561b840d4592f6312051e62",
|
||||
"index_sha256": "966068555a6724e620a2c377b98d8dc02f141466c5cdd44636f86cb1cfe9ac78"
|
||||
},
|
||||
"tests/test_infantry_resupply_planning.py": {
|
||||
"baseline_sha256": "20747ffda8754f81f3b9e9912b9f60a300c439f2ea2c473bb900302f61dd691f",
|
||||
"proposal_sha256": "9879a27816dbc6b9c4da19c4714407614b4c6e20b2dd831b2701e5f3500ede6a",
|
||||
"index_sha256": "211e3d0ee20242f271afc46885e1ba7845ff2406d663bfe5118f40578cd5d709"
|
||||
},
|
||||
"tests/test_infantry_resupply_coordinator.py": {
|
||||
"baseline_sha256": "f9cf7d583a25a12cec9f5f80539b2590449560331f4ef34e33ea2db283c5d54a",
|
||||
"proposal_sha256": "a7eaa26e21f587fd8abde5dee6f7f8afc1e9f2f7ed0bcf40ed6a087a56908adc",
|
||||
"index_sha256": "65fa119778289175766ba7fdecd9e5685199736dffecc32056692121cbc6a682"
|
||||
},
|
||||
"tests/test_infantry_ammo_transfer.py": {
|
||||
"baseline_sha256": "0d2ebe4d5c18a4187745784013d07df621b8495967d0c01f39bd5a68ae574d26",
|
||||
"proposal_sha256": "18029a092262d0d1a309108a158597a174c1a05f58157eafd096c1c707fa0e29",
|
||||
"index_sha256": "e1172dda6350d2f8b89166ba63995cd1590435930ba220cd38b022307103a306"
|
||||
}
|
||||
},
|
||||
"patch_sha256": "ece65980fbe99627d6984e3d964a4aa30d6d80bcc44939245c49644e0225bb6a",
|
||||
"source_manifest_sha256": "7d98965a23809a0dc4999a762c6dd8240f37cfc68290035fb884ab07744e33ea",
|
||||
"test_results_sha256": "c68108d773de900e6d559fd8f63829b8bdb2084a3e885820a67aae89d3b7bed9",
|
||||
"findings": [],
|
||||
"conclusions": [
|
||||
"Finish retains the exact ordinary rifle leaf, recipient token and donor truck token while existing Unresolved returns true; clears only owned waypoints/order as before.",
|
||||
"PollTransfers clears settled leaf before Finish, including stopped services; matching-token release semantics unchanged. No new native inventory calls, retries, refunds or stock changes.",
|
||||
"Actual TryPlan plus actual HQ ReserveLogistics/ReleaseLogistics reproduces second-truck admission at fresh report2 / 180001ms after previous cooldown; baseline compiled/runtime failed, proposal passes. Claim retention precedes report consumption, and settlement allows later matching plan.",
|
||||
"Actual unchanged leaf test shows two accepted delayed empty-return submissions can reference the same original empty and different donor destinations if force exclusivity is released. This is modeled interference, not claimed native outcome.",
|
||||
"Existing mine/launcher state7 paths remain behaviorally unchanged; ordinary leaf terminal-negative and acceptance semantics are not broadened."
|
||||
],
|
||||
"limits": [
|
||||
"Unknown accepted operations may retain claims indefinitely until existing custody/deletion/callback rules settle.",
|
||||
"Planning/coordinator leaf responses and native inventory/radio/group behavior use explicit doubles; separate actual leaf harness covers transaction semantics.",
|
||||
"No native compilation, physical delivery, multiplayer or performance qualification."
|
||||
],
|
||||
"observed_results": {
|
||||
"baseline-test_infantry_resupply_planning": 1,
|
||||
"proposal-test_infantry_resupply_planning": 0,
|
||||
"proposal-test_infantry_resupply_coordinator": 0,
|
||||
"proposal-test_infantry_ammo_transfer": 0
|
||||
},
|
||||
"artifact_hashes": {
|
||||
"apply-check.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
"proposal-test_infantry_ammo_transfer.log": "27d49fc10aa8a5f150cdae91a192788fe84cb01b5998760ad6aba83d3c44d469",
|
||||
"proposal-test_infantry_resupply_coordinator.log": "956e431f178f472436c3abd25fcd34bfd6309ae1446335c9fbc23229428bc7cd",
|
||||
"proposal-test_infantry_resupply_planning.log": "c12aa5ba9b2141830d3916c3ab0285c06cbb44f606a9f8fbe42787ade0e67b21",
|
||||
"baseline-test_infantry_resupply_planning.log": "bf89459dc00b4db4c351933d382c400b1736f885a69443856fdd630175b742ff"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
from pathlib import Path
|
||||
import hashlib,json,subprocess
|
||||
R=Path('/home/jakub/devel/escapistsrereintroduced'); D=Path('/tmp/erri-ai-review-1509')
|
||||
files=['addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c','tests/test_infantry_resupply_planning.py','tests/test_infantry_resupply_coordinator.py','tests/test_infantry_ammo_transfer.py']
|
||||
baseline={}
|
||||
for f in files:
|
||||
b=(R/f).read_bytes(); p=D/'baseline'/f;p.parent.mkdir(parents=True,exist_ok=True);p.write_bytes(b)
|
||||
q=D/f;q.parent.mkdir(parents=True,exist_ok=True);q.write_bytes(b)
|
||||
index=subprocess.run(['git','show',':'+f],cwd=R,capture_output=True,check=True).stdout
|
||||
ip=D/'index'/f;ip.parent.mkdir(parents=True,exist_ok=True);ip.write_bytes(index)
|
||||
baseline[f]={'working_sha256':hashlib.sha256(b).hexdigest(),'index_sha256':hashlib.sha256(index).hexdigest()}
|
||||
(D/'baseline.json').write_text(json.dumps(baseline,indent=2)+'\n')
|
||||
p=D/files[0];s=p.read_text().replace('(m_State == 7 && m_LauncherTrip)','m_State == 7').replace('Finish("launcher custody settled; original claims released without retry or refund")','Finish("magazine custody settled; original claims released without retry or refund")').replace('(m_LauncherTrip && m_Move && m_Move.Unresolved())','(m_Move && m_Move.Unresolved())');p.write_text(s)
|
||||
p=D/files[1];s=p.read_text();start=s.index(' // A submitted unknown mine retains');end=s.index(' // Removed stock',start);block=s[start:end];block=block.replace('mine retains','rifle move retains').replace('first.s.m_MineMove=&leaf;first.s.m_MineTrip=true;','first.s.m_Move=&leaf;').replace('unknown native move','accepted native rifle move remains unresolved');s=s[:start]+block+s[start:];p.write_text(s)
|
||||
p=D/files[2];s=p.read_text();s=s.replace('f.s.m_Move==&leaf&&f.hq.token==0&&!f.truck.SupplyHeld&&f.s.m_Stopped','f.s.m_Move==&leaf&&f.hq.token==7&&f.truck.SupplyHeld&&f.s.m_State==7&&f.s.m_Stopped');s=s.replace('assert(f.s.audits==audits&&leaf.stops==1);','assert(f.s.audits==audits&&leaf.stops==1);leaf.unresolved=false;f.s.Tick(6000);assert(f.hq.token==0&&!f.truck.SupplyHeld&&f.s.m_State==1&&!f.s.m_Move);');p.write_text(s)
|
||||
p=D/files[3];s=p.read_text();at=s.index(' // Rifle moves must obey');extra=r'''
|
||||
// The shared force claim is necessary: independent rifle leaves can otherwise
|
||||
// submit the same still-carried empty to two different trucks. Native acceptance
|
||||
// is delayed here; this proves submission interference, not an engine outcome.
|
||||
{EmptyFixture first;Fixture second;ERR_GameMode::current=&first.mode;
|
||||
first.ledger.records.Insert(&second.donorRecord);second.source.selected=&second.sourceStorage;
|
||||
auto old=first.Job();assert(old.Tick(0)==PENDING&&old.Unresolved());
|
||||
assert(old.m_ReturnMagazine==&first.empty&&old.m_ReturnStorage==&first.sourceStorage);
|
||||
old.Stop();assert(old.Unresolved()&&old.Tick(180001)==FAILED);
|
||||
ERR_InfantryAmmoTransfer next(&first.mode,&second.truck,&second.donorGroup,&first.recipient,&first.recipientGroup,&second.magEntity,true);
|
||||
assert(next.Tick(180001)==PENDING&&next.Unresolved());
|
||||
assert(first.destination.calls==2&&next.m_ReturnMagazine==old.m_ReturnMagazine);
|
||||
assert(next.m_ReturnStorage==&second.sourceStorage&&next.m_ReturnStorage!=old.m_ReturnStorage);
|
||||
assert(first.destination.items.Contains(&first.empty)&&first.source.calls==0&&second.source.calls==0);
|
||||
// No duplicate object is invented: one physical completion can settle only its
|
||||
// original donor proof; the competing outstanding submission remains unknown.
|
||||
first.Return();old.m_ReturnCallback->OnComplete();assert(!old.Unresolved()&&next.Unresolved());
|
||||
assert(old.Tick(180002)==FAILED&&first.source.calls==0&&second.source.calls==0);}
|
||||
''';s=s[:at]+extra+s[at:];p.write_text(s)
|
||||
+1
@@ -0,0 +1 @@
|
||||
PASS: actual bounded empty-return and finite delivery; phase-isolated callbacks, exact ownership proof, stop quarantine and original actor/vehicle boundaries
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
infantry resupply actual rules, radio transitions, owned cleanup and unresolved-operation tests passed
|
||||
PASS: actual resupply Roster preserves permanent release, original slot mapping and bounded ownership
|
||||
+1
@@ -0,0 +1 @@
|
||||
PASS: actual Compatible and bounded stock preflight before report/claim consumption, later compatible truck, launcher controls, convoy binding, finite identities, disjoint tokens, shared report replay/cooldown, original recipients and HQ cleanup
|
||||
+592
@@ -0,0 +1,592 @@
|
||||
// HQ-owned ground rendezvous using delivered positions and existing finite cargo.
|
||||
class ERR_InfantryResupplyRules
|
||||
{
|
||||
static bool Fresh(ERR_HQWatchEntry entry, float now)
|
||||
{
|
||||
return entry && !entry.Closed && entry.Count > 0 && entry.Fit > 0
|
||||
&& ERR_ForceRules.Finite(now) && entry.ObservedAt >= 0 && now >= entry.ObservedAt
|
||||
&& now - entry.ObservedAt <= 120000 && ERR_ForceRules.FiniteVector(entry.Position);
|
||||
}
|
||||
static bool Need(ERR_HQWatchEntry entry, float now)
|
||||
{
|
||||
return Fresh(entry, now) && entry.AmmoState && entry.AmmoState.Valid(entry.Count)
|
||||
&& entry.AmmoState.Complete && entry.AmmoState.Members == entry.Count
|
||||
&& entry.AmmoState.SmallArmsMuzzles > 0
|
||||
&& entry.AmmoState.SmallArmsRounds + entry.AmmoState.SmallArmsChambers <= entry.Count * 30;
|
||||
}
|
||||
// Only positively sampled reloadable magazine-well muzzles establish launcher demand.
|
||||
static bool LauncherNeed(ERR_HQWatchEntry entry, float now)
|
||||
{
|
||||
return Fresh(entry, now) && entry.AmmoState && entry.AmmoState.Valid(entry.Count)
|
||||
&& entry.AmmoState.LauncherComplete && entry.AmmoState.Members == entry.Count
|
||||
&& entry.AmmoState.LauncherMuzzles > 0
|
||||
&& entry.AmmoState.LauncherRounds == 0 && entry.AmmoState.LauncherChambers == 0;
|
||||
}
|
||||
static bool LauncherPair(ERR_HQWatchEntry recipient, ERR_HQWatchEntry donor, float now)
|
||||
{
|
||||
return LauncherNeed(recipient, now) && Fresh(donor, now) && recipient.SourceId != donor.SourceId
|
||||
&& vector.DistanceXZ(recipient.Position, donor.Position) <= 200;
|
||||
}
|
||||
static bool MinePair(ERR_HQWatchEntry recipient, ERR_HQWatchEntry donor, float now)
|
||||
{
|
||||
return Fresh(recipient, now) && Fresh(donor, now) && recipient.SourceId != donor.SourceId
|
||||
&& recipient.AmmoState && recipient.AmmoState.Valid(recipient.Count)
|
||||
&& recipient.AmmoState.MineComplete && recipient.AmmoState.MineMembers == recipient.Count
|
||||
&& recipient.AmmoState.ReadyMines <= 1 && vector.DistanceXZ(recipient.Position, donor.Position) <= 200;
|
||||
}
|
||||
static bool Pair(ERR_HQWatchEntry recipient, ERR_HQWatchEntry donor, float now)
|
||||
{
|
||||
return Need(recipient, now) && Fresh(donor, now) && recipient.SourceId != donor.SourceId
|
||||
&& vector.DistanceXZ(recipient.Position, donor.Position) <= 200;
|
||||
}
|
||||
}
|
||||
|
||||
class ERR_InfantryResupply
|
||||
{
|
||||
protected ERR_HQ m_HQ;
|
||||
protected ERR_GameMode m_Mode;
|
||||
protected ERR_ConvoyTask m_Convoy;
|
||||
protected int m_ConvoySlot = -1;
|
||||
protected ERR_ConvoyVehicle m_Truck;
|
||||
protected ERR_HQUnit m_Recipient;
|
||||
protected ERR_HQUnit m_Donor;
|
||||
protected ref array<IEntity> m_Stock = {};
|
||||
protected ref array<IEntity> m_Spent = {};
|
||||
protected ref array<IEntity> m_MineStock = {};
|
||||
protected ref ERR_ConvoyMineStock m_MineBatch;
|
||||
protected bool m_MineStockCaptured;
|
||||
protected bool m_MineTrip;
|
||||
protected bool m_LauncherTrip;
|
||||
protected int m_MineRecipientSlot = -1;
|
||||
protected bool m_EmptyMineReplacement;
|
||||
protected int m_MinesDelivered;
|
||||
protected ref array<IEntity> m_Members = {};
|
||||
protected ref array<IEntity> m_Served = {};
|
||||
protected ref map<string, int> m_Consumed = new map<string, int>();
|
||||
protected ref map<string, float> m_NextAttempt = new map<string, float>();
|
||||
protected ref ERR_HQRoute m_Order;
|
||||
protected ref ERR_InfantryAmmoTransfer m_Move;
|
||||
protected ref ERR_InfantryMineTransfer m_MineMove;
|
||||
protected ref ERR_MountedResupply m_Mounted;
|
||||
protected IEntity m_Receiving;
|
||||
protected AIWaypoint m_MoveWaypoint;
|
||||
protected AIWaypoint m_HoldWaypoint;
|
||||
protected vector m_Rendezvous;
|
||||
protected int m_State; // 0 stock startup, 1 idle, 2 truck downlink, 3 stopped status, 4 infantry downlink, 5 transfer, 7 unresolved item custody
|
||||
protected int m_Trip;
|
||||
protected int m_Token;
|
||||
protected int m_ReportId;
|
||||
protected int m_Delivered;
|
||||
protected int m_TripDelivered;
|
||||
protected float m_Deadline;
|
||||
protected float m_StockDeadline = -1;
|
||||
protected float m_HeldAt;
|
||||
protected float m_NextTick;
|
||||
protected bool m_Stopped;
|
||||
protected string m_Reason;
|
||||
void ERR_InfantryResupply(ERR_HQ hq, ERR_GameMode mode) { m_HQ = hq; m_Mode = mode; }
|
||||
// Bind before startup; every coordinator retains its exact finite convoy identity.
|
||||
bool Bind(ERR_ConvoyTask task, int slot, map<string, int> consumed, map<string, float> nextAttempt)
|
||||
{
|
||||
if (!task || !consumed || !nextAttempt || !m_HQ || !m_HQ.Convoys() || slot < 0 || slot >= 20
|
||||
|| slot >= m_HQ.Convoys().Count() || m_HQ.Convoys().At(slot) != task) return false;
|
||||
if (m_Stopped || m_Convoy || m_ConvoySlot >= 0 || m_State != 0 || m_Trip != 0 || m_NextTick != 0
|
||||
|| m_StockDeadline >= 0 || !m_Stock.IsEmpty() || m_Move || m_Truck) return false;
|
||||
m_Convoy = task; m_ConvoySlot = slot; m_Consumed = consumed; m_NextAttempt = nextAttempt;
|
||||
return true;
|
||||
}
|
||||
ERR_ConvoyTask Task() { return m_Convoy; }
|
||||
int State()
|
||||
{
|
||||
if (m_Mounted && m_Mounted.Busy()) return 6;
|
||||
return m_State;
|
||||
}
|
||||
ERR_MountedResupply Mounted() { return m_Mounted; }
|
||||
bool Unresolved() { return (m_Move && m_Move.Unresolved()) || (m_MineMove && m_MineMove.Unresolved()) || (m_Mounted && m_Mounted.Unresolved()); }
|
||||
protected void PollTransfers(float now)
|
||||
{
|
||||
if (m_Mounted) m_Mounted.Tick(now);
|
||||
if (m_Move && !m_Move.Unresolved() && (m_State <= 1 || m_State == 7))
|
||||
{
|
||||
m_Move = null;
|
||||
if (m_State == 7) Finish("magazine custody settled; original claims released without retry or refund");
|
||||
}
|
||||
if (m_MineMove && !m_MineMove.Unresolved() && (m_State <= 1 || m_State == 7))
|
||||
{
|
||||
m_MineMove = null;
|
||||
if (m_State == 7) Finish("mine custody settled; original claims released without retry or refund");
|
||||
}
|
||||
}
|
||||
int Delivered() { return m_Delivered; }
|
||||
int MinesDelivered() { return m_MinesDelivered; }
|
||||
int StockCount() { return m_Stock.Count(); }
|
||||
// Admission uses the existing array object so an already-created mounted
|
||||
// coordinator observes this exact finite addition without a replacement ledger.
|
||||
protected int m_DepotImports;
|
||||
protected int m_DepotMineImports;
|
||||
bool DepotCurrent()
|
||||
{
|
||||
return Current() && m_State == 1 && !m_Move && !m_MineMove && !Unresolved()
|
||||
&& (!m_Mounted || !m_Mounted.Busy()) && TruckValid(true);
|
||||
}
|
||||
bool DepotAvailable() { return DepotCurrent() && m_Stock.Count() < 96 && m_Spent.Count() < 96; }
|
||||
bool DepotNeeded()
|
||||
{
|
||||
if (!DepotAvailable()) return false;
|
||||
int committed;
|
||||
foreach (IEntity item : m_Spent)
|
||||
if (item && m_Stock.Contains(item)) committed++;
|
||||
return committed > m_DepotImports;
|
||||
}
|
||||
// Mine imports replace only proved outgoing original mine commitments.
|
||||
// Keep the startup batch binding and both lifetime identity/spent ceilings.
|
||||
bool DepotMineAvailable()
|
||||
{
|
||||
return DepotCurrent() && CaptureMines() && m_MineStock.Count() < 96 && m_Spent.Count() < 96;
|
||||
}
|
||||
bool DepotMineNeeded()
|
||||
{
|
||||
if (!DepotMineAvailable()) return false;
|
||||
int committed;
|
||||
foreach (IEntity item : m_Spent)
|
||||
if (item && m_MineStock.Contains(item)) committed++;
|
||||
return committed > m_DepotMineImports;
|
||||
}
|
||||
bool AdmitDepotMine(ERR_GroundDepotLoading job, IEntity item)
|
||||
{
|
||||
if (!job || !DepotMineNeeded() || !ERR_InfantryMineTransfer.ReadyMine(item)
|
||||
|| m_MineStock.Contains(item) || m_Stock.Contains(item) || m_Spent.Contains(item)) return false;
|
||||
if (!job.DeliveredTo(this, item, true) || !Contains(m_Truck.Entity, item)
|
||||
|| !ERR_InfantryAmmoTransfer.StoredUnder(item, m_Truck.Entity)) return false;
|
||||
InventoryItemComponent carried = InventoryItemComponent.Cast(item.FindComponent(InventoryItemComponent));
|
||||
if (!carried || !carried.GetParentSlot() || carried.GetParentSlot().GetAttachedEntity() != item) return false;
|
||||
m_MineStock.Insert(item); m_DepotMineImports++;
|
||||
Audit("one exact finite camp PMN4 admitted after proved physical courier delivery");
|
||||
return true;
|
||||
}
|
||||
ERR_ConvoyVehicle DepotTruck()
|
||||
{
|
||||
if (!DepotCurrent()) return null;
|
||||
return m_Truck;
|
||||
}
|
||||
bool AdmitDepot(ERR_GroundDepotLoading job, IEntity item)
|
||||
{
|
||||
if (!job || !DepotAvailable() || !item || m_Stock.Contains(item) || m_Spent.Contains(item)) return false;
|
||||
if (!job.DeliveredTo(this, item) || !Contains(m_Truck.Entity, item)) return false;
|
||||
m_Stock.Insert(item); m_DepotImports++; Audit("one exact finite camp magazine admitted after proved physical courier delivery");
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void Audit(string reason)
|
||||
{
|
||||
if (m_MineTrip) reason = "mine top-up: " + reason;
|
||||
if (m_LauncherTrip) reason = "depleted launcher magazine: " + reason;
|
||||
m_Reason = reason;
|
||||
m_HQ.Journal().Write("INFANTRY SUPPLY", string.Format("convoy-slot=%1 trip=%2 state=%3 moved=%4 spent=%5/%6; %7", m_ConvoySlot, m_Trip, m_State, m_Delivered, m_Spent.Count(), m_Stock.Count(), reason), m_ReportId);
|
||||
}
|
||||
protected bool Current()
|
||||
{
|
||||
return !m_Stopped && Replication.IsServer() && m_Mode && m_Mode == ERR_GameMode.Get() && m_Mode.Active();
|
||||
}
|
||||
protected bool Contains(IEntity owner, IEntity item)
|
||||
{
|
||||
if (!owner || !item) return false;
|
||||
InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(owner.FindComponent(InventoryStorageManagerComponent));
|
||||
if (!inventory) return false;
|
||||
array<IEntity> items = {}; ERR_Inventory.Items(inventory, items);
|
||||
return items.Count() <= 128 && items.Contains(item);
|
||||
}
|
||||
protected bool ConvoyCurrent()
|
||||
{
|
||||
if (!m_HQ || !m_Convoy) return false;
|
||||
if (m_ConvoySlot < 0) return m_HQ.ConvoyTask() == m_Convoy;
|
||||
return m_HQ.Convoys() && m_ConvoySlot < m_HQ.Convoys().Count() && m_HQ.Convoys().At(m_ConvoySlot) == m_Convoy;
|
||||
}
|
||||
protected bool TruckValid(bool allowArrived = false)
|
||||
{
|
||||
if (!m_Convoy || m_Convoy.Stopped || !m_Convoy.Ready || !m_Convoy.Receipt || !m_Convoy.Receipt.Consumed
|
||||
|| !ConvoyCurrent() || m_Convoy.Vehicles.Count() != 6 || m_Convoy.Vehicles[1] != m_Truck) return false;
|
||||
if (!m_Truck || m_Truck.Index != 1 || !m_Truck.Registered || m_Truck.Released || (m_Truck.Arrived && !allowArrived)
|
||||
|| !m_Truck.CrewValid(m_Mode) || ERR_ConvoyRules.Captured(m_Truck.Entity, m_Truck.Group)) return false;
|
||||
ERR_ForceRecord record = m_Mode.Forces().FindGroup(m_Truck.Group);
|
||||
return record && record.Physical && !record.Eliminated && record.Kind == ERR_ForceKind.CONVOY
|
||||
&& m_Convoy.Receipt.Records.Count() >= 6 && record.Id == m_Convoy.Receipt.Records[1];
|
||||
}
|
||||
protected bool Quiet(ERR_HQUnit unit)
|
||||
{
|
||||
return unit && unit.Group && unit.Utility && !unit.Group.IsSlave() && unit.Group.GetPlayerCount(true) == 0
|
||||
&& unit.Group.GetFaction() == m_Mode.EnemyFaction()
|
||||
&& (!unit.Utility.m_Perception || unit.Utility.m_Perception.m_aTargets.IsEmpty());
|
||||
}
|
||||
protected bool Roster()
|
||||
{
|
||||
if (!m_Recipient || !Quiet(m_Recipient) || !m_Recipient.StatusSampler.OwnsRoster(m_Recipient.Group)) return false;
|
||||
int strength = m_Recipient.StatusSampler.InitialStrength();
|
||||
if (strength < 1 || strength > 32) return false;
|
||||
array<AIAgent> agents = {}; m_Recipient.Group.GetAgents(agents);
|
||||
if (agents.IsEmpty() || agents.Count() > 32) return false;
|
||||
foreach (AIAgent agent : agents)
|
||||
if (!agent || !m_Members.Contains(agent.GetControlledEntity())) return false;
|
||||
bool living;
|
||||
foreach (IEntity actor : m_Members)
|
||||
{
|
||||
if (!actor || !ERR_Actors.Alive(actor)) continue;
|
||||
// Returning to the group cannot undo a sampler's permanent release of an
|
||||
// original slot after transfer or player control during this trip.
|
||||
bool attributed = false;
|
||||
for (int slot = 0; slot < strength; slot++)
|
||||
{
|
||||
if (m_Recipient.StatusSampler.InitialMember(slot) != actor) continue;
|
||||
attributed = m_Recipient.StatusSampler.CanAttribute(slot, actor);
|
||||
break;
|
||||
}
|
||||
if (!attributed) return false;
|
||||
if (ERR_Actors.Player(actor) || ERR_Actors.Group(actor) != m_Recipient.Group
|
||||
|| SCR_FactionManager.SGetFaction(actor) != m_Mode.EnemyFaction() || CompartmentAccessComponent.GetVehicleIn(actor)) return false;
|
||||
if (ERR_Actors.CanFight(actor)) living = true;
|
||||
}
|
||||
return living;
|
||||
}
|
||||
protected void Stock(float now)
|
||||
{
|
||||
if (!m_Convoy) m_Convoy = m_HQ.ConvoyTask();
|
||||
if (m_Convoy && !ConvoyCurrent()) { Stop(); return; }
|
||||
if (!m_Convoy || !m_Convoy.Ready || m_Convoy.Vehicles.Count() != 6) return;
|
||||
m_Truck = m_Convoy.Vehicles[1];
|
||||
if (!TruckValid()) { Stop(); return; }
|
||||
// Cargo has a later, separately bounded lifecycle than native crew admission.
|
||||
// Supply convoys first request faction weapons, then their matching magazines.
|
||||
if (m_StockDeadline < 0) m_StockDeadline = now + 90000;
|
||||
if (now >= m_StockDeadline) { Stop(); return; }
|
||||
if (!m_Convoy.CargoIssued) return;
|
||||
ERR_SupplyConvoyTask supply = ERR_SupplyConvoyTask.Cast(m_Convoy);
|
||||
if (supply && !supply.MagazinesIssued) return;
|
||||
if (supply) m_MineBatch = supply.MineStock;
|
||||
foreach (ERR_ConvoyCargoCallback operation : m_Convoy.Cargo)
|
||||
if (!operation.Finished) return;
|
||||
InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(m_Truck.Entity.FindComponent(InventoryStorageManagerComponent));
|
||||
if (!inventory) { Stop(); return; }
|
||||
array<IEntity> items = {}; ERR_Inventory.Items(inventory, items);
|
||||
if (items.Count() > 128) { Stop(); return; }
|
||||
foreach (IEntity item : items)
|
||||
{
|
||||
if (!item || !item.FindComponent(BaseMagazineComponent)) continue;
|
||||
if (m_Stock.Count() >= 96) { Stop(); return; }
|
||||
m_Stock.Insert(item);
|
||||
}
|
||||
m_State = 1; Audit("truck magazine identities captured once after startup; absent/looted stock is never replaced");
|
||||
}
|
||||
bool TryPlan(ERR_HQUnit recipient, ERR_HQUnit donor, ERR_HQWatchEntry demand, ERR_HQWatchEntry donorStatus, float now, bool mineTrip = false, bool launcherTrip = false)
|
||||
{
|
||||
if (!Current() || m_State != 1 || m_Move || m_MineMove || (m_Mounted && m_Mounted.Busy()) || m_Trip >= 128 || !TruckValid()) return false;
|
||||
if ((mineTrip && launcherTrip) || m_Truck.Combat.Held || m_Truck.SupplyToken > 0 || !recipient || !donor) return false;
|
||||
if (donor.Group != m_Truck.Group || recipient.HomeGuard || !Quiet(recipient) || !Quiet(donor)) return false;
|
||||
if (donor.Downlink || donor.PendingOrder || donor.PendingConvoyOrder) return false;
|
||||
if (mineTrip)
|
||||
{
|
||||
if (!ERR_InfantryResupplyRules.MinePair(demand, donorStatus, now)) return false;
|
||||
// Empty reports authorize only an original startup-designated engineer.
|
||||
// This reads retained entitlement, never live positions/inventory for planning.
|
||||
if (demand.AmmoState.ReadyMines == 0)
|
||||
{
|
||||
bool designated;
|
||||
for (int member = 0; member < recipient.StatusSampler.InitialStrength() && member < 32; member++)
|
||||
{
|
||||
IEntity original = recipient.StatusSampler.InitialMember(member);
|
||||
if (original && recipient.StatusSampler.CanAttribute(member, original)
|
||||
&& m_HQ.MineSupplyReady(recipient.Group, original, true)) { designated = true; break; }
|
||||
}
|
||||
if (!designated) return false;
|
||||
}
|
||||
}
|
||||
else if (launcherTrip)
|
||||
{
|
||||
if (!ERR_InfantryResupplyRules.LauncherPair(demand, donorStatus, now)) return false;
|
||||
}
|
||||
else if (!ERR_InfantryResupplyRules.Pair(demand, donorStatus, now)) return false;
|
||||
if (demand.SourceId != recipient.ForceSourceId || donorStatus.SourceId != donor.ForceSourceId) return false;
|
||||
if (demand.MessageId <= m_Consumed.Get(demand.SourceId) || now < m_NextAttempt.Get(demand.SourceId)) return false;
|
||||
bool available;
|
||||
if (mineTrip)
|
||||
{
|
||||
if (!CaptureMines()) return false;
|
||||
foreach (IEntity mine : m_MineStock)
|
||||
if (ERR_InfantryMineTransfer.ReadyMine(mine) && !m_Spent.Contains(mine) && Contains(m_Truck.Entity, mine)) { available = true; break; }
|
||||
}
|
||||
else if (launcherTrip) available = LauncherStock(recipient);
|
||||
else available = CompatibleStock(recipient, false);
|
||||
if (m_Spent.Count() >= 96) return false;
|
||||
if (!available) return false;
|
||||
m_Members.Clear();
|
||||
for (int i = 0; i < recipient.StatusSampler.InitialStrength(); i++)
|
||||
{
|
||||
IEntity actor = recipient.StatusSampler.InitialMember(i);
|
||||
if (actor && recipient.StatusSampler.CanAttribute(i, actor)) m_Members.Insert(actor);
|
||||
}
|
||||
m_Recipient = recipient; m_Donor = donor;
|
||||
if (!Roster()) { m_Recipient = null; m_Donor = null; return false; }
|
||||
// Disjoint bounded token range from the existing mortar courier's trip IDs.
|
||||
int slot = m_ConvoySlot;
|
||||
if (slot < 0) slot = 0; // Isolated legacy fixture uses the first convoy's range.
|
||||
int token = 100000 + slot * 128 + m_Trip + 1;
|
||||
if (!m_HQ.ReserveLogistics(recipient.Group, token)) { m_Recipient = null; m_Donor = null; return false; }
|
||||
m_MineTrip = mineTrip; m_LauncherTrip = launcherTrip; m_MineRecipientSlot = -1; m_Receiving = null; m_EmptyMineReplacement = false;
|
||||
m_Trip++; m_Token = token; m_Truck.SupplyToken = token; m_ReportId = demand.MessageId; m_TripDelivered = 0; m_Served.Clear();
|
||||
m_Consumed.Set(demand.SourceId, demand.MessageId); m_NextAttempt.Set(demand.SourceId, now + 180000);
|
||||
m_Deadline = Math.Min(now + 120000, demand.ObservedAt + 180000); m_State = 2;
|
||||
string purpose = "stop existing ammo truck and report position";
|
||||
if (mineTrip) purpose += "; one finite PMN4 top-up for an existing carrier";
|
||||
if (launcherTrip) purpose += "; finite compatible magazine for a reported depleted launcher";
|
||||
m_Order = m_HQ.Downlink(donor.Group, "INFANTRY SUPPLY HOLD", purpose, m_ReportId);
|
||||
if (!m_Order) Finish("truck radio downlink unavailable");
|
||||
else Audit("existing patrol reserved; truck hold awaits radio delivery");
|
||||
return true;
|
||||
}
|
||||
// Optional mine startup must never delay normal magazine readiness. Pin the
|
||||
// original batch during Stock(), then copy its closed exact identities once.
|
||||
protected bool CaptureMines()
|
||||
{
|
||||
ERR_SupplyConvoyTask supply = ERR_SupplyConvoyTask.Cast(m_Convoy);
|
||||
if (!supply || !m_MineBatch || supply.MineStock != m_MineBatch || !m_MineBatch.Complete()) return false;
|
||||
if (m_MineStockCaptured) return !m_MineStock.IsEmpty();
|
||||
m_MineStockCaptured = true;
|
||||
int count = m_MineBatch.Count();
|
||||
if (count < 0 || count > 2) return false;
|
||||
for (int index = 0; index < count; index++)
|
||||
{
|
||||
IEntity item = m_MineBatch.At(index);
|
||||
if (item && !m_MineStock.Contains(item)) m_MineStock.Insert(item);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// Compatibility-only preflight of original own carriers; HQ still uses the
|
||||
// delivered report for demand and positions. No item is reserved or moved here.
|
||||
protected bool CompatibleStock(ERR_HQUnit recipient, bool launcherMagazine)
|
||||
{
|
||||
if (!recipient || !recipient.StatusSampler || m_Stock.Count() > 96) return false;
|
||||
int strength = recipient.StatusSampler.InitialStrength();
|
||||
if (strength < 1 || strength > 32) return false;
|
||||
int checks;
|
||||
foreach (IEntity magazine : m_Stock)
|
||||
{
|
||||
if (!magazine || m_Spent.Contains(magazine) || !Contains(m_Truck.Entity, magazine)) continue;
|
||||
for (int slot = 0; slot < strength; slot++)
|
||||
{
|
||||
if (++checks > 96 * 32) return false;
|
||||
IEntity actor = recipient.StatusSampler.InitialMember(slot);
|
||||
if (!actor || !recipient.StatusSampler.CanAttribute(slot, actor) || !ERR_Actors.CanFight(actor)) continue;
|
||||
if (ERR_InfantryAmmoTransfer.Compatible(actor, magazine, launcherMagazine)) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
protected bool LauncherStock(ERR_HQUnit recipient)
|
||||
{
|
||||
return CompatibleStock(recipient, true);
|
||||
}
|
||||
bool TryPlanLauncher(ERR_HQUnit recipient, ERR_HQUnit donor, ERR_HQWatchEntry demand, ERR_HQWatchEntry donorStatus, float now)
|
||||
{
|
||||
return TryPlan(recipient, donor, demand, donorStatus, now, false, true);
|
||||
}
|
||||
bool TryPlanMines(ERR_HQUnit recipient, ERR_HQUnit donor, ERR_HQWatchEntry demand, ERR_HQWatchEntry donorStatus, float now)
|
||||
{
|
||||
return TryPlan(recipient, donor, demand, donorStatus, now, true);
|
||||
}
|
||||
// Share exact frozen inventory identities and global radio replay state.
|
||||
bool TryPlanMounted(ERR_HQUnit recipient, ERR_HQUnit donor, ERR_HQWatchEntry demand, ERR_HQWatchEntry donorStatus, float now)
|
||||
{
|
||||
if (!Current() || m_State != 1 || m_Move || m_MineMove || m_ConvoySlot < 0 || !TruckValid(true)) return false;
|
||||
if (m_Mounted && m_Mounted.Busy()) return false;
|
||||
if (!m_Mounted) m_Mounted = new ERR_MountedResupply(m_HQ, m_Mode, m_Convoy, m_ConvoySlot, m_Stock, m_Spent, m_Consumed, m_NextAttempt);
|
||||
return m_Mounted.Begin(recipient, donor, demand, donorStatus, now);
|
||||
}
|
||||
protected bool Waypoints()
|
||||
{
|
||||
m_MoveWaypoint = AIWaypoint.Cast(ERR_Actors.Spawn(ERR_Resources.MoveWaypoint(), ERR_Actors.Ground(m_Rendezvous)));
|
||||
m_HoldWaypoint = AIWaypoint.Cast(ERR_Actors.Spawn(ERR_Resources.DefendWaypoint(), ERR_Actors.Ground(m_Rendezvous)));
|
||||
if (!m_MoveWaypoint || !m_HoldWaypoint) return false;
|
||||
// The reported rendezvous is 3 m from the donor report. A 2 m move
|
||||
// radius allowed arrival 5 m away, beyond the transfer's physical reach.
|
||||
m_MoveWaypoint.SetCompletionRadius(0.5); m_HoldWaypoint.SetCompletionRadius(0.5);
|
||||
m_Recipient.Group.AddWaypointAt(m_HoldWaypoint, 0); m_Recipient.Group.AddWaypointAt(m_MoveWaypoint, 0);
|
||||
m_Recipient.Group.ActivateAI(); return true;
|
||||
}
|
||||
protected void ClearWaypoints()
|
||||
{
|
||||
if (m_MoveWaypoint) { if (m_Recipient && m_Recipient.Group) m_Recipient.Group.RemoveWaypoint(m_MoveWaypoint); ERR_Actors.DeleteSpawned(m_MoveWaypoint); }
|
||||
if (m_HoldWaypoint) { if (m_Recipient && m_Recipient.Group) m_Recipient.Group.RemoveWaypoint(m_HoldWaypoint); ERR_Actors.DeleteSpawned(m_HoldWaypoint); }
|
||||
m_MoveWaypoint = null; m_HoldWaypoint = null;
|
||||
}
|
||||
protected void Finish(string reason)
|
||||
{
|
||||
Audit(reason);
|
||||
if (m_Move) m_Move.Stop();
|
||||
if (m_MineMove) m_MineMove.Stop();
|
||||
ClearWaypoints();
|
||||
m_Order = null;
|
||||
// A late native move must not race another truck's newer report. Retain both
|
||||
// exact claims until the existing transfer leaf reports that its operation has settled.
|
||||
if ((m_MineMove && m_MineMove.Unresolved()) || (m_Move && m_Move.Unresolved())) { m_State = 7; return; }
|
||||
if (m_Recipient) m_HQ.ReleaseLogistics(m_Recipient.Group, m_Token);
|
||||
if (m_Truck && m_Truck.SupplyToken == m_Token) { m_Truck.SupplyToken = 0; m_Truck.SupplyHeld = false; }
|
||||
m_Recipient = null; m_Donor = null; m_Order = null; m_Receiving = null; m_State = 1; m_MineTrip = false; m_LauncherTrip = false; m_MineRecipientSlot = -1;
|
||||
}
|
||||
protected void TransferMine(float now)
|
||||
{
|
||||
if (m_MineMove)
|
||||
{
|
||||
int result = m_MineMove.Tick(now);
|
||||
if (result == 0) return;
|
||||
if (result < 0) { Finish("native mine transfer failed or expired; exact submitted identity stays spent"); return; }
|
||||
m_MineMove = null; m_MinesDelivered++;
|
||||
Finish("one exact finite PMN4 confirmed in the original carrier inventory"); return;
|
||||
}
|
||||
if (!m_Receiving)
|
||||
{
|
||||
int strength = m_Recipient.StatusSampler.InitialStrength();
|
||||
for (int slot = 0; slot < strength && slot < 32; slot++)
|
||||
{
|
||||
IEntity actor = m_Recipient.StatusSampler.InitialMember(slot);
|
||||
if (!actor || !m_Members.Contains(actor) || !m_Recipient.StatusSampler.CanAttribute(slot, actor, false)) continue;
|
||||
if (!ERR_Actors.CanFight(actor) || vector.DistanceXZ(actor.GetOrigin(), m_Truck.Entity.GetOrigin()) > 4) continue;
|
||||
if (!m_HQ.MineSupplyReady(m_Recipient.Group, actor)) continue;
|
||||
IEntity carried;
|
||||
int count = ERR_InfantryMineTransfer.CarriedCount(actor, m_Recipient.Group, carried);
|
||||
if (count != 1 && (count != 0 || !m_HQ.MineSupplyReady(m_Recipient.Group, actor, true))) continue;
|
||||
m_EmptyMineReplacement = count == 0;
|
||||
m_Receiving = actor; m_MineRecipientSlot = slot; break;
|
||||
}
|
||||
if (!m_Receiving) return;
|
||||
}
|
||||
if (!m_HQ.MineSupplyReady(m_Recipient.Group, m_Receiving, m_EmptyMineReplacement)) return;
|
||||
IEntity carried;
|
||||
int count = ERR_InfantryMineTransfer.CarriedCount(m_Receiving, m_Recipient.Group, carried);
|
||||
if (!m_Recipient.StatusSampler.CanAttribute(m_MineRecipientSlot, m_Receiving, false)
|
||||
|| (m_EmptyMineReplacement && count != 0) || (!m_EmptyMineReplacement && count != 1))
|
||||
{ Finish("original mine recipient lost or its pinned zero/one stock changed"); return; }
|
||||
foreach (IEntity mine : m_MineStock)
|
||||
{
|
||||
if (!ERR_InfantryMineTransfer.ReadyMine(mine) || m_Spent.Contains(mine) || !Contains(m_Truck.Entity, mine)) continue;
|
||||
ERR_FiniteMagazineReservation reservation = new ERR_FiniteMagazineReservation(m_MineStock, m_Spent, mine);
|
||||
if (!reservation.Reserve()) continue;
|
||||
m_MineMove = new ERR_InfantryMineTransfer(m_Mode, m_Truck.Entity, m_Truck.Group, m_Receiving, m_Recipient.Group,
|
||||
mine, reservation, m_Recipient.StatusSampler, m_MineRecipientSlot, m_EmptyMineReplacement);
|
||||
m_MineMove.Tick(now);
|
||||
// The leaf commits before the one native move. Only an unsubmitted refusal
|
||||
// may release its tentative claim while the same carrier approaches/retries.
|
||||
if (m_MineMove.Submitted()) return;
|
||||
reservation.ReleaseUnsubmitted(); m_MineMove = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
protected void Transfer(float now)
|
||||
{
|
||||
if (m_Move)
|
||||
{
|
||||
int result = m_Move.Tick(now);
|
||||
if (result == 0) return;
|
||||
if (result < 0) { Finish("native transfer rejected, expired or lost authority; no item retry"); return; }
|
||||
m_Move = null; m_Delivered++; m_TripDelivered++; m_Served.Insert(m_Receiving); m_Receiving = null;
|
||||
Audit("exact finite magazine confirmed in original soldier inventory");
|
||||
if (m_TripDelivered >= 6) { Finish("six-magazine trip allowance reached"); return; }
|
||||
}
|
||||
foreach (IEntity actor : m_Members)
|
||||
{
|
||||
if (!ERR_Actors.CanFight(actor) || m_Served.Contains(actor) || vector.DistanceXZ(actor.GetOrigin(), m_Truck.Entity.GetOrigin()) > 4) continue;
|
||||
ERR_HQAmmoSnapshot local = new ERR_HQAmmoSnapshot(); local.Complete = true; local.LauncherComplete = true;
|
||||
ERR_HQAmmoSampler.Inspect(actor, m_Recipient.Group, local);
|
||||
if (m_LauncherTrip)
|
||||
{
|
||||
if (!local.Valid(1) || !local.LauncherComplete || local.Members != 1 || local.LauncherMuzzles <= 0
|
||||
|| local.LauncherRounds != 0 || local.LauncherChambers != 0) continue;
|
||||
}
|
||||
else if (!local.Complete || local.SmallArmsMuzzles <= 0 || local.SmallArmsRounds + local.SmallArmsChambers > 30) continue;
|
||||
foreach (IEntity magazine : m_Stock)
|
||||
{
|
||||
if (!magazine || m_Spent.Contains(magazine) || !Contains(m_Truck.Entity, magazine) || !ERR_InfantryAmmoTransfer.Compatible(actor, magazine, m_LauncherTrip)) continue;
|
||||
ERR_FiniteMagazineReservation reservation = new ERR_FiniteMagazineReservation(m_Stock, m_Spent, magazine);
|
||||
if (!reservation.Reserve()) continue;
|
||||
m_Receiving = actor;
|
||||
m_Move = new ERR_InfantryAmmoTransfer(m_Mode, m_Truck.Entity, m_Truck.Group, actor, m_Recipient.Group, magazine, !m_LauncherTrip, m_LauncherTrip);
|
||||
m_Move.Tick(now);
|
||||
if (m_Move.Submitted()) { reservation.Commit(); return; }
|
||||
// No native operation exists yet: approach geometry, stopped state or
|
||||
// capacity may improve while the same bounded rendezvous remains valid.
|
||||
// Keep every submitted identity spent, including a synchronous rejection.
|
||||
reservation.ReleaseUnsubmitted(); m_Move = null; m_Receiving = null;
|
||||
break; // At most one unsubmitted preflight per member on this slow tick.
|
||||
}
|
||||
}
|
||||
}
|
||||
void Tick(float now)
|
||||
{
|
||||
if (!ERR_ForceRules.Finite(now) || now < 0) return;
|
||||
// Stopped services retain uncertain leaf refs until exact late proof settles.
|
||||
if (m_Stopped) { PollTransfers(now); return; }
|
||||
if (!Current() || now < m_NextTick) return;
|
||||
m_NextTick = now + 1000;
|
||||
PollTransfers(now);
|
||||
if (m_Mounted && m_Mounted.Busy()) return;
|
||||
if (m_State == 7) return;
|
||||
if (m_State == 0) { Stock(now); return; }
|
||||
if (m_State == 1)
|
||||
{
|
||||
if (m_Move && !m_Move.Unresolved()) m_Move = null;
|
||||
return;
|
||||
}
|
||||
if (now >= m_Deadline || !TruckValid() || !Quiet(m_Donor) || !Roster() || m_Truck.Combat.Held
|
||||
|| m_HQ.LogisticsToken(m_Recipient.Group) != m_Token)
|
||||
{ Finish("rendezvous expired, contact appeared or original ownership changed"); return; }
|
||||
if (m_Truck.SupplyToken != m_Token) { Finish("truck hold authority lost"); return; }
|
||||
if (m_State == 2)
|
||||
{
|
||||
int delivered = m_Order.Advance(now, m_HQ.Journal());
|
||||
if (delivered == 0) return;
|
||||
if (delivered < 0 || m_Truck.SupplyToken != m_Token) { Finish("truck hold downlink interrupted or reservation lost"); return; }
|
||||
m_Truck.SupplyHeld = true; m_Truck.ClearOrder(); m_HeldAt = -1;
|
||||
m_Order = null; m_State = 3; Audit("truck received stop; waiting for delivered stopped-position report"); return;
|
||||
}
|
||||
if (m_State == 3)
|
||||
{
|
||||
// The delivered hold asks the original crew to report only after physically stopping.
|
||||
if (m_HeldAt < 0)
|
||||
{
|
||||
Physics physics = m_Truck.Entity.GetPhysics();
|
||||
if (!physics) return;
|
||||
float speed = physics.GetVelocity().Length();
|
||||
float angular = physics.GetAngularVelocity().Length();
|
||||
if (!(speed >= 0 && speed <= 0.25 && angular >= 0 && angular <= 0.1)) return;
|
||||
m_HeldAt = now; m_Donor.NextStatus = now; return;
|
||||
}
|
||||
ERR_HQWatchEntry stopped = m_HQ.Watch().Find(m_Donor.ForceSourceId);
|
||||
if (!ERR_InfantryResupplyRules.Fresh(stopped, now) || stopped.ObservedAt < m_HeldAt) return;
|
||||
m_Rendezvous = stopped.Position + "3 0 0";
|
||||
m_Order = m_HQ.Downlink(m_Recipient.Group, "INFANTRY SUPPLY RENDEZVOUS", string.Format("walk to reported stopped ammo truck at %1", m_Rendezvous), m_ReportId);
|
||||
if (!m_Order) { Finish("infantry radio downlink unavailable"); return; }
|
||||
m_State = 4; return;
|
||||
}
|
||||
if (m_State == 4)
|
||||
{
|
||||
int delivered = m_Order.Advance(now, m_HQ.Journal());
|
||||
if (delivered == 0) return;
|
||||
if (delivered < 0 || !Waypoints()) { Finish("infantry order interrupted or native waypoint creation failed"); return; }
|
||||
m_Order = null; m_State = 5; Audit("infantry received reported rendezvous; native movement and physical transfer required");
|
||||
}
|
||||
if (m_State == 5)
|
||||
{
|
||||
if (m_MineTrip) TransferMine(now);
|
||||
else Transfer(now);
|
||||
}
|
||||
}
|
||||
string Status()
|
||||
{
|
||||
string detail = string.Format("Ground supply: state=%1 trips=%2 infantry moved=%3 stock=%4 spent=%5", State(), m_Trip, m_Delivered, m_Stock.Count(), m_Spent.Count());
|
||||
return detail + string.Format("; mines moved=%1 allowance=%2; %3", m_MinesDelivered, m_MineStock.Count(), m_Reason);
|
||||
}
|
||||
void Stop()
|
||||
{
|
||||
if (m_Stopped) return;
|
||||
if (m_Mounted) m_Mounted.Stop();
|
||||
Finish("service stopped; original forces and all remaining cargo retained"); m_Stopped = true;
|
||||
}
|
||||
}
|
||||
+371
@@ -0,0 +1,371 @@
|
||||
"""Execute the actual finite native magazine transaction; engine behavior remains separate."""
|
||||
from pathlib import Path
|
||||
import os,re
|
||||
from policy_harness import ROOT,run,body
|
||||
from test_finite_magazine_reservation import translated_reservation
|
||||
p=Path(os.environ.get('ERR_INFANTRY_TRANSFER_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoTransfer.c'))
|
||||
s=p.read_text()
|
||||
for forbidden in ('TrySpawn','DeleteEntity','SetOrigin','SetTransform','TryInsert','TryRemove','SetAmmoCount'):
|
||||
assert forbidden not in s,forbidden
|
||||
callback=s[s.index('class ERR_InfantryAmmoCallback'):s.index('// One exact physical')]
|
||||
code=s[s.index('class ERR_InfantryAmmoTransfer\n'):]
|
||||
code=re.sub(r'//[^\n]*','',code).replace('protected ','').replace('class ','struct ')
|
||||
for src,dst in {
|
||||
'm_Donor.FindComponent(VehicleHelicopterSimulation)':'m_Donor->helicopter',
|
||||
'InventoryItemComponent.Cast(loaded.GetOwner().FindComponent(InventoryItemComponent))':'loaded->GetOwner()->item',
|
||||
'BaseMagazineComponent.Cast(exactMagazine.FindComponent(BaseMagazineComponent))':'exactMagazine->magazine',
|
||||
'BaseWeaponManagerComponent.Cast(actor.FindComponent(BaseWeaponManagerComponent))':'actor->weapons',
|
||||
'BaseWeaponComponent.Cast(rifle.FindComponent(BaseWeaponComponent))':'rifle->weapon',
|
||||
'InventoryItemComponent.Cast(entity.FindComponent(InventoryItemComponent))':'entity->item',
|
||||
'InventoryItemComponent.Cast(m_Magazine.FindComponent(InventoryItemComponent))':'m_Magazine->item',
|
||||
'InventoryItemComponent.Cast(exact.FindComponent(InventoryItemComponent))':'exact->item',
|
||||
'InventoryItemComponent.Cast(candidate.FindComponent(InventoryItemComponent))':'candidate->item',
|
||||
'BaseMagazineComponent.Cast(m_Magazine.FindComponent(BaseMagazineComponent))':'m_Magazine->magazine',
|
||||
'BaseMagazineComponent.Cast(candidate.FindComponent(BaseMagazineComponent))':'candidate->magazine',
|
||||
'SCR_AIVehicleUsageComponent.Cast(m_Donor.FindComponent(SCR_AIVehicleUsageComponent))':'m_Donor->usage',
|
||||
'InventoryStorageManagerComponent.Cast(m_Donor.FindComponent(InventoryStorageManagerComponent))':'m_Donor->inventory',
|
||||
'InventoryStorageManagerComponent.Cast(m_Recipient.FindComponent(InventoryStorageManagerComponent))':'m_Recipient->inventory',
|
||||
}.items():code=code.replace(src,dst)
|
||||
code=code.replace('SCR_MuzzleInMagComponent.Cast(muzzle)', '(muzzle->inMag ? muzzle : null)')
|
||||
code=code.replace('ref ERR_InfantryAmmoCallback','ERR_InfantryAmmoCallback*').replace('array<','Array<').replace('foreach (','for (').replace('null','nullptr')
|
||||
code=re.sub(r'\bERR_GameMode (?=\w)','ERR_GameMode* ',code)
|
||||
code=code.replace('void ERR_InfantryAmmoTransfer(','ERR_InfantryAmmoTransfer(').replace('EWeaponType kind','int kind').replace('EMuzzleType muzzleKind','int muzzleKind')
|
||||
for name in ('ERR_InfantryAmmoTransferState','ERR_InfantryAmmoAccess','ERR_GameMode','ERR_EnemyEquipmentRules','ERR_ForceRules','Replication','SCR_Global','ERR_Actors','SCR_FactionManager','ERR_ConvoyRules','CompartmentAccessComponent','EWeaponType','EMuzzleType','EStoragePurpose','vector'):
|
||||
code=code.replace(name+'.',name+'::')
|
||||
for name in ('m_Mode','m_Donor','m_DonorGroup','m_Recipient','m_RecipientGroup','m_Source','m_Destination','m_Storage','m_OriginalSlot','m_Callback','magazine','reloadable','loaded','loadedItem','loadedSlot','manager','weapon','muzzle','entity','item','storage','inventory','incoming','empty','source','destination','m_ReturnCallback','donorRecord','recipientRecord','utility','usage','physics'):
|
||||
code=re.sub(r'\b'+name+r'\.',name+'->',code)
|
||||
code=code.replace('GetMagazineWell().','GetMagazineWell()->').replace('GetParentSlot().','GetParentSlot()->').replace('Forces().','Forces()->').replace('m_VehicleMgr.','m_VehicleMgr->').replace('GetPilotCompartmentSlot().','GetPilotCompartmentSlot()->')
|
||||
code=re.sub(r'\b(bool|int|Vehicle|IEntity|SCR_AIGroup|ERR_ForceRecord|InventoryStorageSlot|InventoryStorageManagerComponent|BaseInventoryStorageComponent|ERR_GameMode\*|ERR_InfantryAmmoCallback\*) (\w+);',r'\1 \2{};',code)
|
||||
code=code.replace('\n}\n','\n};\n')
|
||||
callback=callback.replace('class ERR_InfantryAmmoCallback : ScriptedInventoryOperationCallback','').strip()[1:-1]
|
||||
callbacks=[]
|
||||
for name in ('OnComplete','OnFailed','OnAllComplete','OnAllFailed'):
|
||||
m=re.search(r'protected override void '+name+r'\(\) (\{[^\n]+\})',callback)
|
||||
callbacks.append('void ERR_InfantryAmmoCallback::'+name+'() '+m[1].replace('Transfer.','Transfer->'))
|
||||
# Integrate the actual coordinator transfer selector with this actual leaf.
|
||||
coordinator_path=Path(os.environ.get('ERR_INFANTRY_RESUPPLY_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c'))
|
||||
transfer=body(coordinator_path,'protected void Transfer(float now)').replace('protected ','').replace('null','nullptr').replace('foreach (','for (')
|
||||
transfer=transfer.replace('ERR_HQAmmoSnapshot local','ERR_HQAmmoSnapshot* local')
|
||||
for name in ('ERR_Actors','ERR_HQAmmoSampler','ERR_InfantryAmmoTransfer','vector'):
|
||||
transfer=transfer.replace(name+'.',name+'::')
|
||||
transfer=transfer.replace('ERR_FiniteMagazineReservation reservation', 'ERR_FiniteMagazineReservation* reservation').replace('new ERR_FiniteMagazineReservation(m_Stock, m_Spent,', 'new ERR_FiniteMagazineReservation(&m_Stock, &m_Spent,')
|
||||
for name in ('m_Move','actor','m_Truck','m_Recipient','local','reservation'):
|
||||
transfer=transfer.replace(name+'.',name+'->')
|
||||
transfer=transfer.replace('Entity.GetOrigin()', 'Entity->GetOrigin()')
|
||||
pre=r'''
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <functional>
|
||||
using string=std::string;
|
||||
template<class T>struct Array:std::vector<T>{using std::vector<T>::vector;int Count(){return this->size();}bool IsEmpty(){return this->empty();}void Insert(T t){this->push_back(t);}void RemoveItem(T t){this->erase(std::remove(this->begin(),this->end(),t),this->end());}bool Contains(T t){return std::find(this->begin(),this->end(),t)!=this->end();}};
|
||||
struct vector{float x=0,y=0,z=0;float Length(){return std::sqrt(x*x+y*y+z*z);}static float DistanceXZ(vector a,vector b){return std::hypot(a.x-b.x,a.z-b.z);}static float Distance(vector a,vector b){return vector{a.x-b.x,a.y-b.y,a.z-b.z}.Length();}};
|
||||
struct Entity;struct Group;struct Inventory;struct Storage;struct Item;struct Slot;struct Magazine;struct Weapon;struct Muzzle;struct Manager;struct Utility;struct Usage;struct Physics_;struct Record;
|
||||
using IEntity=Entity*;using Vehicle=Entity*;using SCR_AIGroup=Group*;using ERR_ForceRecord=Record*;
|
||||
using InventoryStorageSlot=Slot*;using InventoryStorageManagerComponent=Inventory*;using BaseInventoryStorageComponent=Storage*;using InventoryItemComponent=Item*;using BaseMagazineComponent=Magazine*;
|
||||
using BaseWeaponManagerComponent=Manager*;using BaseWeaponComponent=Weapon*;using BaseMuzzleComponent=Muzzle*;using SCR_MuzzleInMagComponent=Muzzle*;
|
||||
using SCR_AIGroupUtilityComponent=Utility*;using SCR_AIVehicleUsageComponent=Usage*;using Physics=Physics_*;
|
||||
enum ERR_InfantryAmmoTransferState{FAILED=-1,PENDING,SUCCEEDED};
|
||||
struct ERR_InfantryAmmoTransfer;
|
||||
struct ScriptedInventoryOperationCallback{virtual void OnComplete(){}virtual void OnFailed(){}virtual void OnAllComplete(){}virtual void OnAllFailed(){}virtual ~ScriptedInventoryOperationCallback()=default;};
|
||||
struct ERR_InfantryAmmoCallback:ScriptedInventoryOperationCallback{ERR_InfantryAmmoTransfer*Transfer=nullptr;bool Returning=false;void OnComplete()override;void OnFailed()override;void OnAllComplete()override;void OnAllFailed()override;};
|
||||
struct EWeaponType{static const int WT_RIFLE=1,WT_SNIPERRIFLE=2,WT_MACHINEGUN=3,WT_HANDGUN=4,WT_GRENADELAUNCHER=5,WT_ROCKETLAUNCHER=6;};
|
||||
struct EMuzzleType{static const int MT_BaseMuzzle=0,MT_UGLMuzzle=1,MT_RPGMuzzle=2;};struct EStoragePurpose{static const int PURPOSE_DEPOSIT=1;};
|
||||
struct Well{int type=1,parent=0;int Type(){return type;}bool IsInherited(int t){return type==t||parent==t;}};
|
||||
struct Magazine{IEntity owner=nullptr;IEntity GetOwner(){return owner;}Well*well=nullptr;int rounds=30,capacity=30;bool used=false;bool IsUsed(){return used;}Well*GetMagazineWell(){return well;}int GetAmmoCount(){return rounds;}int GetMaxAmmoCount(){return capacity;}};
|
||||
struct Muzzle{bool inMag=false,canReload=true;bool CanBeReloaded(){return canReload;}bool disposable=false;bool IsDisposable(){return disposable;}Magazine*loaded=nullptr;Magazine*GetMagazine(){return loaded;}Well*well=nullptr;int kind=0;Well*GetMagazineWell(){return well;}int GetMuzzleType(){return kind;}};
|
||||
struct Weapon{IEntity owner=nullptr;Array<Muzzle*>muzzles;int kind=1;IEntity GetOwner(){return owner;}int GetWeaponType(){return kind;}void GetMuzzlesList(Array<Muzzle*>&a){a=muzzles;}};
|
||||
struct Manager{Array<IEntity>weapons;void GetWeaponsList(Array<IEntity>&a){a=weapons;}};
|
||||
struct Storage{IEntity owner=nullptr;IEntity GetOwner(){return owner;}};
|
||||
struct Slot{Storage*storage=nullptr;IEntity occupant=nullptr;Muzzle*container=nullptr;IEntity attached=nullptr;Muzzle*GetParentContainer(){return container;}IEntity GetAttachedEntity(){return attached;}Storage*GetStorage(){return storage;}IEntity GetOccupant(){return occupant;}};
|
||||
struct Item{Slot*slot=nullptr;Slot*GetParentSlot(){return slot;}};
|
||||
struct Physics_{vector velocity,angular;vector GetVelocity(){return velocity;}vector GetAngularVelocity(){return angular;}};
|
||||
struct Usage{Slot*pilot=nullptr;Slot*GetPilotCompartmentSlot(){return pilot;}};
|
||||
struct VehicleManager{IEntity vehicle=nullptr;IEntity FindVehicle(IEntity v){return vehicle==v?v:nullptr;}};
|
||||
struct Utility{VehicleManager*m_VehicleMgr=nullptr;bool military=true;bool IsMilitary(){return military;}};
|
||||
struct Group{int faction=1,players=0;bool slave=false;Utility*utility=nullptr;int GetPlayerCount(bool){return players;}int GetFaction(){return faction;}bool IsSlave(){return slave;}Utility*GetGroupUtilityComponent(){return utility;}};
|
||||
struct Entity{bool helicopter=false;bool alive=true,awake=true,player=false,captured=false;int faction=1;Group*group=nullptr;IEntity vehicle=nullptr,parent=nullptr;
|
||||
Inventory*inventory=nullptr;Magazine*magazine=nullptr;Manager*weapons=nullptr;Weapon*weapon=nullptr;Item*item=nullptr;Usage*usage=nullptr;Physics_*physics=nullptr;vector position;
|
||||
IEntity GetParent(){return parent;}Physics_*GetPhysics(){return physics;}vector GetOrigin(){return position;}};
|
||||
struct Record{SCR_AIGroup Group=nullptr;bool Physical=true,Eliminated=false;};
|
||||
struct Ledger{Array<Record*>records;Record*FindGroup(SCR_AIGroup g){for(auto*r:records)if(r->Group==g)return r;return nullptr;}};
|
||||
struct ERR_GameMode{inline static ERR_GameMode*current=nullptr;bool active=true;Ledger*ledger=nullptr;static ERR_GameMode*Get(){return current;}bool Active(){return active;}Ledger*Forces(){return ledger;}int EnemyFaction(){return 1;}};
|
||||
struct Replication{inline static bool server=true;static bool IsServer(){return server;}};
|
||||
struct SCR_Global{inline static bool editor=false;static bool IsEditMode(){return editor;}};
|
||||
struct ERR_Actors{static bool CanFight(IEntity a){return a&&a->alive&&a->awake;}static bool Alive(IEntity a){return a&&a->alive;}};
|
||||
struct SCR_FactionManager{static int SGetFaction(IEntity a){return a?a->faction:-1;}};
|
||||
struct CompartmentAccessComponent{static IEntity GetVehicleIn(IEntity a){return a?a->vehicle:nullptr;}};
|
||||
struct ERR_ConvoyRules{static bool Captured(Vehicle v,SCR_AIGroup g){return v->captured||g->players>0;}static bool PartOf(IEntity a,IEntity root){return a==root;}};
|
||||
struct ERR_EnemyEquipmentRules{static bool Eligible(ERR_GameMode*m,SCR_AIGroup g,IEntity a){return m&&g&&a&&a->alive&&a->awake&&!a->player&&a->group==g&&g->players==0&&g->faction==m->EnemyFaction()&&g->utility&&g->utility->military;}};
|
||||
struct ERR_ForceRules{static bool Finite(float n){return std::isfinite(n);}};
|
||||
struct ERR_InfantryAmmoAccess{static inline bool clear=true;static inline int checks=0;static bool Clear(Vehicle donor,IEntity recipient){assert(donor&&recipient);checks++;return clear;}};
|
||||
struct Inventory{IEntity owner=nullptr;Array<IEntity>items;Array<Storage*>storages;Storage*selected=nullptr;bool allow=true,accept=true;int calls=0,callback=0;ScriptedInventoryOperationCallback*last=nullptr;std::function<void()> effect;
|
||||
IEntity GetOwner(){return owner;}void GetItems(Array<IEntity>&a,int purpose){assert(purpose==1);a=items;}void GetStorages(Array<Storage*>&a,int purpose){assert(purpose==1);a=storages;}
|
||||
Storage*FindStorageForItem(IEntity,int purpose){assert(purpose==1);return selected;}
|
||||
bool CanMoveItemToStorage(IEntity,Storage*,int slot){assert(slot==-1);return allow;}
|
||||
bool TryMoveItemToStorage(IEntity,Storage*,int slot,ScriptedInventoryOperationCallback*cb){assert(slot==-1);calls++;last=cb;if(effect)effect();if(callback==1){cb->OnComplete();}if(callback==2){cb->OnFailed();}return accept;}};
|
||||
'''
|
||||
main=r'''
|
||||
struct Fixture{ERR_GameMode mode;Ledger ledger;Group donorGroup,recipientGroup,otherGroup;Record donorRecord,recipientRecord;Entity truck,recipient,driver,spareDriver,magEntity,rifle,foreign;
|
||||
VehicleManager vehicleManager;Utility donorUtility,recipientUtility;Physics_ physics;Usage usage;Slot pilot,fromSlot,toSlot;Storage sourceStorage,targetStorage;Inventory source,destination;Item item;Magazine magazine;Manager weapons;Weapon weapon;Muzzle muzzle;Well well;
|
||||
Fixture(){ERR_GameMode::current=&mode;mode.ledger=&ledger;donorRecord.Group=&donorGroup;recipientRecord.Group=&recipientGroup;ledger.records={&donorRecord,&recipientRecord};
|
||||
donorGroup.utility=&donorUtility;recipientGroup.utility=&recipientUtility;donorUtility.m_VehicleMgr=&vehicleManager;vehicleManager.vehicle=&truck;
|
||||
truck.physics=&physics;truck.usage=&usage;usage.pilot=&pilot;pilot.occupant=&driver;driver.group=&donorGroup;driver.vehicle=&truck;spareDriver.group=&donorGroup;spareDriver.vehicle=&truck;
|
||||
recipient.group=&recipientGroup;recipient.position.x=4;truck.inventory=&source;source.owner=&truck;recipient.inventory=&destination;destination.owner=&recipient;
|
||||
sourceStorage.owner=&truck;targetStorage.owner=&recipient;source.storages={&sourceStorage};destination.storages={&targetStorage};destination.selected=&targetStorage;
|
||||
source.items={&magEntity};magEntity.item=&item;item.slot=&fromSlot;fromSlot.storage=&sourceStorage;fromSlot.attached=&magEntity;toSlot.storage=&targetStorage;magEntity.magazine=&magazine;magazine.well=&well;
|
||||
recipient.weapons=&weapons;weapons.weapons={&rifle};rifle.weapon=&weapon;weapon.owner=&rifle;weapon.muzzles={&muzzle};muzzle.well=&well;}
|
||||
ERR_InfantryAmmoTransfer Job(){return ERR_InfantryAmmoTransfer(&mode,&truck,&donorGroup,&recipient,&recipientGroup,&magEntity,true);}
|
||||
void Move(){source.items.RemoveItem(&magEntity);destination.items.Insert(&magEntity);item.slot=&toSlot;}
|
||||
};
|
||||
struct EmptyFixture:Fixture{
|
||||
Entity empty,secondEmpty;Magazine emptyMag;Item emptyItem,secondItem;Slot emptyFrom,emptyTo;
|
||||
EmptyFixture(){emptyMag.well=&well;emptyMag.rounds=0;empty.magazine=&emptyMag;empty.item=&emptyItem;
|
||||
emptyFrom.storage=&targetStorage;emptyTo.storage=&sourceStorage;emptyItem.slot=&emptyFrom;
|
||||
secondEmpty.magazine=&emptyMag;secondEmpty.item=&secondItem;secondItem.slot=&emptyFrom;
|
||||
destination.items={&empty,&secondEmpty};destination.selected=nullptr;source.selected=&sourceStorage;}
|
||||
void Return(bool capacity=true){destination.items.RemoveItem(&empty);source.items.Insert(&empty);emptyItem.slot=&emptyTo;if(capacity)destination.selected=&targetStorage;}
|
||||
};
|
||||
struct ERR_HQAmmoSnapshot{bool Complete=true,LauncherComplete=true;int Members=1,LauncherMuzzles=1,LauncherMagazines=1,LauncherRounds=0,LauncherChambers=0;bool Valid(int n){return n==Members;}int SmallArmsMuzzles=1,SmallArmsRounds=0,SmallArmsChambers=0;};
|
||||
struct ERR_HQAmmoSampler{static void Inspect(IEntity actor,SCR_AIGroup group,ERR_HQAmmoSnapshot* stock){assert(actor&&actor->group==group&&stock);}};
|
||||
struct SupplyTruck{IEntity Entity;SCR_AIGroup Group;};
|
||||
struct SupplyRecipient{SCR_AIGroup Group;};
|
||||
struct Coordinator{bool m_LauncherTrip=false;ERR_GameMode* m_Mode;SupplyTruck* m_Truck;SupplyRecipient* m_Recipient;
|
||||
ERR_InfantryAmmoTransfer* m_Move=nullptr;Array<IEntity>m_Members,m_Stock,m_Spent,m_Served;IEntity m_Receiving=nullptr;
|
||||
int m_Delivered=0,m_TripDelivered=0,finishes=0,audits=0;
|
||||
void Finish(string){finishes++;if(m_Move)m_Move->Stop();}
|
||||
void Audit(string){audits++;}
|
||||
bool Contains(IEntity owner,IEntity item){return owner&&owner->inventory&&owner->inventory->items.Count()<=128&&owner->inventory->items.Contains(item);}
|
||||
'''+transfer+r'''
|
||||
};
|
||||
struct SupplyFixture:Fixture{SupplyTruck supplyTruck;SupplyRecipient supplyRecipient;Coordinator c;
|
||||
SupplyFixture():supplyTruck{&truck,&donorGroup},supplyRecipient{&recipientGroup}{
|
||||
c.m_Mode=&mode;c.m_Truck=&supplyTruck;c.m_Recipient=&supplyRecipient;c.m_Members={&recipient};c.m_Stock={&magEntity};}
|
||||
};
|
||||
struct LauncherFixture:SupplyFixture{Entity loaded;Magazine empty;Item loadedItem;Slot loadedSlot;
|
||||
LauncherFixture(){c.m_LauncherTrip=true;weapon.kind=EWeaponType::WT_GRENADELAUNCHER;muzzle.kind=EMuzzleType::MT_UGLMuzzle;
|
||||
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(){
|
||||
|
||||
// The shared force claim is necessary: independent rifle leaves can otherwise
|
||||
// submit the same still-carried empty to two different trucks. Native acceptance
|
||||
// is delayed here; this proves submission interference, not an engine outcome.
|
||||
{EmptyFixture first;Fixture second;ERR_GameMode::current=&first.mode;
|
||||
first.ledger.records.Insert(&second.donorRecord);second.source.selected=&second.sourceStorage;
|
||||
auto old=first.Job();assert(old.Tick(0)==PENDING&&old.Unresolved());
|
||||
assert(old.m_ReturnMagazine==&first.empty&&old.m_ReturnStorage==&first.sourceStorage);
|
||||
old.Stop();assert(old.Unresolved()&&old.Tick(180001)==FAILED);
|
||||
ERR_InfantryAmmoTransfer next(&first.mode,&second.truck,&second.donorGroup,&first.recipient,&first.recipientGroup,&second.magEntity,true);
|
||||
assert(next.Tick(180001)==PENDING&&next.Unresolved());
|
||||
assert(first.destination.calls==2&&next.m_ReturnMagazine==old.m_ReturnMagazine);
|
||||
assert(next.m_ReturnStorage==&second.sourceStorage&&next.m_ReturnStorage!=old.m_ReturnStorage);
|
||||
assert(first.destination.items.Contains(&first.empty)&&first.source.calls==0&&second.source.calls==0);
|
||||
// No duplicate object is invented: one physical completion can settle only its
|
||||
// original donor proof; the competing outstanding submission remains unknown.
|
||||
first.Return();old.m_ReturnCallback->OnComplete();assert(!old.Unresolved()&&next.Unresolved());
|
||||
assert(old.Tick(180002)==FAILED&&first.source.calls==0&&second.source.calls==0);}
|
||||
// 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());
|
||||
if(bad!=0)f.source.last->OnFailed();
|
||||
if(bad==1)f.item.slot=nullptr;
|
||||
if(bad==2)f.fromSlot.attached=nullptr;
|
||||
if(bad==3)f.sourceStorage.owner=&f.foreign;
|
||||
if(bad==4)f.destination.items.Insert(&f.magEntity);
|
||||
if(bad==5)f.truck.inventory=&f.destination;
|
||||
if(bad==6)f.source.items.RemoveItem(&f.magEntity);
|
||||
assert(f.c.m_Move->Unresolved());f.c.m_Move->Stop();assert(f.c.m_Move->Unresolved());}
|
||||
|
||||
{LauncherFixture f;f.muzzle.loaded=nullptr;assert(ERR_InfantryAmmoTransfer::Compatible(&f.recipient,&f.magEntity,true));f.c.Transfer(0);assert(f.source.calls==1&&f.c.m_Move->Submitted());}
|
||||
|
||||
{LauncherFixture f;assert(!ERR_InfantryAmmoTransfer::Compatible(&f.recipient,&f.magEntity));assert(ERR_InfantryAmmoTransfer::Compatible(&f.recipient,&f.magEntity,true));
|
||||
f.c.Transfer(0);assert(f.c.m_Move&&f.c.m_Move->Submitted()&&f.c.m_Spent.Count()==1&&f.source.calls==1);
|
||||
f.Move();f.source.last->OnComplete();f.c.Transfer(1000);f.c.Transfer(2000);assert(f.c.m_Delivered==1&&f.source.calls==1&&f.c.m_Served.Count()==1);}
|
||||
for(int bad=0;bad<8;bad++){LauncherFixture f;if(bad==0)f.magazine.used=true;if(bad==1)f.muzzle.well=nullptr;if(bad==2)f.muzzle.disposable=true;if(bad==3)f.empty.well=nullptr;if(bad==4)f.loadedSlot.attached=nullptr;if(bad==5)f.rifle.parent=nullptr;if(bad==6)f.empty.capacity=0;if(bad==7){f.muzzle.inMag=true;f.muzzle.canReload=false;}
|
||||
f.c.Transfer(0);assert(!f.c.m_Move&&f.source.calls==0&&f.c.m_Spent.IsEmpty());}
|
||||
{LauncherFixture f;f.source.accept=false;f.c.Transfer(0);assert(f.c.m_Move&&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.Move();f.source.last->OnComplete();assert(!f.c.m_Move->Unresolved());}
|
||||
{LauncherFixture f;auto t=ERR_InfantryAmmoTransfer(&f.mode,&f.truck,&f.donorGroup,&f.recipient,&f.recipientGroup,&f.magEntity,false,true);
|
||||
f.source.effect=[&](){t.Stop();f.Move();};f.source.callback=1;assert(t.Tick(0)==FAILED&&!t.Unresolved()&&f.source.calls==1);assert(t.Tick(1)==FAILED);}
|
||||
|
||||
// A capacity recovery uses one exact unused empty, separately proving both native operations.
|
||||
{Fixture f;Entity empty;Magazine emptyMag;Item emptyItem;Slot emptyFrom{&f.targetStorage},emptyTo{&f.sourceStorage};
|
||||
emptyMag.well=&f.well;emptyMag.rounds=0;empty.magazine=&emptyMag;empty.item=&emptyItem;emptyItem.slot=&emptyFrom;
|
||||
f.destination.items={&empty};f.destination.selected=nullptr;f.source.selected=&f.sourceStorage;
|
||||
auto t=f.Job();assert(t.Tick(0)==PENDING&&t.Submitted()&&t.Unresolved()&&f.destination.calls==1&&f.source.calls==0);
|
||||
auto returning=f.destination.last;returning->OnComplete();assert(t.Tick(1)==PENDING&&f.source.calls==0&&t.Unresolved());
|
||||
f.destination.items.clear();f.source.items.Insert(&empty);emptyItem.slot=&emptyTo;f.destination.selected=&f.targetStorage;
|
||||
assert(t.Tick(2)==PENDING&&!t.Unresolved()&&f.source.calls==0);assert(t.Tick(3)==PENDING&&f.source.calls==1&&t.Unresolved());
|
||||
returning->OnAllComplete();returning->OnFailed();assert(t.Tick(4)==PENDING&&t.Unresolved());
|
||||
f.Move();assert(t.Tick(5)==PENDING);f.source.last->OnComplete();assert(t.Tick(6)==SUCCEEDED&&!t.Unresolved());
|
||||
assert(f.destination.calls==1&&f.source.calls==1);}
|
||||
// Ground coordinator reserves the incoming identity as soon as reverse native movement is submitted.
|
||||
// A failed/ambiguous return never releases it to try a second empty or another incoming magazine.
|
||||
for(int outcome=0;outcome<3;outcome++){EmptyFixture f;SupplyTruck truck{&f.truck,&f.donorGroup};SupplyRecipient recipient{&f.recipientGroup};Coordinator c;
|
||||
c.m_Mode=&f.mode;c.m_Truck=&truck;c.m_Recipient=&recipient;c.m_Members={&f.recipient};c.m_Stock={&f.magEntity};
|
||||
if(outcome==0){f.destination.accept=false;}
|
||||
c.Transfer(0);assert(c.m_Move&&c.m_Move->Submitted()&&c.m_Spent.Count()==1&&c.m_Receiving==&f.recipient&&c.m_Delivered==0);
|
||||
if(outcome==1){f.Return(false);f.destination.last->OnComplete();c.Transfer(1000);}
|
||||
c.Transfer(outcome==2?8000:2000);assert(c.finishes==1&&c.m_Spent.Contains(&f.magEntity)&&c.m_Delivered==0&&f.destination.calls==1&&f.source.calls==0);
|
||||
assert(c.m_Move->Unresolved()==(outcome==2));}
|
||||
{EmptyFixture f;SupplyTruck truck{&f.truck,&f.donorGroup};SupplyRecipient recipient{&f.recipientGroup};Coordinator c;
|
||||
c.m_Mode=&f.mode;c.m_Truck=&truck;c.m_Recipient=&recipient;c.m_Members={&f.recipient};c.m_Stock={&f.magEntity};
|
||||
c.Transfer(0);f.Return();f.destination.last->OnComplete();c.Transfer(1000);assert(c.m_Delivered==0&&f.source.calls==0);
|
||||
c.Transfer(2000);assert(c.m_Delivered==0&&f.source.calls==1);f.Move();f.source.last->OnComplete();c.Transfer(3000);c.Transfer(4000);
|
||||
assert(c.m_Delivered==1&&c.m_Served.Count()==1&&c.m_Spent.Count()==1&&f.source.calls==1&&f.destination.calls==1&&f.source.items.Contains(&f.empty));}
|
||||
// Default callers (including air delivery) retain the original one-way behavior.
|
||||
{EmptyFixture f;ERR_InfantryAmmoTransfer t(&f.mode,&f.truck,&f.donorGroup,&f.recipient,&f.recipientGroup,&f.magEntity);
|
||||
assert(t.Tick(0)==FAILED&&!t.Submitted()&&f.destination.calls==0&&f.source.calls==0);}
|
||||
// No return when capacity already exists, even with carried empties.
|
||||
{EmptyFixture f;f.destination.selected=&f.targetStorage;auto t=f.Job();assert(t.Tick(0)==PENDING&&f.source.calls==1&&f.destination.calls==0);}
|
||||
// Unused, zero-round, exact-well, exclusive recipient storage ownership and donor space are required.
|
||||
for(int invalid=0;invalid<12;invalid++){EmptyFixture f;f.destination.items={&f.empty};Well other;other.type=2;
|
||||
if(invalid==0)f.emptyMag.used=true;if(invalid==1)f.emptyMag.rounds=1;if(invalid==2)f.emptyMag.rounds=-1;
|
||||
if(invalid==3)f.emptyMag.capacity=0;if(invalid==4)f.emptyMag.well=&other;if(invalid==5)f.emptyMag.well=nullptr;
|
||||
if(invalid==6)f.emptyItem.slot=&f.emptyTo;if(invalid==7)f.source.items.Insert(&f.empty);
|
||||
if(invalid==8)f.source.selected=nullptr;if(invalid==9)f.destination.allow=false;
|
||||
if(invalid==10){for(int i=0;i<129;i++)f.destination.items.Insert(&f.empty);}if(invalid==11)ERR_InfantryAmmoAccess::clear=false;
|
||||
auto t=f.Job();assert(t.Tick(0)==FAILED&&!t.Submitted()&&!t.Unresolved()&&f.destination.calls==0&&f.source.calls==0);
|
||||
ERR_InfantryAmmoAccess::clear=true;}
|
||||
// Return proof needs exact destination slot as well as callback; no second candidate is ever moved.
|
||||
{EmptyFixture f;auto t=f.Job();t.Tick(0);f.Return();f.emptyItem.slot=&f.emptyFrom;f.destination.last->OnComplete();
|
||||
assert(t.Tick(1)==PENDING&&t.Unresolved()&&f.source.calls==0&&f.destination.calls==1);
|
||||
f.emptyItem.slot=&f.emptyTo;assert(t.Tick(2)==PENDING&&!t.Unresolved());assert(t.Tick(3)==PENDING&&f.source.calls==1&&f.destination.calls==1);}
|
||||
// Inline success callbacks override a false API result for the reverse operation, but require physical proof.
|
||||
{EmptyFixture f;f.destination.accept=false;f.destination.callback=1;f.destination.effect=[&](){f.Return();};auto t=f.Job();
|
||||
assert(t.Tick(0)==PENDING&&t.Submitted()&&!t.Unresolved());assert(t.Tick(1)==PENDING&&f.source.calls==0);
|
||||
f.source.accept=false;f.source.callback=1;f.source.effect=[&](){f.Move();};assert(t.Tick(2)==SUCCEEDED&&f.source.calls==1&&f.destination.calls==1);}
|
||||
// Every attempted reverse move burns the incoming identity, including synchronous rejection.
|
||||
for(int failure=0;failure<3;failure++){EmptyFixture f;if(failure==0)f.destination.accept=false;if(failure==1)f.destination.callback=2;
|
||||
auto t=f.Job();assert(t.Tick(0)==PENDING&&t.Submitted()&&f.destination.calls==1&&f.source.calls==0);
|
||||
assert(t.Tick(failure==2?8000:1)==FAILED);assert(t.Unresolved()==(failure==2));
|
||||
for(int i=0;i<3;i++){t.Tick(9000+i);}assert(f.destination.calls==1&&f.source.calls==0);}
|
||||
// Stop before, during, or after confirmed return can never launch the incoming move.
|
||||
for(int stopAt=0;stopAt<3;stopAt++){EmptyFixture f;auto t=f.Job();if(stopAt==0){t.Stop();assert(t.Tick(0)==FAILED&&!t.Submitted());continue;}
|
||||
t.Tick(0);if(stopAt==2){f.Return();f.destination.last->OnComplete();assert(t.Tick(1)==PENDING&&!t.Unresolved());}
|
||||
t.Stop();assert(t.Tick(2)==FAILED&&t.Submitted()&&f.source.calls==0);if(stopAt==1){assert(t.Unresolved());f.Return();f.destination.last->OnAllComplete();}
|
||||
assert(!t.Unresolved()&&t.Tick(3)==FAILED&&f.source.calls==0&&f.destination.calls==1);}
|
||||
// Confirmed return cannot trigger a second empty or bypass revalidated incoming custody/capacity/access.
|
||||
for(int changed=0;changed<6;changed++){EmptyFixture f;auto t=f.Job();t.Tick(0);f.Return(changed!=0);f.destination.last->OnComplete();assert(t.Tick(1)==PENDING);
|
||||
if(changed==1)f.source.items.RemoveItem(&f.magEntity);if(changed==2)f.destination.items.Insert(&f.magEntity);
|
||||
if(changed==3)f.truck.captured=true;if(changed==4)f.recipient.player=true;if(changed==5)ERR_InfantryAmmoAccess::clear=false;
|
||||
assert(t.Tick(2)==FAILED&&t.Submitted()&&!t.Unresolved()&&f.source.calls==0&&f.destination.calls==1);
|
||||
assert(t.Tick(3)==FAILED&&f.destination.calls==1);ERR_InfantryAmmoAccess::clear=true;}
|
||||
// Original owner/driver/ledger loss while a return is accepted quarantines that exact operation.
|
||||
for(int changed=0;changed<4;changed++){EmptyFixture f;auto t=f.Job();t.Tick(0);
|
||||
if(changed==0)f.truck.captured=true;if(changed==1)f.recipient.player=true;if(changed==2)f.pilot.occupant=&f.spareDriver;if(changed==3)f.donorRecord.Eliminated=true;
|
||||
assert(t.Tick(1)==FAILED&&t.Unresolved());f.destination.last->OnFailed();assert(!t.Unresolved()&&f.source.calls==0&&f.destination.calls==1);}
|
||||
// Both native phases are bounded independently, with no renewal while waiting for callbacks.
|
||||
{EmptyFixture f;auto t=f.Job();t.Tick(0);f.Return();f.destination.last->OnComplete();assert(t.Tick(7999)==PENDING);
|
||||
assert(t.Tick(8000)==PENDING&&f.source.calls==1);assert(t.Tick(15999)==FAILED&&t.Unresolved());}
|
||||
// XZ approach can precede valid vertical reach, stopped state, capacity or clear access.
|
||||
// None of those no-submission outcomes consumes cargo or ends the trip; the same exact item can later submit once.
|
||||
for(int obstruction=0;obstruction<5;obstruction++){SupplyFixture f;
|
||||
if(obstruction==0){f.recipient.position.y=3;}if(obstruction==1){f.physics.velocity.x=1;}
|
||||
if(obstruction==2){f.destination.selected=nullptr;}if(obstruction==3){f.source.allow=false;}
|
||||
if(obstruction==4){ERR_InfantryAmmoAccess::clear=false;}
|
||||
for(int tick=0;tick<3;tick++){f.c.Transfer(tick*1000);assert(f.source.calls==0&&f.c.m_Spent.IsEmpty()&&!f.c.m_Move&&!f.c.m_Receiving&&f.c.finishes==0);}
|
||||
f.recipient.position.y=0;f.physics.velocity.x=0;f.destination.selected=&f.targetStorage;f.source.allow=true;ERR_InfantryAmmoAccess::clear=true;
|
||||
f.c.Transfer(3000);assert(f.source.calls==1&&f.c.m_Spent.Count()==1&&f.c.m_Move&&f.c.m_Move->Submitted());
|
||||
f.Move();f.source.last->OnComplete();f.c.Transfer(4000);assert(f.c.m_Delivered==1&&f.c.m_Served.Contains(&f.recipient)&&f.source.calls==1&&f.c.m_Spent.Count()==1);
|
||||
}
|
||||
// A capacity-blocked first member cannot prevent another original member from receiving this magazine.
|
||||
{SupplyFixture f;Fixture second;ERR_GameMode::current=&f.mode;
|
||||
second.recipient.group=&f.recipientGroup;second.recipientRecord.Group=&f.recipientGroup;
|
||||
f.c.m_Members.Insert(&second.recipient);f.destination.selected=nullptr;
|
||||
f.c.Transfer(0);assert(f.source.calls==1&&f.c.m_Receiving==&second.recipient&&f.c.m_Spent.Count()==1&&f.c.finishes==0);
|
||||
f.source.items.clear();second.destination.items={&f.magEntity};f.item.slot=&second.toSlot;f.source.last->OnComplete();
|
||||
f.c.Transfer(1000);assert(f.c.m_Delivered==1&&f.c.m_Served.Contains(&second.recipient)&&!f.c.m_Served.Contains(&f.recipient));}
|
||||
// A native API may complete both physical movement and callback inline. Account once on the next slow tick.
|
||||
{SupplyFixture f;f.source.callback=1;f.source.effect=[&](){f.Move();};f.c.Transfer(0);
|
||||
assert(f.source.calls==1&&f.c.m_Move&&f.c.m_Move->Submitted()&&f.c.m_Delivered==0&&f.c.m_Spent.Count()==1);
|
||||
f.c.Transfer(1000);f.c.Transfer(2000);assert(f.c.m_Delivered==1&&f.c.m_Served.Count()==1&&f.source.calls==1&&f.c.finishes==0);}
|
||||
// Crossing the native submission boundary burns the exact identity even if native refusal is synchronous.
|
||||
for(int refusal=0;refusal<2;refusal++){SupplyFixture f;if(refusal==0){f.source.accept=false;}else{f.source.callback=2;}
|
||||
f.c.Transfer(0);assert(f.source.calls==1&&f.c.m_Spent.Count()==1&&f.c.m_Move->Submitted());
|
||||
f.c.Transfer(1000);assert(f.c.finishes==1&&f.c.m_Spent.Count()==1&&f.source.calls==1);
|
||||
}
|
||||
// Accepted but unresolved loss stays retained/spent; changing geometry cannot cause a second native move.
|
||||
{SupplyFixture f;f.c.Transfer(0);f.recipient.position.x=8;f.c.Transfer(1000);
|
||||
assert(f.c.finishes==1&&f.c.m_Move&&f.c.m_Move->Unresolved()&&f.c.m_Spent.Count()==1&&f.source.calls==1);}
|
||||
// Several equivalent magazines do not multiply a blocked actor's expensive preflight work on one slow tick.
|
||||
{SupplyFixture f;Entity another=f.magEntity;f.source.items.Insert(&another);f.c.m_Stock.Insert(&another);
|
||||
ERR_InfantryAmmoAccess::clear=false;ERR_InfantryAmmoAccess::checks=0;f.c.Transfer(0);
|
||||
assert(ERR_InfantryAmmoAccess::checks==1&&f.source.calls==0&&f.c.m_Spent.IsEmpty());ERR_InfantryAmmoAccess::clear=true;}
|
||||
// A blocked native access check happens before submission and is terminal.
|
||||
{Fixture f;auto t=f.Job();ERR_InfantryAmmoAccess::clear=false;ERR_InfantryAmmoAccess::checks=0;
|
||||
assert(t.Tick(0)==FAILED&&!t.Submitted()&&!t.Unresolved()&&f.source.calls==0&&ERR_InfantryAmmoAccess::checks==1);
|
||||
ERR_InfantryAmmoAccess::clear=true;assert(t.Tick(1)==FAILED&&f.source.calls==0&&ERR_InfantryAmmoAccess::checks==1);}
|
||||
// Once native move is accepted, later geometry cannot cause a second operation or pretend cancellation.
|
||||
{Fixture f;auto t=f.Job();ERR_InfantryAmmoAccess::checks=0;assert(t.Tick(0)==PENDING&&ERR_InfantryAmmoAccess::checks==1);
|
||||
ERR_InfantryAmmoAccess::clear=false;assert(t.Tick(1)==PENDING&&t.Unresolved()&&f.source.calls==1&&ERR_InfantryAmmoAccess::checks==1);
|
||||
f.Move();f.source.last->OnComplete();assert(t.Tick(2)==SUCCEEDED);ERR_InfantryAmmoAccess::clear=true;}
|
||||
// Read-only selection follows the native inherited-well direction, excluding launcher muzzles and weapons.
|
||||
{Fixture f;assert(ERR_InfantryAmmoTransfer::Compatible(&f.recipient,&f.magEntity));Well derived;derived.type=2;derived.parent=1;f.magazine.well=&derived;assert(ERR_InfantryAmmoTransfer::Compatible(&f.recipient,&f.magEntity));
|
||||
f.magazine.well=&f.well;f.muzzle.well=&derived;assert(!ERR_InfantryAmmoTransfer::Compatible(&f.recipient,&f.magEntity));
|
||||
f.muzzle.well=&f.well;f.muzzle.kind=EMuzzleType::MT_UGLMuzzle;assert(!ERR_InfantryAmmoTransfer::Compatible(&f.recipient,&f.magEntity));
|
||||
f.muzzle.kind=0;f.weapon.kind=EWeaponType::WT_ROCKETLAUNCHER;assert(!ERR_InfantryAmmoTransfer::Compatible(&f.recipient,&f.magEntity));}
|
||||
// Exactly one source move; neither a callback alone nor physical movement alone is a successful transaction.
|
||||
{Fixture f;auto t=f.Job();assert(t.Tick(100)==PENDING&&f.source.calls==1&&t.Unresolved());f.source.last->OnComplete();assert(t.Tick(101)==PENDING&&t.Unresolved());
|
||||
f.Move();assert(t.Tick(102)==SUCCEEDED&&!t.Unresolved());t.Stop();assert(t.Tick(103)==SUCCEEDED&&f.source.calls==1);}
|
||||
{Fixture f;auto t=f.Job();t.Tick(100);f.Move();assert(t.Tick(101)==PENDING&&t.Unresolved());f.source.last->OnAllComplete();assert(t.Tick(102)==SUCCEEDED);}
|
||||
// Exact destination slot and known donor absence are mandatory even after success callback.
|
||||
{Fixture f;auto t=f.Job();t.Tick(100);f.Move();f.item.slot=&f.fromSlot;f.source.last->OnComplete();assert(t.Tick(101)==PENDING&&t.Unresolved());
|
||||
f.item.slot=&f.toSlot;for(int i=0;i<513;i++)f.source.items.Insert(&f.foreign);assert(t.Tick(102)==PENDING&&t.Unresolved());}
|
||||
// Late callbacks resolve retained reservations after Stop without Tick or further operations; the stopped task stays failed.
|
||||
{Fixture f;auto t=f.Job();t.Tick(0);t.Stop();assert(t.Unresolved());f.Move();f.source.last->OnAllComplete();assert(!t.Unresolved());assert(t.Tick(2)==FAILED&&f.source.calls==1);}
|
||||
{Fixture f;auto t=f.Job();t.Tick(0);t.Stop();f.source.last->OnAllFailed();assert(!t.Unresolved());assert(t.Tick(1)==FAILED&&f.source.calls==1);}
|
||||
{Fixture f;auto t=f.Job();t.Tick(0);f.source.last->OnComplete();f.source.last->OnFailed();assert(t.Unresolved());f.Move();assert(!t.Unresolved()&&t.Tick(1)==SUCCEEDED);}
|
||||
// Failure/rejection and the 8s deadline never submit a second move.
|
||||
for(int failure=0;failure<3;failure++){Fixture f;if(failure==0)f.source.accept=false;if(failure==1)f.source.callback=2;auto t=f.Job();t.Tick(100);
|
||||
if(failure==2){assert(t.Tick(8100)==FAILED&&t.Unresolved());}else assert(t.Tick(101)==FAILED&&!t.Unresolved());
|
||||
for(int i=0;i<10;i++)t.Tick(8200+i);assert(f.source.calls==1);}
|
||||
// Invalid physical state before submission spends no native action; the terminal object cannot revive.
|
||||
for(int invalid=0;invalid<25;invalid++){Fixture f;auto t=f.Job();
|
||||
if(invalid==0)Replication::server=false;if(invalid==1)SCR_Global::editor=true;if(invalid==2)f.mode.active=false;
|
||||
if(invalid==3)f.truck.alive=false;if(invalid==4)f.recipient.alive=false;if(invalid==5)f.recipient.awake=false;if(invalid==6)f.recipient.player=true;
|
||||
if(invalid==7)f.recipient.vehicle=&f.truck;if(invalid==8)f.truck.captured=true;if(invalid==9)f.donorGroup.players=1;
|
||||
if(invalid==10)f.recipient.group=&f.otherGroup;if(invalid==11)f.donorRecord.Physical=false;if(invalid==12)f.recipientRecord.Eliminated=true;
|
||||
if(invalid==13)f.vehicleManager.vehicle=&f.foreign;if(invalid==14)f.driver.alive=false;if(invalid==15)f.driver.vehicle=nullptr;
|
||||
if(invalid==16)f.physics.velocity.x=.251f;if(invalid==17)f.physics.angular.x=.101f;if(invalid==18)f.recipient.position.x=4.001f;
|
||||
if(invalid==19)f.truck.faction=2;if(invalid==20)f.driver.faction=2;if(invalid==21)f.recipientGroup.slave=true;
|
||||
if(invalid==22)f.magazine.rounds=0;if(invalid==23)f.magazine.rounds=31;if(invalid==24)f.physics.velocity.x=std::numeric_limits<float>::quiet_NaN();
|
||||
assert(t.Tick(100)==FAILED&&f.source.calls==0&&!t.Unresolved());Replication::server=true;SCR_Global::editor=false;assert(t.Tick(200)==FAILED&&f.source.calls==0);}
|
||||
// Native stock/storage identity and capacity guards reject shared, foreign, oversized and inaccessible inventory.
|
||||
for(int invalid=0;invalid<9;invalid++){Fixture f;auto t=f.Job();if(invalid==0)f.source.items.clear();if(invalid==1)f.destination.items={&f.magEntity};
|
||||
if(invalid==2)f.fromSlot.storage=&f.targetStorage;if(invalid==3)f.sourceStorage.owner=&f.foreign;if(invalid==4)f.destination.selected=nullptr;
|
||||
if(invalid==5)f.targetStorage.owner=&f.foreign;if(invalid==6)f.source.allow=false;if(invalid==7)f.destination.storages.clear();if(invalid==8){for(int i=0;i<65;i++)f.destination.storages.Insert(&f.targetStorage);}
|
||||
assert(t.Tick(0)==FAILED&&f.source.calls==0);}
|
||||
// Conditions and original native driver/ledger identities remain strict while an accepted move is pending.
|
||||
for(int changed=0;changed<4;changed++){Fixture f;auto t=f.Job();t.Tick(100);Record replacement=f.recipientRecord;
|
||||
if(changed==0)f.pilot.occupant=&f.spareDriver;if(changed==1)f.ledger.records[1]=&replacement;if(changed==2)f.physics.velocity.x=1;if(changed==3)f.recipient.position.x=8;
|
||||
assert(t.Tick(101)==FAILED&&t.Unresolved());f.source.last->OnFailed();assert(!t.Unresolved()&&f.source.calls==1);}
|
||||
{Fixture f;auto t=f.Job();t.Tick(100);assert(t.Tick(99)==FAILED&&t.Unresolved());}
|
||||
// Clothing storage ownership follows native inventory slots and bounds cycles.
|
||||
{Fixture f;Entity vest;Item vestItem;Slot vestSlot;Storage body;body.owner=&f.recipient;vestSlot.storage=&body;vestItem.slot=&vestSlot;vest.item=&vestItem;f.targetStorage.owner=&vest;
|
||||
auto t=f.Job();assert(t.Tick(0)==PENDING);f.Move();f.source.last->OnComplete();assert(t.Tick(1)==SUCCEEDED);
|
||||
vestSlot.storage=&f.targetStorage;assert(!ERR_InfantryAmmoTransfer::StoredUnder(&vest,&f.recipient));}
|
||||
}
|
||||
'''
|
||||
# Brace tiny fixture statements to retain -Werror without suppressing useful compiler diagnostics.
|
||||
main=re.sub(r'if\((invalid|changed|failure)==(\d+)\)([^;{}]+);',r'if(\1==\2){\3;}',main)
|
||||
main=main.replace('for(int i=0;i<10;i++)t.Tick(8200+i);','for(int i=0;i<10;i++){t.Tick(8200+i);}')
|
||||
run(pre+translated_reservation()+code+'\n'.join(callbacks)+main)
|
||||
print('PASS: actual bounded empty-return and finite delivery; phase-isolated callbacks, exact ownership proof, stop quarantine and original actor/vehicle boundaries')
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
"""Actual coordinator decisions/transitions with native boundaries doubled; no engine proof."""
|
||||
import os,re,sys
|
||||
from pathlib import Path
|
||||
REPO=Path(os.environ.get('ERR_REPO','/home/jakub/devel/escapistsrereintroduced'))
|
||||
sys.path.insert(0,str(REPO/'tests'))
|
||||
from policy_harness import body,run
|
||||
SOURCE=Path(os.environ.get('ERR_INFANTRY_RESUPPLY_SOURCE',REPO/'addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c'))
|
||||
def method(signature):
|
||||
s=body(SOURCE,signature).replace('protected ','').replace('null','nullptr')
|
||||
s=s.replace('vector.DistanceXZ','Vec::DistanceXZ').replace('ERR_ForceRules.','ERR_ForceRules::').replace('ERR_InfantryResupplyRules.','ERR_InfantryResupplyRules::').replace('ERR_Actors.','ERR_Actors::')
|
||||
s=s.replace(' + "3 0 0"',' + Vec{3,0,0}')
|
||||
s=re.sub(r'string\.Format\("walk to reported stopped ammo truck at %1", m_Rendezvous\)', '"rendezvous"', s)
|
||||
for kind in ['ERR_HQWatchEntry','Physics']:
|
||||
s=re.sub(r'\b'+kind+r' (\w+)',kind+r'* \1',s)
|
||||
# Enforce native entity/reference member access becomes C++ pointer member access.
|
||||
for name in ['entry','recipient','donor','stopped','m_HQ','m_Move','m_MineMove','m_Mounted','m_Recipient','m_Donor','m_Truck','m_Order','physics']:
|
||||
s=s.replace(name+'.',name+'->')
|
||||
for name in ['AmmoState','Group','Combat','Entity']:
|
||||
s=s.replace(name+'.',name+'->')
|
||||
s=s.replace('Watch().','Watch()->').replace('GetVelocity().','GetVelocity().').replace('GetAngularVelocity().','GetAngularVelocity().')
|
||||
return s
|
||||
rules='\n'.join(method(x) for x in ['static bool Fresh','static bool Need','static bool Pair'])
|
||||
methods='\n'.join(method(x) for x in ['protected void PollTransfers','protected void ClearWaypoints','protected void Finish','void Tick(float now)','void Stop()'])
|
||||
code=r'''
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
using string=std::string;
|
||||
struct Vec {float x=0,y=0,z=0; float Length(){return std::sqrt(x*x+y*y+z*z);} static float DistanceXZ(Vec a,Vec b){return std::hypot(a.x-b.x,a.z-b.z);} Vec operator+(Vec b){return {x+b.x,y+b.y,z+b.z};} string ToString(){return "position";}};
|
||||
struct ERR_ForceRules {static bool Finite(float n){return std::isfinite(n);} static bool FiniteVector(Vec v){return Finite(v.x)&&Finite(v.y)&&Finite(v.z);}};
|
||||
struct Ammo {bool Complete=true,valid=true;int Members=2,SmallArmsMuzzles=2,SmallArmsRounds=60,SmallArmsChambers=0;bool Valid(int){return valid;}};
|
||||
struct ERR_HQWatchEntry {bool Closed=false;int Count=2,Fit=2,SourceId=1;float ObservedAt=0;Vec Position;Ammo* AmmoState=nullptr;};
|
||||
struct ERR_InfantryResupplyRules {
|
||||
RULES
|
||||
};
|
||||
struct Waypoint {int id;};
|
||||
struct Group {std::vector<Waypoint*> points;void RemoveWaypoint(Waypoint* p){points.erase(std::remove(points.begin(),points.end(),p),points.end());}};
|
||||
struct ERR_Actors {static inline int deleted=0;static void DeleteSpawned(Waypoint*){deleted++;}};
|
||||
struct Physics {Vec linear,angular;Vec GetVelocity(){return linear;} Vec GetAngularVelocity(){return angular;}};
|
||||
struct Entity {Physics* physics=nullptr;Physics* GetPhysics(){return physics;}};
|
||||
struct Combat {bool Held=false;};
|
||||
struct Truck {int SupplyToken=7,clears=0;bool SupplyHeld=false;struct Combat* Combat=nullptr;struct Entity* Entity=nullptr;void ClearOrder(){clears++;}};
|
||||
struct Unit {struct Group* Group=nullptr;int ForceSourceId=1;float NextStatus=-1;};
|
||||
struct Leaf {int stops=0;bool unresolved=true;void Stop(){stops++;}bool Unresolved(){return unresolved;}};
|
||||
struct Mounted{bool busy=false;int ticks=0,stops=0;bool Busy(){return busy;}void Tick(float){ticks++;}void Stop(){stops++;}};
|
||||
struct Route {int result=0,advances=0;int Advance(float,int){advances++;return result;}};
|
||||
struct Watch {ERR_HQWatchEntry* entry=nullptr;ERR_HQWatchEntry* Find(int){return entry;}};
|
||||
struct HQ {int token=7,releases=0,downlinks=0;struct Watch watch;Route* next=nullptr;int Journal(){return 0;}int LogisticsToken(Group*){return token;}void ReleaseLogistics(Group*,int owned){releases++;if(token==owned)token=0;}struct Watch* Watch(){return &watch;} Route* Downlink(Group*,string,string,int){downlinks++;return next;}};
|
||||
struct Service {
|
||||
HQ* m_HQ;Truck* m_Truck;Unit* m_Recipient;Unit* m_Donor;Leaf* m_Move=nullptr;Leaf*m_MineMove=nullptr;bool m_MineTrip=false,m_LauncherTrip=false;int m_MineRecipientSlot=-1;Mounted*m_Mounted=nullptr;Route* m_Order=nullptr;Entity* m_Receiving=nullptr;
|
||||
Waypoint* m_MoveWaypoint=nullptr;Waypoint* m_HoldWaypoint=nullptr;Vec m_Rendezvous;int m_State=2,m_Token=7,m_ReportId=11;
|
||||
float m_NextTick=0,m_Deadline=200000,m_HeldAt=-1;bool m_Stopped=false,valid=true,quiet=true,roster=true,waypoints=true;int audits=0,transfers=0,waypointCalls=0,stocks=0;
|
||||
bool Current(){return !m_Stopped;}bool TruckValid(){return valid;}bool Quiet(Unit*){return quiet;}bool Roster(){return roster;}void Audit(string){audits++;}void Stock(float){stocks++;}bool Waypoints(){waypointCalls++;return waypoints;}void Transfer(float){transfers++;}int mineTransfers=0;void TransferMine(float){mineTransfers++;}
|
||||
METHODS
|
||||
};
|
||||
struct Fixture {Physics physics;Entity entity{&physics};Combat combat;Truck truck;Group group,donorGroup;Unit recipient{&group},donor{&donorGroup};HQ hq;Route order,next;Service s;
|
||||
Fixture(){truck.Combat=&combat;truck.Entity=&entity;s.m_HQ=&hq;s.m_Truck=&truck;s.m_Recipient=&recipient;s.m_Donor=&donor;s.m_Order=ℴhq.next=&next;}
|
||||
};
|
||||
int main(){
|
||||
{Fixture f;Leaf leaf;f.s.m_Move=&leaf;f.s.m_LauncherTrip=true;f.truck.SupplyHeld=true;f.s.Stop();assert(f.s.m_State==7&&f.hq.token==7&&f.truck.SupplyHeld);
|
||||
f.s.Tick(200000);assert(f.s.m_State==7&&f.hq.token==7&&f.s.transfers==0);leaf.unresolved=false;f.s.Tick(201000);assert(f.s.m_State==1&&f.hq.token==0&&!f.truck.SupplyHeld&&!f.s.m_Move);}
|
||||
|
||||
{Fixture f;Leaf leaf;f.s.m_MineMove=&leaf;f.s.m_MineTrip=true;f.truck.SupplyHeld=true;f.s.Stop();assert(f.s.m_State==7&&f.hq.token==7&&f.truck.SupplyHeld&&f.s.m_Recipient);
|
||||
f.s.Tick(200000);assert(f.hq.token==7&&f.s.m_State==7&&f.s.transfers==0&&f.s.mineTransfers==0);leaf.unresolved=false;f.s.Tick(201000);assert(f.hq.token==0&&!f.truck.SupplyHeld&&f.s.m_State==1&&!f.s.m_MineMove);}
|
||||
{Fixture f;f.s.m_State=5;f.s.m_MineTrip=true;f.s.Tick(0);assert(f.s.mineTransfers==1&&f.s.transfers==0);}
|
||||
|
||||
Ammo ammo;ERR_HQWatchEntry demand,donor;demand.AmmoState=&ammo;donor.SourceId=2;donor.Position={200,500,0};
|
||||
assert(ERR_InfantryResupplyRules::Need(&demand,120000));assert(ERR_InfantryResupplyRules::Pair(&demand,&donor,120000));
|
||||
assert(!ERR_InfantryResupplyRules::Fresh(&demand,120001));assert(!ERR_InfantryResupplyRules::Fresh(nullptr,0));
|
||||
demand.ObservedAt=1;assert(!ERR_InfantryResupplyRules::Fresh(&demand,0));demand.ObservedAt=0;
|
||||
ammo.SmallArmsChambers=1;assert(!ERR_InfantryResupplyRules::Need(&demand,0));ammo.SmallArmsChambers=0;
|
||||
ammo.Complete=false;assert(!ERR_InfantryResupplyRules::Need(&demand,0));ammo.Complete=true;
|
||||
ammo.Members=1;assert(!ERR_InfantryResupplyRules::Need(&demand,0));ammo.Members=2;
|
||||
ammo.valid=false;assert(!ERR_InfantryResupplyRules::Need(&demand,0));ammo.valid=true;
|
||||
donor.SourceId=1;assert(!ERR_InfantryResupplyRules::Pair(&demand,&donor,0));donor.SourceId=2;donor.Position.x=201;assert(!ERR_InfantryResupplyRules::Pair(&demand,&donor,0));
|
||||
demand.Position.x=std::numeric_limits<float>::quiet_NaN();assert(!ERR_InfantryResupplyRules::Need(&demand,0));demand.Position.x=0;
|
||||
{Fixture f;f.s.Tick(0);assert(f.s.m_State==2&&!f.truck.SupplyHeld&&f.truck.clears==0&&f.s.waypointCalls==0);f.order.result=1;f.s.Tick(1000);assert(f.s.m_State==3&&f.truck.SupplyHeld&&f.truck.clears==1&&f.s.m_Order==nullptr);f.physics.linear.x=1;f.s.Tick(2000);assert(f.s.m_HeldAt==-1&&f.donor.NextStatus==-1);f.physics.linear.x=0;f.s.Tick(3000);assert(f.s.m_HeldAt==3000&&f.donor.NextStatus==3000);ERR_HQWatchEntry report;report.Position={20,0,5};report.ObservedAt=2999;f.hq.watch.entry=&report;f.s.Tick(4000);assert(f.hq.downlinks==0);report.ObservedAt=3000;f.s.Tick(5000);assert(f.s.m_State==4&&f.hq.downlinks==1&&f.s.m_Rendezvous.x==23);f.s.Tick(6000);assert(f.s.m_State==4&&f.s.waypointCalls==0&&f.s.transfers==0);f.next.result=1;f.s.Tick(7000);assert(f.s.m_State==5&&f.s.waypointCalls==1&&f.s.transfers==1);}
|
||||
{Fixture f;f.order.result=-1;f.s.Tick(0);assert(f.s.m_State==1&&f.hq.token==0&&f.truck.SupplyToken==0&&!f.truck.SupplyHeld&&f.truck.clears==0);}
|
||||
{Fixture f;f.s.m_State=4;f.order.result=-1;f.s.Tick(0);assert(f.s.waypointCalls==0&&f.s.transfers==0&&f.hq.token==0);}
|
||||
{Fixture f;f.hq.token=99;f.truck.SupplyToken=99;f.truck.SupplyHeld=true;f.s.Tick(0);assert(f.s.m_State==1&&f.hq.token==99&&f.truck.SupplyToken==99&&f.truck.SupplyHeld);}
|
||||
{Fixture f;Waypoint own1{1},own2{2},other{3};f.group.points={&own1,&other,&own2};f.s.m_MoveWaypoint=&own1;f.s.m_HoldWaypoint=&own2;Leaf leaf;f.s.m_Move=&leaf;f.truck.SupplyHeld=true;f.s.Stop();assert(f.group.points.size()==1&&f.group.points[0]==&other&&leaf.stops==1&&f.s.m_Move==&leaf&&f.hq.token==7&&f.truck.SupplyHeld&&f.s.m_State==7&&f.s.m_Stopped);int audits=f.s.audits;f.s.Stop();f.s.Tick(5000);assert(f.s.audits==audits&&leaf.stops==1);leaf.unresolved=false;f.s.Tick(6000);assert(f.hq.token==0&&!f.truck.SupplyHeld&&f.s.m_State==1&&!f.s.m_Move);}
|
||||
{Fixture f;Leaf leaf;f.s.m_Move=&leaf;f.s.Finish("timeout");f.s.Tick(0);assert(f.s.m_Move==&leaf);leaf.unresolved=false;f.s.Tick(1000);assert(f.s.m_Move==nullptr);}
|
||||
{Fixture f;f.s.m_State=3;f.physics.linear.x=std::numeric_limits<float>::quiet_NaN();f.s.Tick(0);assert(f.s.m_HeldAt==-1&&f.donor.NextStatus==-1);}
|
||||
{Fixture f;f.s.m_State=3;f.physics.angular.x=std::numeric_limits<float>::quiet_NaN();f.s.Tick(0);assert(f.s.m_HeldAt==-1&&f.donor.NextStatus==-1);}
|
||||
{Fixture f;f.s.m_Deadline=0;f.s.Tick(0);assert(f.s.m_State==1&&f.order.advances==0&&f.hq.token==0);}
|
||||
// Waiting for physical transfer never extends the original bounded rendezvous deadline.
|
||||
{Fixture f;f.s.m_State=5;f.s.m_Deadline=1000;f.s.Tick(0);assert(f.s.transfers==1&&f.s.m_State==5);
|
||||
f.s.Tick(1000);assert(f.s.transfers==1&&f.s.m_State==1&&f.hq.token==0&&!f.truck.SupplyHeld);}
|
||||
|
||||
{Fixture f;f.s.quiet=false;f.order.result=1;f.s.Tick(0);assert(f.s.m_State==1&&f.order.advances==0&&!f.truck.SupplyHeld);}
|
||||
{Fixture f;f.s.m_State=4;f.order.result=1;f.s.waypoints=false;f.s.Tick(0);assert(f.s.m_State==1&&f.s.waypointCalls==1&&f.s.transfers==0&&f.hq.token==0);}
|
||||
{Fixture f;f.s.m_State=3;f.s.m_HeldAt=100;ERR_HQWatchEntry report;report.ObservedAt=100;f.hq.watch.entry=&report;f.hq.next=nullptr;f.s.Tick(1000);assert(f.s.m_State==1&&f.hq.downlinks==1&&f.s.waypointCalls==0&&f.hq.token==0);}
|
||||
|
||||
}
|
||||
'''.replace('RULES',rules).replace('METHODS',methods)
|
||||
run(code)
|
||||
print('infantry resupply actual rules, radio transitions, owned cleanup and unresolved-operation tests passed')
|
||||
|
||||
# Recheck permanent initial-roster eligibility during an active trip.
|
||||
src=SOURCE
|
||||
s=body(src,'protected bool Roster()').replace('protected ','')
|
||||
s=s.replace('array<AIAgent> agents = {};','Array<Agent*> agents;')
|
||||
s=s.replace('foreach (AIAgent agent : agents)','for (Agent* agent : agents)').replace('foreach (IEntity actor : m_Members)','for (Actor* actor : m_Members)')
|
||||
for x in ['m_Recipient','agent']:s=s.replace(x+'.',x+'->')
|
||||
s=s.replace('StatusSampler.','StatusSampler->').replace('Group.','Group->')
|
||||
for x in ['ERR_Actors','SCR_FactionManager','CompartmentAccessComponent']:s=s.replace(x+'.',x+'::')
|
||||
s=s.replace('m_Mode.','m_Mode->').replace('bool living;', 'bool living = false;')
|
||||
run(r'''
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
template<class T> struct Array:std::vector<T>{using std::vector<T>::vector;bool IsEmpty(){return this->empty();}int Count(){return this->size();}bool Contains(T a){return std::find(this->begin(),this->end(),a)!=this->end();}};
|
||||
struct Group;
|
||||
struct Actor{bool alive=true,player=false,fight=true;Group* group=nullptr;int faction=1;};
|
||||
struct Agent{Actor* actor;Actor* GetControlledEntity(){return actor;}};
|
||||
struct Group{Array<Agent*> agents;void GetAgents(Array<Agent*>& out){out=agents;}};
|
||||
struct Sampler{Group* group;bool released=false;int strength=1;Array<Actor*> original;int InitialStrength(){return strength;}Actor* InitialMember(int slot){return slot>=0&&slot<(int)original.size()?original[slot]:nullptr;}bool OwnsRoster(Group* g){return g==group;}bool CanAttribute(int,Actor*){return !released;}};
|
||||
struct Unit{struct Group* Group;Sampler* StatusSampler;};
|
||||
struct Mode{int EnemyFaction(){return 1;}};
|
||||
struct ERR_Actors{static bool Alive(Actor* a){return a->alive;}static bool Player(Actor* a){return a->player;}static struct Group* Group(Actor* a){return a->group;}static bool CanFight(Actor* a){return a->fight;}};
|
||||
struct SCR_FactionManager{static int SGetFaction(Actor* a){return a->faction;}};
|
||||
struct CompartmentAccessComponent{static bool GetVehicleIn(Actor*){return false;}};
|
||||
struct Service{Unit* m_Recipient;Mode* m_Mode;Array<Actor*> m_Members;bool Quiet(Unit*){return true;}
|
||||
METHOD
|
||||
};
|
||||
int main(){
|
||||
Group group;Actor soldier;soldier.group=&group;Agent agent{&soldier};group.agents={&agent};Sampler sampler{&group,false,1,{&soldier}};Unit unit{&group,&sampler};Mode mode;Service service{&unit,&mode,{&soldier}};assert(service.Roster());sampler.released=true;assert(!sampler.CanAttribute(0,&soldier));
|
||||
// Permanent sampler release survives returning to the physical group.
|
||||
assert(!service.Roster());sampler.released=false;assert(service.Roster());
|
||||
sampler.strength=33;assert(!service.Roster());sampler.strength=0;assert(!service.Roster());sampler.strength=1;
|
||||
Actor foreign;foreign.group=&group;sampler.original={&foreign};assert(!service.Roster());
|
||||
// Initial roster order, not current GetAgents order, determines the slot.
|
||||
sampler.strength=2;sampler.original={&foreign,&soldier};assert(service.Roster());
|
||||
soldier.player=true;assert(!service.Roster());soldier.player=false;
|
||||
soldier.group=nullptr;assert(!service.Roster());soldier.group=&group;
|
||||
soldier.alive=false;assert(!service.Roster());soldier.alive=true;
|
||||
Agent extra{&foreign};group.agents.push_back(&extra);assert(!service.Roster());
|
||||
}
|
||||
'''.replace('METHOD',s))
|
||||
print('PASS: actual resupply Roster preserves permanent release, original slot mapping and bounded ownership')
|
||||
+304
@@ -0,0 +1,304 @@
|
||||
"""Execute real finite-stock/planning/reservation bodies; native inventory/group APIs are doubles."""
|
||||
import os,re
|
||||
from pathlib import Path
|
||||
from policy_harness import ROOT,body,run
|
||||
P=Path(os.environ.get('ERR_INFANTRY_RESUPPLY_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c'))
|
||||
A=Path(os.environ.get('ERR_INFANTRY_TRANSFER_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoTransfer.c'))
|
||||
I=ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_Inventory.c'
|
||||
H=Path(os.environ.get('ERR_HQ_SOURCE',ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_HQ.c'))
|
||||
def cpp(s):
|
||||
s=s.replace('protected ','').replace('notnull ','').replace('null','nullptr')
|
||||
s=s.replace('map<string, int>', 'Map<int>*').replace('map<string, float>', 'Map<float>*')
|
||||
s=s.replace('array<IEntity> items = {};','Array<IEntity> items;').replace('array<IEntity> raw = {};','Array<IEntity> raw;').replace('array<AIAgent> agents = {};','Array<AIAgent> agents;')
|
||||
s=s.replace('out array<IEntity> items','Array<IEntity>& items').replace('array<IEntity> items','Array<IEntity>& items')
|
||||
s=re.sub(r'foreach \((\w+) (\w+) : ([^)]+)\)',r'for (\1 \2 : \3)',s)
|
||||
for typ in ('InventoryStorageManagerComponent','ERR_ForceRecord','ERR_SupplyConvoyTask'):
|
||||
s=re.sub(r'\b'+typ+r' (?=\w)',typ+'* ',s)
|
||||
for name in ('ERR_ForceRules','ERR_InfantryResupplyRules','ERR_InfantryMineTransfer','ERR_InfantryAmmoTransfer','ERR_ConvoyRules','ERR_ForceKind','ERR_ConvoyResources','ERR_Inventory','ERR_Actors','SCR_FactionManager','CompartmentAccessComponent','Replication','Math'):
|
||||
s=s.replace(name+'.',name+'::')
|
||||
s=s.replace('ERR_SupplyConvoyTask.Cast','ERR_SupplyConvoyTask::Cast').replace('FindComponent(BaseMagazineComponent)','HasMagazine()')
|
||||
s=s.replace('vector.DistanceXZ','Vec::DistanceXZ').replace('InventoryStorageManagerComponent.Cast','InventoryStorageManagerComponent::Cast').replace('FindComponent(InventoryStorageManagerComponent)','FindComponent()')
|
||||
for name in ('m_Mode','m_HQ','m_Convoy','m_Truck','m_Recipient','m_Donor','m_Move','m_MineMove','m_MineBatch','m_Mounted','recipient','donor','demand','donorStatus','entry','operation','inventory','item','owner','record','actor','agent','unit','m_MoveWaypoint','m_HoldWaypoint','magazine','supply','m_Consumed','m_NextAttempt'):
|
||||
s=s.replace(name+'.',name+'->')
|
||||
for name in ('Receipt','Entity','Group','Utility','StatusSampler','AmmoState','Combat','m_Perception'):
|
||||
s=s.replace(name+'.',name+'->')
|
||||
for name in ('Forces()','GetPrefabData()','Convoys()'):s=s.replace(name+'.',name+'->')
|
||||
s=s.replace('ERR_SupplyConvoyTask* supply', 'Convoy* supply')
|
||||
s=s.replace('bool designated;','bool designated=false;')
|
||||
s=s.replace('int checks;', 'int checks=0;')
|
||||
s=s.replace('bool available;','bool available=false;').replace('bool living;','bool living=false;')
|
||||
return s
|
||||
rules='\n'.join(cpp(body(P,x)) for x in ('static bool Fresh(', 'static bool Need(', 'static bool Pair(', 'static bool MinePair(', 'static bool LauncherNeed(', 'static bool LauncherPair('))
|
||||
stock_method=('protected bool CompatibleStock(',) if 'protected bool CompatibleStock(' in P.read_text() else ()
|
||||
methods='\n'.join(cpp(body(P,x)) for x in stock_method+('bool Bind(', 'ERR_ConvoyTask Task(', 'protected bool ConvoyCurrent(', 'protected bool Contains(', 'protected bool TruckValid(', 'protected bool Quiet(', 'protected bool Roster(', 'protected void Stock(', 'protected bool CaptureMines(', 'protected bool LauncherStock(', 'bool TryPlanLauncher(', 'bool TryPlanMines(', 'bool TryPlan(', 'protected void ClearWaypoints(', 'protected void Finish(', 'void Stop('))
|
||||
reserve=cpp(body(H,'bool ReserveLogistics('))+cpp(body(H,'void ReleaseLogistics('))
|
||||
unique=cpp(body(I,'static int AppendUnique('))+cpp(body(I,'static int Items('))
|
||||
compatible=body(A,'static bool Compatible(')
|
||||
for a,b in {
|
||||
'BaseMagazineComponent.Cast(exactMagazine.FindComponent(BaseMagazineComponent))':'exactMagazine->ammoComp',
|
||||
'BaseWeaponManagerComponent.Cast(actor.FindComponent(BaseWeaponManagerComponent))':'actor->weapons',
|
||||
'BaseWeaponComponent.Cast(rifle.FindComponent(BaseWeaponComponent))':'rifle->weapon',
|
||||
'InventoryItemComponent.Cast(loaded.GetOwner().FindComponent(InventoryItemComponent))':'loaded->GetOwner()->item',
|
||||
'SCR_MuzzleInMagComponent.Cast(muzzle)':'(muzzle->inMag ? muzzle : nullptr)',
|
||||
}.items():compatible=compatible.replace(a,b)
|
||||
compatible=compatible.replace('array<','Array<').replace('foreach (','for (').replace('EWeaponType kind','int kind').replace('EMuzzleType muzzleKind','int muzzleKind')
|
||||
for a in ['EWeaponType','EMuzzleType']:compatible=compatible.replace(a+'.',a+'::')
|
||||
for a in ['magazine','manager','weapon','muzzle','reloadable','loaded','loadedItem','loadedSlot']:compatible=compatible.replace(a+'.',a+'->')
|
||||
compatible=compatible.replace('GetMagazineWell().','GetMagazineWell()->')
|
||||
run(r'''
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
using string=std::string;
|
||||
template<class T>struct Array:std::vector<T>{using std::vector<T>::vector;int Count(){return this->size();}bool IsEmpty(){return this->empty();}void Clear(){this->clear();}void Insert(T v){this->push_back(v);}bool Contains(T v){return std::find(this->begin(),this->end(),v)!=this->end();}};
|
||||
template<class V>struct Map{std::map<string,V>data;V Get(string k){auto it=data.find(k);return it==data.end()?V{}:it->second;}void Set(string k,V v){data[k]=v;}};
|
||||
struct Vec{float x=0,y=0,z=0;static float DistanceXZ(Vec a,Vec b){return std::hypot(a.x-b.x,a.z-b.z);}};
|
||||
struct ERR_ForceRules{static bool Finite(float f){return std::isfinite(f);}static bool FiniteVector(Vec v){return Finite(v.x)&&Finite(v.y)&&Finite(v.z);}};
|
||||
struct Math{static float Min(float a,float b){return std::min(a,b);}};
|
||||
struct Replication{static inline bool server=true;static bool IsServer(){return server;}};
|
||||
struct Entity;using IEntity=Entity*;
|
||||
struct Magazine;struct Manager;struct Weapon;struct Muzzle;struct Item;struct Slot;
|
||||
using BaseMagazineComponent=Magazine*;using BaseWeaponManagerComponent=Manager*;using BaseWeaponComponent=Weapon*;using BaseMuzzleComponent=Muzzle*;using SCR_MuzzleInMagComponent=Muzzle*;using InventoryItemComponent=Item*;using InventoryStorageSlot=Slot*;
|
||||
struct EWeaponType{static const int WT_RIFLE=1,WT_SNIPERRIFLE=2,WT_MACHINEGUN=3,WT_HANDGUN=4,WT_GRENADELAUNCHER=5,WT_ROCKETLAUNCHER=6;};
|
||||
struct EMuzzleType{static const int MT_BaseMuzzle=0,MT_UGLMuzzle=1,MT_RPGMuzzle=2;};
|
||||
struct Well{int type=1,parent=0;int Type(){return type;}bool IsInherited(int t){return type==t||parent==t;}};
|
||||
struct Magazine{IEntity owner=nullptr;Well*well=nullptr;int rounds=30,capacity=30;bool used=false;IEntity GetOwner(){return owner;}Well*GetMagazineWell(){return well;}int GetAmmoCount(){return rounds;}int GetMaxAmmoCount(){return capacity;}bool IsUsed(){return used;}};
|
||||
struct Muzzle{bool inMag=true,canReload=true,disposable=false;Magazine*loaded=nullptr;Well*well=nullptr;int kind=0;bool CanBeReloaded(){return canReload;}bool IsDisposable(){return disposable;}Magazine*GetMagazine(){return loaded;}Well*GetMagazineWell(){return well;}int GetMuzzleType(){return kind;}};
|
||||
struct Weapon{IEntity owner=nullptr;Array<Muzzle*>muzzles;int kind=1;IEntity GetOwner(){return owner;}int GetWeaponType(){return kind;}void GetMuzzlesList(Array<Muzzle*>&a){a=muzzles;}};
|
||||
struct Manager{Array<IEntity>weapons;void GetWeaponsList(Array<IEntity>&a){a=weapons;}};
|
||||
struct Slot{Muzzle*container=nullptr;IEntity attached=nullptr;Muzzle*GetParentContainer(){return container;}IEntity GetAttachedEntity(){return attached;}};
|
||||
struct Item{Slot*slot=nullptr;Slot*GetParentSlot(){return slot;}};
|
||||
struct InventoryStorageManagerComponent{Array<IEntity>items;void GetItems(Array<IEntity>& out){out=items;}static auto Cast(InventoryStorageManagerComponent* p){return p;}};
|
||||
struct Prefab{string name="magazine";string GetPrefabName(){return name;}};
|
||||
struct Group;using SCR_AIGroup=Group*;
|
||||
struct Entity{Magazine*ammoComp=nullptr;Manager*weapons=nullptr;Weapon*weapon=nullptr;Item*item=nullptr;IEntity parent=nullptr;Prefab prefab;bool readyMine=false,magazine=true,hasPrefab=true,alive=true,player=false,fight=true,aboard=false,captured=false,released=false;int faction=1;Group* group=nullptr;InventoryStorageManagerComponent* inventory=nullptr;bool HasMagazine(){return magazine;}Prefab* GetPrefabData(){return hasPrefab?&prefab:nullptr;}InventoryStorageManagerComponent* FindComponent(){return inventory;}};
|
||||
struct Agent{IEntity actor;IEntity GetControlledEntity(){return actor;}};using AIAgent=Agent*;
|
||||
struct Waypoint{};
|
||||
struct Group{Array<AIAgent>agents;bool slave=false;int players=0,faction=1;bool IsSlave(){return slave;}int GetPlayerCount(bool){return players;}int GetFaction(){return faction;}void GetAgents(Array<AIAgent>& out){out=agents;}void RemoveWaypoint(Waypoint*){}};
|
||||
struct ERR_Actors{static bool Alive(IEntity a){return a&&a->alive;}static bool Player(IEntity a){return a&&a->player;}static SCR_AIGroup Group(IEntity a){return a->group;}static bool CanFight(IEntity a){return a&&a->alive&&a->fight;}static void DeleteSpawned(Waypoint*){}};
|
||||
struct SCR_FactionManager{static int SGetFaction(IEntity a){return a->faction;}};
|
||||
struct CompartmentAccessComponent{static bool GetVehicleIn(IEntity a){return a->aboard;}};
|
||||
struct ERR_Inventory{
|
||||
'''+unique+r'''
|
||||
};
|
||||
struct Ammo{bool LauncherComplete=true;int LauncherMuzzles=1,LauncherMagazines=1,LauncherRounds=0,LauncherChambers=0;bool MineComplete=true;int MineMembers=2,ReadyMines=1;bool Complete=true;int Members=2,SmallArmsMuzzles=2,SmallArmsRounds=60,SmallArmsChambers=0;bool Valid(int n){return Members==n;}};
|
||||
struct Entry{bool Closed=false;int Count=2,Fit=2,MessageId=1;float ObservedAt=0;Vec Position;string SourceId;Ammo* AmmoState=nullptr;};using ERR_HQWatchEntry=Entry*;
|
||||
struct ERR_InfantryResupplyRules{
|
||||
'''+rules+r'''
|
||||
};
|
||||
namespace ERR_ForceKind{const int CONVOY=3;}
|
||||
struct ERR_ForceRecord{bool Physical=true,Eliminated=false;int Kind=3,Id=2;};
|
||||
struct Ledger{Group* owned=nullptr;ERR_ForceRecord record;ERR_ForceRecord* FindGroup(Group* g){return g==owned?&record:nullptr;}};
|
||||
struct Mode{Ledger ledger;Ledger* Forces(){return &ledger;}int EnemyFaction(){return 1;}};
|
||||
struct Perception{Array<int>m_aTargets;};
|
||||
struct Utility{Perception* m_Perception=nullptr;};
|
||||
struct Sampler{Group* group;Array<IEntity>original;int InitialStrength(){return original.Count();}IEntity InitialMember(int i){return original[i];}bool CanAttribute(int i,IEntity a){return original[i]==a&&!a->released;}bool OwnsRoster(Group* g){return g==group;}};
|
||||
struct Unit{struct Group* Group=nullptr;struct Utility* Utility=nullptr;Sampler* StatusSampler=nullptr;string ForceSourceId;bool HomeGuard=false,eligible=true;int LogisticsReservation=0;void* Downlink=nullptr;void* PendingOrder=nullptr;void* PendingConvoyOrder=nullptr;void* Radio=this;void* Assignment=nullptr;void* Waypoint=nullptr;bool Eligible(Mode*){return eligible&&LogisticsReservation==0;}};using ERR_HQUnit=Unit*;
|
||||
struct Combat{bool Held=false;};
|
||||
struct Truck{int Index=1,SupplyToken=0;bool Registered=true,Released=false,Arrived=false,SupplyHeld=false,crew=true;struct Entity* Entity=nullptr;struct Group* Group=nullptr;struct Combat* Combat=nullptr;bool CrewValid(Mode*){return crew;}};
|
||||
struct Receipt{bool Consumed=true;Array<int>Records={1,2,3,4,5,6};};
|
||||
struct Cargo{bool Finished=true;};using ERR_ConvoyCargoCallback=Cargo*;
|
||||
struct MineBatch{bool complete=true;Array<IEntity>items;bool Complete(){return complete;}int Count(){return items.Count();}IEntity At(int i){return items[i];}};
|
||||
struct Convoy{MineBatch*MineStock=nullptr;bool supply=false,MagazinesIssued=true,CargoIssued=true,Stopped=false,Ready=true;struct Receipt* Receipt=nullptr;Array<Truck*>Vehicles;Array<struct Cargo*>Cargo;float Deadline=30000;};
|
||||
using ERR_ConvoyTask=Convoy*;
|
||||
struct ConvoyService{Array<Convoy*>tasks;int Count(){return tasks.Count();}Convoy* At(int index){return index>=0&&index<Count()?tasks[index]:nullptr;}};
|
||||
struct ERR_SupplyConvoyTask:Convoy{static Convoy* Cast(Convoy* task){return task&&task->supply?task:nullptr;}};
|
||||
struct ERR_ConvoyRules{static bool Captured(Entity* e,Group*){return e->captured;}};
|
||||
struct ERR_ConvoyResources{static string Magazine(){return "magazine";}};
|
||||
struct ERR_InfantryMineTransfer{static bool ReadyMine(IEntity x){return x&&x->readyMine;}};
|
||||
struct Route{};struct Leaf{bool unresolved=false;void Stop(){}bool Unresolved(){return unresolved;}};struct Mounted{bool busy=false;bool Busy(){return busy;}void Stop(){}};
|
||||
struct HQ{Mode* m_Mode;Array<ERR_HQUnit>m_Units;Convoy* convoy=nullptr;ConvoyService convoys;ConvoyService* Convoys(){return &convoys;}Route route;bool active=true,routeAvailable=true;int downlinks=0;bool MissionActive(){return active;}Convoy* ConvoyTask(){return convoy;}
|
||||
bool designated=false;bool MineSupplyReady(Group*,IEntity,bool replacement=false){return !replacement||designated;}
|
||||
Route* Downlink(Group*,string,string,int){downlinks++;return routeAvailable?&route:nullptr;}
|
||||
'''+reserve+r'''
|
||||
};
|
||||
struct ERR_InfantryAmmoTransfer{static bool StoredUnder(IEntity item,IEntity actor){return item&&item->parent==actor;}
|
||||
'''+compatible+r'''
|
||||
};
|
||||
struct Service{HQ* m_HQ;Mode* m_Mode;Convoy* m_Convoy=nullptr;Truck* m_Truck=nullptr;Unit* m_Recipient=nullptr;Unit* m_Donor=nullptr;Leaf* m_Move=nullptr;Leaf*m_MineMove=nullptr;MineBatch*m_MineBatch=nullptr;bool m_LauncherTrip=false,m_MineTrip=false,m_MineStockCaptured=false,m_EmptyMineReplacement=false;int m_MineRecipientSlot=-1;Mounted*m_Mounted=nullptr;Route* m_Order=nullptr;IEntity m_Receiving=nullptr;
|
||||
Array<IEntity>m_Stock,m_MineStock,m_Spent,m_Members,m_Served;Map<int>*m_Consumed=new Map<int>();Map<float>*m_NextAttempt=new Map<float>();int m_ConvoySlot=-1;float m_NextTick=0;int m_State=0,m_Trip=0,m_Token=0,m_ReportId=0,m_TripDelivered=0;float m_Deadline=0,m_StockDeadline=-1;bool m_Stopped=false;
|
||||
Waypoint* m_MoveWaypoint=nullptr;Waypoint* m_HoldWaypoint=nullptr;string reason;bool Current(){return !m_Stopped&&Replication::IsServer()&&m_HQ->active;}void Audit(string why){reason=why;}
|
||||
'''+methods+r'''
|
||||
};
|
||||
struct Fixture{Mode mode;HQ hq;Service s;InventoryStorageManagerComponent inventory;Entity vehicle;std::array<Entity,140>items;std::array<Magazine,140>magazines;Entity rifle,launcher;Manager weapons;Weapon rifleWeapon,launcherWeapon;Muzzle rifleMuzzle,launcherMuzzle;Well well,wrongWell{2,0};Entity one,two;Agent a{&one},b{&two};Group recipients,donors;Utility recipientUtility,donorUtility;Sampler sampler;Unit recipient,donor;Combat combat;Truck truck;Receipt receipt;Cargo cargo;Convoy convoy;Ammo ammo;Entry demand,donorStatus;
|
||||
Fixture():sampler{&recipients,{&one,&two}}{
|
||||
hq.m_Mode=&mode;hq.convoy=&convoy;hq.convoys.tasks={&convoy};s.m_HQ=&hq;s.m_Mode=&mode;
|
||||
one.weapons=&weapons;two.weapons=&weapons;weapons.weapons={&rifle,&launcher};rifle.weapon=&rifleWeapon;rifleWeapon.owner=&rifle;rifleWeapon.muzzles={&rifleMuzzle};rifleMuzzle.well=&well;
|
||||
launcher.weapon=&launcherWeapon;launcherWeapon.owner=&launcher;launcherWeapon.kind=EWeaponType::WT_ROCKETLAUNCHER;launcherWeapon.muzzles={&launcherMuzzle};launcherMuzzle.well=&well;launcherMuzzle.kind=EMuzzleType::MT_RPGMuzzle;launcher.parent=&one;
|
||||
for(int i=0;i<140;i++){items[i].ammoComp=&magazines[i];magazines[i].owner=&items[i];magazines[i].well=&well;}
|
||||
vehicle.inventory=&inventory;vehicle.group=&donors;truck.Entity=&vehicle;truck.Group=&donors;truck.Combat=&combat;
|
||||
mode.ledger.owned=&donors;convoy.Receipt=&receipt;convoy.Vehicles={&truck,&truck,&truck,&truck,&truck,&truck};convoy.Cargo={&cargo};
|
||||
one.group=&recipients;two.group=&recipients;recipients.agents={&a,&b};recipient.Group=&recipients;recipient.Utility=&recipientUtility;recipient.StatusSampler=&sampler;recipient.ForceSourceId="recipient";
|
||||
donor.Group=&donors;donor.Utility=&donorUtility;donor.ForceSourceId="donor";hq.m_Units={&recipient,&donor};
|
||||
demand.SourceId="recipient";demand.AmmoState=&ammo;donorStatus.SourceId="donor";donorStatus.AmmoState=&ammo;
|
||||
for(int i=0;i<48;i++)inventory.items.Insert(&items[i]);
|
||||
}
|
||||
bool Plan(float now=0){return s.TryPlan(&recipient,&donor,&demand,&donorStatus,now);}
|
||||
void Refresh(float now,int id){demand.ObservedAt=now;donorStatus.ObservedAt=now;demand.MessageId=id;}
|
||||
void Unchanged(){assert(s.m_Trip==0&&s.m_Consumed->Get("recipient")==0&&s.m_NextAttempt->Get("recipient")==0&&recipient.LogisticsReservation==0&&truck.SupplyToken==0&&hq.downlinks==0&&!truck.SupplyHeld&&!convoy.Stopped&&!s.m_Recipient&&!s.m_Donor);}
|
||||
};
|
||||
int main(){
|
||||
// Actual Compatible must reject wrong-well, empty or malformed stock before
|
||||
// any report/cooldown consumption, reservation, downlink or convoy hold.
|
||||
for(int bad=0;bad<5;bad++){Fixture f;for(auto&mag:f.magazines){if(bad==0)mag.well=&f.wrongWell;if(bad==1)mag.rounds=0;if(bad==2)mag.capacity=0;if(bad==3)mag.rounds=31;if(bad==4)mag.well=nullptr;}f.s.Stock(0);assert(!f.Plan());f.Unchanged();}
|
||||
{Fixture f;f.s.Stock(0);f.rifleMuzzle.well=&f.wrongWell;assert(!f.Plan());f.Unchanged();f.rifleMuzzle.well=&f.well;assert(f.Plan());}
|
||||
// Same delivered recipient report remains available to a later compatible
|
||||
// truck sharing the real per-source consumption/cooldown maps.
|
||||
{Fixture first,second;Map<int> consumed;Map<float> cooldown;second.hq.convoys.tasks={&first.convoy,&second.convoy};second.hq.convoy=&first.convoy;second.hq.m_Units={&first.recipient,&second.donor};
|
||||
assert(first.s.Bind(&first.convoy,0,&consumed,&cooldown));assert(second.s.Bind(&second.convoy,1,&consumed,&cooldown));
|
||||
for(auto&mag:first.magazines){mag.well=&first.wrongWell;}first.s.Stock(0);second.s.Stock(0);assert(!first.Plan());first.Unchanged();
|
||||
assert(second.s.TryPlan(&first.recipient,&second.donor,&first.demand,&second.donorStatus,0));assert(consumed.Get("recipient")==1&&cooldown.Get("recipient")==180000&&first.recipient.LogisticsReservation==100129&&second.hq.downlinks==1&&first.hq.downlinks==0);}
|
||||
// A usable compatible item must still be a surviving unspent frozen identity.
|
||||
{Fixture f;for(auto&mag:f.magazines)mag.rounds=0;f.magazines[48].rounds=30;f.s.Stock(0);f.inventory.items.Insert(&f.items[48]);assert(!f.Plan());f.Unchanged();f.magazines[0].rounds=30;f.s.m_Spent.Insert(&f.items[0]);assert(!f.Plan());f.Unchanged();f.s.m_Spent.Clear();assert(f.Plan());}
|
||||
// Hard 32 original carriers and 96 captured magazines remain fail-closed.
|
||||
{Fixture f;f.s.Stock(0);f.sampler.original.resize(33,&f.one);assert(!f.Plan());f.Unchanged();}
|
||||
{Fixture f;f.s.Stock(0);for(int i=48;i<97;i++){f.s.m_Stock.Insert(&f.items[i]);f.inventory.items.Insert(&f.items[i]);}assert(!f.Plan());f.Unchanged();}
|
||||
{Fixture f;for(int i=48;i<96;i++)f.inventory.items.Insert(&f.items[i]);for(int i=0;i<95;i++)f.magazines[i].well=&f.wrongWell;f.s.Stock(0);assert(f.Plan());}
|
||||
// Small-arms demand cannot borrow launcher compatibility, but the dedicated
|
||||
// launcher path still supports its real empty reloadable muzzle and rejects disposables.
|
||||
{Fixture f;f.weapons.weapons={&f.launcher};f.s.Stock(0);assert(!f.Plan());f.Unchanged();assert(f.s.TryPlanLauncher(&f.recipient,&f.donor,&f.demand,&f.donorStatus,0));}
|
||||
{Fixture f;f.weapons.weapons={&f.launcher};f.launcherMuzzle.disposable=true;f.s.Stock(0);assert(!f.s.TryPlanLauncher(&f.recipient,&f.donor,&f.demand,&f.donorStatus,0));f.Unchanged();}
|
||||
{Fixture f;for(int i=48;i<96;i++)f.inventory.items.Insert(&f.items[i]);f.s.Stock(0);
|
||||
for(int i=0;i<95;i++)f.magazines[i].well=&f.wrongWell;
|
||||
assert(f.s.TryPlanLauncher(&f.recipient,&f.donor,&f.demand,&f.donorStatus,0));
|
||||
assert(f.s.m_LauncherTrip);}
|
||||
|
||||
{Fixture f;f.s.Stock(0);for(auto&mag:f.magazines)mag.well=&f.wrongWell;assert(!f.s.TryPlanLauncher(&f.recipient,&f.donor,&f.demand,&f.donorStatus,0)&&f.truck.SupplyToken==0);}
|
||||
|
||||
{Fixture f;f.s.Stock(0);f.ammo.SmallArmsRounds=999;f.ammo.LauncherMagazines=0;assert(!f.Plan());assert(f.s.TryPlanLauncher(&f.recipient,&f.donor,&f.demand,&f.donorStatus,0));assert(f.s.m_LauncherTrip&&!f.s.m_MineTrip);}
|
||||
for(int bad=0;bad<7;bad++){Fixture f;f.s.Stock(0);f.ammo.SmallArmsRounds=999;if(bad==0)f.ammo.LauncherComplete=false;if(bad==1)f.ammo.LauncherMuzzles=0;if(bad==2)f.ammo.LauncherRounds=1;if(bad==3)f.ammo.LauncherChambers=1;if(bad==4)f.ammo.Members=1;if(bad==5)f.demand.ObservedAt=-1;if(bad==6)f.demand.ObservedAt=1;
|
||||
assert(!f.s.TryPlanLauncher(&f.recipient,&f.donor,&f.demand,&f.donorStatus,0));assert(f.s.m_State==1&&f.truck.SupplyToken==0);}
|
||||
|
||||
// Additional mounted stock callbacks belong to the same initial freeze barrier.
|
||||
{Fixture f;Cargo mounted;mounted.Finished=false;f.convoy.supply=true;f.convoy.Cargo.Insert(&mounted);
|
||||
f.s.Stock(0);assert(f.s.m_State==0&&f.s.m_Stock.IsEmpty());
|
||||
mounted.Finished=true;f.inventory.items.Insert(&f.items[48]);f.s.Stock(1000);
|
||||
assert(f.s.m_State==1&&f.s.m_Stock.Count()==49&&f.s.m_Stock.Contains(&f.items[48]));}
|
||||
// Bind accepts only an exact current slot and non-null shared demand histories.
|
||||
{Fixture f;Map<int> consumed;Map<float> cooldown;Convoy other;
|
||||
assert(!f.s.Bind(nullptr,0,&consumed,&cooldown));assert(!f.s.Bind(&f.convoy,-1,&consumed,&cooldown));
|
||||
assert(!f.s.Bind(&f.convoy,20,&consumed,&cooldown));assert(!f.s.Bind(&f.convoy,1,&consumed,&cooldown));
|
||||
assert(!f.s.Bind(&other,0,&consumed,&cooldown));assert(!f.s.Bind(&f.convoy,0,nullptr,&cooldown));assert(!f.s.Bind(&f.convoy,0,&consumed,nullptr));
|
||||
assert(f.s.Bind(&f.convoy,0,&consumed,&cooldown));assert(f.s.Task()==&f.convoy);assert(!f.s.Bind(&f.convoy,0,&consumed,&cooldown));}
|
||||
// Any prior startup/stock/trip/stop refuses late binding.
|
||||
for(int began=0;began<6;began++){Fixture f;Map<int> consumed;Map<float> cooldown;
|
||||
if(began==0){f.s.Stock(0);}if(began==1){f.s.m_NextTick=1000;}if(began==2){f.s.m_Trip=1;}
|
||||
if(began==3){f.s.m_StockDeadline=90000;}if(began==4){f.s.m_Stopped=true;}if(began==5){f.s.m_State=1;}
|
||||
assert(!f.s.Bind(&f.convoy,0,&consumed,&cooldown));}
|
||||
// Second convoy remains valid independently of canonical first, but never follows replacement/reordering.
|
||||
for(int mutation=0;mutation<3;mutation++){Fixture f;Convoy first,replacement;Map<int> consumed;Map<float> cooldown;
|
||||
f.hq.convoy=&first;f.hq.convoys.tasks={&first,&f.convoy};assert(f.s.Bind(&f.convoy,1,&consumed,&cooldown));
|
||||
f.s.Stock(0);assert(f.s.TruckValid()&&f.s.Task()==&f.convoy&&f.s.m_Stock.Count()==48);
|
||||
if(mutation==0)f.hq.convoys.tasks[1]=&replacement;
|
||||
if(mutation==1)std::swap(f.hq.convoys.tasks[0],f.hq.convoys.tasks[1]);
|
||||
if(mutation==2)f.hq.convoys.tasks.resize(1);
|
||||
assert(!f.s.TruckValid()&&!f.Plan()&&f.s.Task()==&f.convoy);}
|
||||
// Canonical legacy startup also pins its first identity before readiness.
|
||||
{Fixture f;Convoy replacement;f.convoy.Ready=false;f.s.Stock(0);assert(f.s.Task()==&f.convoy);
|
||||
f.hq.convoy=&replacement;f.s.Stock(1000);assert(f.s.m_Stopped&&f.s.Task()==&f.convoy);}
|
||||
// Every bound slot owns a disjoint 128-trip token range, including its last allowed trip.
|
||||
for(int slot=0;slot<20;slot++){Fixture f;Map<int> consumed;Map<float> cooldown;
|
||||
f.hq.convoys.tasks.resize(slot+1,nullptr);f.hq.convoys.tasks[slot]=&f.convoy;assert(f.s.Bind(&f.convoy,slot,&consumed,&cooldown));
|
||||
f.s.Stock(0);assert(f.Plan());assert(f.s.m_Token==100000+slot*128+1);f.s.Finish("test released");
|
||||
f.s.m_Trip=127;f.Refresh(180000,2);assert(f.Plan(180000));assert(f.s.m_Token==100000+(slot+1)*128);
|
||||
f.s.Finish("test released");f.Refresh(360000,3);assert(!f.Plan(360000));}
|
||||
// Separate convoys share report consumption and failed-attempt cooldowns for the same recipient source.
|
||||
{Fixture first,second;Map<int> consumed;Map<float> cooldown;
|
||||
second.hq.convoys.tasks={&first.convoy,&second.convoy};second.hq.convoy=&first.convoy;
|
||||
assert(first.s.Bind(&first.convoy,0,&consumed,&cooldown));assert(second.s.Bind(&second.convoy,1,&consumed,&cooldown));
|
||||
first.s.Stock(0);second.s.Stock(0);first.hq.routeAvailable=false;assert(first.Plan());
|
||||
assert(consumed.Get("recipient")==1&&cooldown.Get("recipient")==180000);
|
||||
second.Refresh(180000,1);assert(!second.Plan(180000));second.Refresh(179999,2);assert(!second.Plan(179999));
|
||||
second.Refresh(180000,2);assert(second.Plan(180000));assert(first.s.m_Consumed->Get("recipient")==2&&first.s.m_NextAttempt->Get("recipient")==360000);}
|
||||
// Actual inventory aggregation collapses repeated native storage references, not distinct identical-prefab magazines.
|
||||
{Fixture f;f.inventory.items.Insert(&f.items[0]);f.inventory.items.Insert(nullptr);f.s.Stock(0);assert(f.s.m_State==1&&!f.s.m_Stopped&&f.s.m_Stock.Count()==48);assert(f.s.m_Stock[0]!=f.s.m_Stock[1]);}
|
||||
// Malformed/non-magazine items never become spendable stock; native startup partial cargo stays partial.
|
||||
{Fixture f;f.inventory.items={&f.items[0],&f.items[1],&f.items[2],nullptr};f.items[1].magazine=false;f.items[2].magazine=false;f.items[2].prefab.name="rifle";f.s.Stock(0);assert(f.s.m_Stock.Count()==1&&f.s.m_State==1);}
|
||||
{Fixture f;f.cargo.Finished=false;f.s.Stock(0);assert(f.s.m_State==0&&f.s.m_Stock.IsEmpty());f.s.Stock(89999);assert(!f.s.m_Stopped&&f.s.m_Stock.IsEmpty());f.s.Stock(90000);assert(f.s.m_Stopped&&f.s.m_Stock.IsEmpty());}
|
||||
{Fixture f;f.cargo.Finished=false;f.s.Stock(0);f.cargo.Finished=true;f.inventory.items={&f.items[0]};f.s.Stock(1000);assert(f.s.m_Stock.Count()==1&&!f.s.m_Stopped);}
|
||||
{Fixture f;for(int i=48;i<97;i++)f.inventory.items.Insert(&f.items[i]);f.s.Stock(0);assert(f.s.m_Stopped&&!f.Plan());f.Unchanged();}
|
||||
{Fixture f;for(auto& item:f.items)f.inventory.items.Insert(&item);f.s.Stock(0);assert(f.s.m_Stopped&&f.s.m_Stock.IsEmpty());}
|
||||
{Fixture f;f.vehicle.inventory=nullptr;f.s.Stock(0);assert(f.s.m_Stopped&&!f.Plan());}
|
||||
{Fixture f;f.convoy.Ready=false;f.s.Stock(0);assert(f.s.m_State==0&&f.s.m_Stock.IsEmpty());}
|
||||
{Fixture f;f.receipt.Consumed=false;f.s.Stock(0);assert(f.s.m_Stopped&&f.s.m_Stock.IsEmpty());}
|
||||
// Supply weapons settle after crew deadline; matching ammo must be issued and settled before snapshot.
|
||||
{Fixture f;f.convoy.supply=true;f.convoy.MagazinesIssued=false;f.s.Stock(25000);assert(f.s.m_State==0&&f.s.m_Stock.IsEmpty());
|
||||
f.s.Stock(31000);assert(!f.s.m_Stopped&&f.s.m_State==0);f.convoy.MagazinesIssued=true;f.cargo.Finished=false;
|
||||
f.s.Stock(32000);assert(f.s.m_State==0&&f.s.m_Stock.IsEmpty());f.cargo.Finished=true;
|
||||
f.items[0].prefab.name="NATO_556_STANAG";f.s.Stock(33000);assert(f.s.m_State==1&&!f.s.m_Stopped&&f.s.m_Stock.Contains(&f.items[0]));}
|
||||
// Earliest admission: producer may finish weapons only at original Deadline+30000.
|
||||
{Fixture f;f.convoy.supply=true;f.convoy.MagazinesIssued=false;f.cargo.Finished=false;f.s.Stock(0);
|
||||
f.s.Stock(59999);assert(!f.s.m_Stopped&&f.s.m_Stock.IsEmpty());
|
||||
f.convoy.MagazinesIssued=true;f.s.Stock(60000);assert(!f.s.m_Stopped&&f.s.m_State==0);
|
||||
f.cargo.Finished=true;f.items[0].prefab.name="NATO_556_STANAG";f.s.Stock(89000);
|
||||
assert(!f.s.m_Stopped&&f.s.m_State==1&&f.s.m_Stock.Contains(&f.items[0]));}
|
||||
// Missing first-phase submission and missing second phase are bounded by one immutable deadline.
|
||||
for(int phase=0;phase<2;phase++){Fixture f;f.convoy.supply=true;f.convoy.CargoIssued=phase!=0;f.convoy.MagazinesIssued=false;
|
||||
f.s.Stock(25000);f.s.Stock(114999);assert(!f.s.m_Stopped&&f.s.m_StockDeadline==115000&&f.s.m_Stock.IsEmpty());
|
||||
f.s.Stock(115000);assert(f.s.m_Stopped&&f.s.m_Stock.IsEmpty());}
|
||||
// Faction catalogs may yield 96 distinct magazine identities; weapons are excluded.
|
||||
{Fixture f;for(int i=48;i<96;i++)f.inventory.items.Insert(&f.items[i]);f.items[0].prefab.name="NATO_556_STANAG";
|
||||
f.items[96].magazine=false;f.inventory.items.Insert(&f.items[96]);f.s.Stock(0);
|
||||
assert(!f.s.m_Stopped&&f.s.m_State==1&&f.s.m_Stock.Count()==96&&f.s.m_Stock.Contains(&f.items[0])&&!f.s.m_Stock.Contains(&f.items[96]));}
|
||||
// Detached known-zero demand also requires settled original designation; unknown never authorizes.
|
||||
{Fixture f;MineBatch batch;f.convoy.supply=true;f.convoy.MineStock=&batch;f.items[48].readyMine=true;batch.items={&f.items[48]};f.inventory.items.Insert(&f.items[48]);f.s.Stock(0);
|
||||
for(int n: {0,2,3}){f.ammo.ReadyMines=n;assert(!f.s.TryPlanMines(&f.recipient,&f.donor,&f.demand,&f.donorStatus,0));}
|
||||
f.ammo.ReadyMines=0;f.hq.designated=true;f.one.released=f.two.released=true;assert(!f.s.TryPlanMines(&f.recipient,&f.donor,&f.demand,&f.donorStatus,0));f.one.released=f.two.released=false;assert(f.s.TryPlanMines(&f.recipient,&f.donor,&f.demand,&f.donorStatus,0));f.s.Finish("reset");f.s.m_Consumed->data.clear();f.s.m_NextAttempt->data.clear();f.hq.designated=false;
|
||||
f.ammo.ReadyMines=1;f.ammo.MineComplete=false;assert(!f.s.TryPlanMines(&f.recipient,&f.donor,&f.demand,&f.donorStatus,0));f.ammo.MineComplete=true;
|
||||
batch.complete=false;assert(!f.s.TryPlanMines(&f.recipient,&f.donor,&f.demand,&f.donorStatus,0));batch.complete=true;
|
||||
assert(f.s.TryPlanMines(&f.recipient,&f.donor,&f.demand,&f.donorStatus,0));assert(f.s.m_MineTrip&&f.s.m_MineStock.Count()==1);}
|
||||
// An accepted unresolved rifle move keeps both original claims across a new
|
||||
// report after the shared180s cooldown. Distinct convoy slots own distinct tokens.
|
||||
{Fixture first,second;Leaf leaf;leaf.unresolved=true;Map<int> consumed;Map<float> cooldown;
|
||||
first.hq.convoys.tasks={&first.convoy,&second.convoy};first.hq.m_Units={&first.recipient,&first.donor,&second.donor};second.s.m_HQ=&first.hq;
|
||||
assert(first.s.Bind(&first.convoy,0,&consumed,&cooldown));assert(second.s.Bind(&second.convoy,1,&consumed,&cooldown));
|
||||
first.s.Stock(0);second.s.Stock(0);assert(first.Plan());first.s.m_Move=&leaf;first.s.Finish("accepted native rifle move remains unresolved");
|
||||
assert(first.s.m_Move==&leaf&&leaf.Unresolved());
|
||||
first.Refresh(180001,2);second.donorStatus.ObservedAt=180001;
|
||||
assert(!second.s.TryPlan(&first.recipient,&second.donor,&first.demand,&second.donorStatus,180001));
|
||||
assert(first.s.m_State==7&&first.recipient.LogisticsReservation==100001&&first.truck.SupplyToken==100001);
|
||||
assert(consumed.Get("recipient")==1&&cooldown.Get("recipient")==180000&&second.s.m_Trip==0);
|
||||
leaf.unresolved=false;first.s.Finish("settled");assert(first.recipient.LogisticsReservation==0);
|
||||
assert(second.s.TryPlan(&first.recipient,&second.donor,&first.demand,&second.donorStatus,180001));
|
||||
assert(first.recipient.LogisticsReservation==100129&&second.truck.SupplyToken==100129&&first.truck.SupplyToken==0);}
|
||||
// A submitted unknown mine retains the real HQ claim across a newer delivered
|
||||
// report and expired shared cooldown; a second truck cannot race the same actor.
|
||||
{Fixture first,second;Leaf leaf;leaf.unresolved=true;first.s.Stock(0);assert(first.Plan());first.s.m_MineMove=&leaf;first.s.m_MineTrip=true;first.s.Finish("unknown native move");
|
||||
assert(first.s.m_State==7&&first.recipient.LogisticsReservation==100001&&first.truck.SupplyToken==100001);
|
||||
second.s.Stock(0);second.s.m_HQ=&first.hq;first.hq.convoy=&second.convoy;first.hq.convoys.tasks={&second.convoy};second.s.m_Consumed=first.s.m_Consumed;second.s.m_NextAttempt=first.s.m_NextAttempt;
|
||||
first.Refresh(180001,2);second.donorStatus.ObservedAt=180001;
|
||||
assert(!second.s.TryPlan(&first.recipient,&second.donor,&first.demand,&second.donorStatus,180001));assert(first.recipient.LogisticsReservation==100001);
|
||||
leaf.unresolved=false;first.s.Finish("settled");assert(first.recipient.LogisticsReservation==0);
|
||||
assert(second.s.TryPlan(&first.recipient,&second.donor,&first.demand,&second.donorStatus,180001));}
|
||||
// Removed stock is unavailable; a different magazine added after capture does not replace its identity.
|
||||
{Fixture f;f.s.Stock(0);f.inventory.items={&f.items[48]};assert(!f.Plan());f.Unchanged();f.inventory.items.Insert(&f.items[0]);assert(f.Plan());assert(f.s.m_Stock.Count()==48&&!f.s.m_Stock.Contains(&f.items[48]));}
|
||||
{Fixture f;f.s.Stock(0);f.s.m_Spent=f.s.m_Stock;assert(!f.Plan());f.Unchanged();}
|
||||
// A delivered report is tied to exact original source identities and original still-owned members.
|
||||
{Fixture f;f.s.Stock(0);f.demand.SourceId="foreign";assert(!f.Plan());f.Unchanged();}
|
||||
{Fixture f;f.s.Stock(0);f.donorStatus.SourceId="foreign";assert(!f.Plan());f.Unchanged();}
|
||||
{Fixture f;f.s.Stock(0);f.one.released=true;assert(!f.Plan());f.Unchanged();assert(!f.s.m_Recipient&&!f.s.m_Donor);}
|
||||
{Fixture f;f.s.Stock(0);Entity foreign;foreign.group=&f.recipients;Agent extra{&foreign};f.recipients.agents.Insert(&extra);assert(!f.Plan());f.Unchanged();}
|
||||
// Real HQ force reservation refuses busy/support-ineligible or silent-radio recipients without consuming the demand.
|
||||
for(int refusal=0;refusal<5;refusal++){Fixture f;f.s.Stock(0);void* owned=&f;
|
||||
if(refusal==0){f.recipient.Assignment=owned;}if(refusal==1){f.recipient.Downlink=owned;}if(refusal==2){f.recipient.Waypoint=owned;}if(refusal==3){f.recipient.Radio=nullptr;}if(refusal==4){f.recipient.eligible=false;}
|
||||
assert(!f.Plan());f.Unchanged();assert(!f.s.m_Recipient&&!f.s.m_Donor);
|
||||
f.recipient.Assignment=nullptr;f.recipient.Downlink=nullptr;f.recipient.Waypoint=nullptr;f.recipient.Radio=&f;f.recipient.eligible=true;
|
||||
assert(f.Plan());assert(f.s.m_Trip==1&&f.s.m_Consumed->Get("recipient")==1&&f.recipient.LogisticsReservation==100001);}
|
||||
{Fixture f;f.s.Stock(0);f.recipient.LogisticsReservation=7;assert(!f.Plan());assert(f.recipient.LogisticsReservation==7&&f.s.m_Trip==0&&f.hq.downlinks==0);}
|
||||
// Failed truck downlink is still a consumed planning attempt; cleanup preserves all cargo and other ownership.
|
||||
{Fixture f;f.s.Stock(0);f.hq.routeAvailable=false;assert(f.Plan());assert(f.s.m_State==1&&f.s.m_Trip==1&&f.s.m_Consumed->Get("recipient")==1&&f.recipient.LogisticsReservation==0&&f.truck.SupplyToken==0&&f.inventory.items.Count()==48);
|
||||
f.hq.routeAvailable=true;f.Refresh(180000,1);assert(!f.Plan(180000)); // same consumed message cannot replay after cooldown
|
||||
f.Refresh(179999,2);assert(!f.Plan(179999));f.Refresh(180000,2);assert(f.Plan(180000));assert(f.s.m_Trip==2&&f.s.m_Deadline==300000);}
|
||||
// A stale-but-still-admissible demand gets only the remaining evidence horizon, never a new full lifetime.
|
||||
{Fixture f;f.s.Stock(0);assert(f.Plan(120000));assert(f.s.m_Deadline==180000);assert(!f.Plan(120000)&&f.hq.downlinks==1);}
|
||||
// Independent guarded failures do not leak reservations or acquire replacement force identities.
|
||||
for(int refusal=0;refusal<7;refusal++){Fixture f;f.s.Stock(0);
|
||||
if(refusal==0){f.recipient.HomeGuard=true;}if(refusal==1){f.truck.Combat->Held=true;}if(refusal==2){f.vehicle.captured=true;}if(refusal==3){f.mode.ledger.record.Eliminated=true;}if(refusal==4){f.donor.PendingConvoyOrder=&f;}if(refusal==5){f.ammo.Complete=false;}if(refusal==6){f.demand.Position.x=201;}
|
||||
assert(!f.Plan());f.Unchanged();}
|
||||
}
|
||||
''')
|
||||
print('PASS: actual Compatible and bounded stock preflight before report/claim consumption, later compatible truck, launcher controls, convoy binding, finite identities, disjoint tokens, shared report replay/cooldown, original recipients and HQ cleanup')
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"files": {
|
||||
"addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c": {
|
||||
"baseline_sha256": "1bfc1079961eaecee0c1ebb434570aaeb359c008f9f309033b33582092557b35",
|
||||
"proposal_sha256": "ca8eee2704e7758172e33014404bb1307c683f19b561b840d4592f6312051e62",
|
||||
"index_sha256": "966068555a6724e620a2c377b98d8dc02f141466c5cdd44636f86cb1cfe9ac78"
|
||||
},
|
||||
"tests/test_infantry_resupply_planning.py": {
|
||||
"baseline_sha256": "20747ffda8754f81f3b9e9912b9f60a300c439f2ea2c473bb900302f61dd691f",
|
||||
"proposal_sha256": "9879a27816dbc6b9c4da19c4714407614b4c6e20b2dd831b2701e5f3500ede6a",
|
||||
"index_sha256": "211e3d0ee20242f271afc46885e1ba7845ff2406d663bfe5118f40578cd5d709"
|
||||
},
|
||||
"tests/test_infantry_resupply_coordinator.py": {
|
||||
"baseline_sha256": "f9cf7d583a25a12cec9f5f80539b2590449560331f4ef34e33ea2db283c5d54a",
|
||||
"proposal_sha256": "a7eaa26e21f587fd8abde5dee6f7f8afc1e9f2f7ed0bcf40ed6a087a56908adc",
|
||||
"index_sha256": "65fa119778289175766ba7fdecd9e5685199736dffecc32056692121cbc6a682"
|
||||
},
|
||||
"tests/test_infantry_ammo_transfer.py": {
|
||||
"baseline_sha256": "0d2ebe4d5c18a4187745784013d07df621b8495967d0c01f39bd5a68ae574d26",
|
||||
"proposal_sha256": "18029a092262d0d1a309108a158597a174c1a05f58157eafd096c1c707fa0e29",
|
||||
"index_sha256": "e1172dda6350d2f8b89166ba63995cd1590435930ba220cd38b022307103a306"
|
||||
}
|
||||
},
|
||||
"patch_sha256": "ece65980fbe99627d6984e3d964a4aa30d6d80bcc44939245c49644e0225bb6a",
|
||||
"artifacts": {
|
||||
"apply-check.log": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
|
||||
"proposal-test_infantry_ammo_transfer.log": "27d49fc10aa8a5f150cdae91a192788fe84cb01b5998760ad6aba83d3c44d469",
|
||||
"proposal-test_infantry_resupply_coordinator.log": "956e431f178f472436c3abd25fcd34bfd6309ae1446335c9fbc23229428bc7cd",
|
||||
"proposal-test_infantry_resupply_planning.log": "c12aa5ba9b2141830d3916c3ab0285c06cbb44f606a9f8fbe42787ade0e67b21",
|
||||
"baseline-test_infantry_resupply_planning.log": "bf89459dc00b4db4c351933d382c400b1736f885a69443856fdd630175b742ff"
|
||||
},
|
||||
"tests": {
|
||||
"baseline-test_infantry_resupply_planning": 1,
|
||||
"proposal-test_infantry_resupply_planning": 0,
|
||||
"proposal-test_infantry_resupply_coordinator": 0,
|
||||
"proposal-test_infantry_ammo_transfer": 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"baseline-test_infantry_resupply_planning": 1,
|
||||
"proposal-test_infantry_resupply_planning": 0,
|
||||
"proposal-test_infantry_resupply_coordinator": 0,
|
||||
"proposal-test_infantry_ammo_transfer": 0
|
||||
}
|
||||
Reference in New Issue
Block a user