Files
EscapistsReintroduced/tests/test_radio_waiting_text.py
T
jakub cab998fb64 Combine Workshop addon and fix prison startup
Merge owned systems into one addon while preserving resource identities. Gate player admission on the replicated prison scene, restore the original framed door, and hold enemy AI until escape. Correct scenario branding and author metadata, include publishing assets, and retain regression and native verification evidence.
2026-09-20 16:42:52 +02:00

73 lines
4.3 KiB
Python

"""Execute actual task/guide copy for initial waiting and subsequent radio states."""
from policy_harness import ROOT, body, run
source = ROOT / 'addons/core/Scripts/Game/ERR/00_Core/ERR_ObjectiveText.c'
def translate(s):
s = s.replace('protected ', '').replace('ERR_GameMode mode,', 'ERR_GameMode* mode,')
s = s.replace('ERR_Phase phase', 'int phase').replace('mode.', 'mode->')
s = s.replace('ERR_RadioFeedback feedback', 'int feedback')
s = s.replace('array<ERR_LocationComponent>', 'std::vector<ERR_LocationComponent*>')
s = s.replace('foreach (ERR_LocationComponent location : locations)', 'for (ERR_LocationComponent* location : locations)')
s = s.replace('location.', 'location->').replace('bool roughRadio;', 'bool roughRadio = false;')
s = s.replace('.IsEmpty()', '.empty()').replace('string.Format(', 'Format(')
for name in ('ERR_Phase', 'ERR_LocationKind', 'ERR_RadioFeedback', 'Math'):
s = s.replace(name + '.', name + '::')
return s
methods = '\n'.join(translate(body(source, signature)) for signature in (
'static string RadioFeedbackMessage(', 'protected static string PhaseDescription('))
run(r'''
#include <cassert>
#include <string>
#include <vector>
#include <cmath>
using string=std::string;
namespace ERR_Phase {enum {PREPARING,PRISON,RADIO_SEARCH,RADIO_DEFENCE,EXTRACTION,VICTORY,DEFEAT};}
namespace ERR_LocationKind {enum {PRISON,RADIO,EXTRACTION,OUTPOST,DEPOT};}
namespace ERR_RadioFeedback {enum {INACTIVE,WAITING,TRANSMITTING,INTERRUPTED};}
namespace Math {float Ceil(float n){return std::ceil(n);}}
struct ERR_LocationComponent {int Kind(){return 0;}int Knowledge(){return 0;}};
struct ERR_GameMode {
int phase=ERR_Phase::RADIO_DEFENCE, feedback=ERR_RadioFeedback::WAITING, remaining=180;
bool occupied=false;int Phase(){return phase;}string PreparationError(){return "";}
void Locations(std::vector<ERR_LocationComponent*>& locations){locations.clear();}
int RadioFeedback(){return feedback;}int DefenceSecondsRemaining(){return remaining;}
bool DefenceOccupied(){return occupied;}float EscapeRadius(){return 9000;}
};
string Format(string s,int value){auto p=s.find("%1");assert(p!=string::npos);return s.replace(p,2,std::to_string(value));}
string Extraction(float radius){assert(radius==9000);return "extraction";}
struct Actual {
''' + methods + r'''
};
bool has(string text,string needle){return text.find(needle)!=string::npos;}
int main(){
ERR_GameMode mode;
for(int duration : {30,180,1800}) {
mode.remaining=duration;
auto task=Actual::PhaseDescription(&mode,true);
assert(has(task,"Waiting for a conscious defender")&&!has(task,"interrupted"));
assert(has(task,std::to_string(duration)+" seconds")&&has(task,"Leaving resets progress"));
auto guide=Actual::PhaseDescription(&mode,false);
assert(has(guide,"Waiting for")&&!has(guide,"interrupted"));
}
mode.feedback=ERR_RadioFeedback::TRANSMITTING;mode.occupied=true;mode.remaining=179;
auto active=Actual::PhaseDescription(&mode,true);
assert(has(active,"up to 180 seconds remaining")&&!has(active,"Waiting")&&!has(active,"interrupted"));
assert(has(Actual::PhaseDescription(&mode,false),"Transmission in progress"));
mode.feedback=ERR_RadioFeedback::INTERRUPTED;mode.occupied=false;mode.remaining=180;
auto interrupted=Actual::PhaseDescription(&mode,true);
assert(has(interrupted,"Transmission interrupted")&&has(interrupted,"180 seconds"));
assert(!has(interrupted,"Waiting")&&has(Actual::PhaseDescription(&mode,false),"Progress has reset"));
mode.feedback=ERR_RadioFeedback::TRANSMITTING;mode.occupied=true;mode.remaining=174;
assert(has(Actual::PhaseDescription(&mode,true),"up to 175 seconds remaining"));
// Occupancy remains the progress authority; WAITING only selects unoccupied copy.
mode.feedback=ERR_RadioFeedback::WAITING;
assert(has(Actual::PhaseDescription(&mode,true),"seconds remaining"));
mode.occupied=false;
assert(has(Actual::PhaseDescription(&mode,true),"Waiting for a conscious defender"));
mode.phase=ERR_Phase::EXTRACTION;assert(Actual::PhaseDescription(&mode,true)=="extraction");
mode.phase=ERR_Phase::VICTORY;assert(Actual::PhaseDescription(&mode,true).empty());
mode.phase=ERR_Phase::DEFEAT;assert(Actual::PhaseDescription(&mode,true).empty());
}
''')
print('PASS: actual initial WAITING task/guide copy, configured duration, unchanged interruption and rounded progress; native task assertion pending')