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

34 lines
4.3 KiB
Python

from pathlib import Path
import hashlib,json,difflib
R=Path('/home/jakub/devel/escapistsrereintroduced');P=Path('/tmp/erri-crash-root-1852/route-proposal');files={}
def edit(n,s):
old=(R/n).read_text() if (R/n).exists() else ''
p=P/n;p.parent.mkdir(parents=True,exist_ok=True);p.write_text(s)
files[n]={'baseline_sha256':hashlib.sha256(old.encode()).hexdigest() if (R/n).exists() else None,'proposal_sha256':hashlib.sha256(s.encode()).hexdigest()}
return ''.join(difflib.unified_diff(old.splitlines(True),s.splitlines(True),fromfile='a/'+n if old else '/dev/null',tofile='b/'+n))
patch=''; n='addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c';s=(R/n).read_text()
s=s.replace('protected bool m_ERRTestCrashGeometry;','protected bool m_ERRTestCrashStart;\n\tprotected bool m_ERRCrashEnteredPrison;\n\tprotected bool m_ERRTestCrashGeometry;')
s=s.replace('m_ERRTestEscapeRoute = outcome == "escape-route" || outcome == "normal-escape-route";','m_ERRTestCrashStart = outcome == "crash-start";\n\t\tm_ERRTestEscapeRoute = outcome == "escape-route" || outcome == "normal-escape-route" || m_ERRTestCrashStart;')
s=s.replace('if (m_ERRSmokeDone || !ERR_MissionRules.Terminal(current)) return;','if (m_ERRTestCrashStart && current == ERR_Phase.PRISON) m_ERRCrashEnteredPrison = true;\n\t\tif (m_ERRSmokeDone || !ERR_MissionRules.Terminal(current)) return;',1)
s=s.replace('if (m_SpawnPreload && Phase() == ERR_Phase.PRISON && !m_ERRSpawnPreloadUIObserved)','ERR_Phase initialPhase = ERR_Phase.PRISON;\n\t\t\tif (m_ERRTestCrashStart) initialPhase = ERR_Phase.RADIO_SEARCH;\n\t\t\tif (m_SpawnPreload && Phase() == initialPhase && !m_ERRSpawnPreloadUIObserved)')
s=s.replace('if (players.Count() != 1 || Phase() != ERR_Phase.PRISON) return;','if (players.Count() != 1 || Phase() != initialPhase) return;')
start=s.index('\t\t\tERR_UnlockPrisonAction lock;');end=s.index('\t\t\tarray<IEntity> cacheStock',start)
original=s[start:end]
s=s[:start]+'''\t\t\tif (m_ERRTestCrashStart)
\t\t\t{
\t\t\t\tif (!ERR_Check(!m_ERRCrashEnteredPrison && ERR_PrisonAIState(true), "crash start never enters prison and existing enemies are active")) return;
\t\t\t\tif (!ERR_NativeCrashStartProbe.Run(this, m_ERRSmokePlayer)) { m_ERRSmokeDone = true; GetGame().GetCallqueue().Remove(ERR_SmokeTick); return; }
\t\t\t}
\t\t\telse
\t\t\t{
'''+''.join('\t'+line if line.strip() else line for line in original.splitlines(True))+ '\t\t\t}\n'+s[end:]
s=s.replace('if (m_ERRSmokeStep == 2 && !ERR_Check(m_ERRGate','if (m_ERRSmokeStep == 2 && !m_ERRTestCrashStart && !ERR_Check(m_ERRGate')
s=s.replace('PrintFormat("ERR SMOKE COMPLETE: terminal=%1 lostHelicopterCase=%2 playerDeathCase=%3", current, m_ERRTestLostHelicopter, m_ERRTestPlayerDeath);','PrintFormat("ERR SMOKE COMPLETE: terminal=%1 lostHelicopterCase=%2 playerDeathCase=%3 crashStartCase=%4", current, m_ERRTestLostHelicopter, m_ERRTestPlayerDeath, m_ERRTestCrashStart);')
patch+=edit(n,s)
n='addons/core/Scripts/Game/ERR/00_Core/ERR_NativeContractsProbe.c';s=(R/n).read_text();s=s.replace('if (!Check(!replies.IsEmpty() && replies[0] == "Escape the prison", "base mission status available before companions")) return false;','string initialStatus = "Escape the prison";\n if (mode.StartMode() == 1) initialStatus = "Locate the radio station";\n if (!Check(!replies.IsEmpty() && replies[0] == initialStatus, "base mission status available before companions")) return false;');patch+=edit(n,s)
n='addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeCrashStartProbe.c';patch+=edit(n,(P/'ERR_NativeCrashStartProbe.c').read_text())
n='tools/headless_workbench.py';s=(R/n).read_text().replace("choices=['crash-geometry',","choices=['crash-start', 'crash-geometry',",1);s=s.replace("if a.smoke == 'crash-geometry'", "if a.smoke == 'crash-start' and (a.project != 'chat' or a.rounds != 1 or a.timeout < 240): p.error('crash-start requires Chat, one round and timeout at least 240 seconds')\nif a.smoke == 'crash-geometry'",1);patch+=edit(n,s)
n='tools/check.py';s=(R/n).read_text().replace("for name in ['test_intercept_vehicle_footprint.py'", "for name in ['test_crash_start.py', 'test_start_settings.py', 'test_intercept_vehicle_footprint.py'",1);patch+=edit(n,s)
(P/'fix.patch').write_text(patch);(P/'source-manifest.json').write_text(json.dumps({'files':files,'patch_sha256':hashlib.sha256(patch.encode()).hexdigest()},indent=2)+'\n')
print('Frozen',len(files),'files',hashlib.sha256(patch.encode()).hexdigest())