96 lines
6.3 KiB
Python
96 lines
6.3 KiB
Python
"""Execute burial eligibility/deletion with native boundaries substituted."""
|
|
import re
|
|
from policy_harness import ROOT, body, run
|
|
p=ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_BuryBodyAction.c'
|
|
def cpp(s):
|
|
s=s.replace('override ', '').replace('string.Empty','string{}').replace('.IsEmpty()', '.empty()')
|
|
for typ in ('ChimeraCharacter','CharacterControllerComponent','ERR_GameMode'):
|
|
s=re.sub(r'\b'+typ+r' (?=\w)',typ+'* ',s)
|
|
for typ in ('ChimeraCharacter','ECharacterLifeState','ERR_GameMode','ERR_Actors','CompartmentAccessComponent','vector','Replication','SCR_EntityHelper','ERR_Burial'):
|
|
s=s.replace(typ+'.',typ+'::')
|
|
for var in ('character','controller','item','mode','user','body'):
|
|
s=s.replace(var+'.',var+'->')
|
|
s=s.replace('GetCharacterController().','GetCharacterController()->').replace('mode->Players().','mode->Players()->').replace('null','nullptr')
|
|
return s
|
|
methods='\n'.join(cpp(body(p,s)) for s in ('static bool Dead(', 'static bool ShovelHeld(', 'static bool Reach(', 'static string Rejection(', 'static bool Permitted(', 'static void Complete('))
|
|
run(r'''
|
|
#include <cassert>
|
|
#include <string>
|
|
#include <cmath>
|
|
#include <limits>
|
|
using string=std::string;
|
|
struct Entity;using IEntity=Entity*;
|
|
namespace ECharacterLifeState {constexpr int ALIVE=0,UNCONSCIOUS=1,DEAD=2;}
|
|
constexpr int SCR_CampaignBuildingGadgetToolComponent=1;
|
|
struct CharacterControllerComponent {
|
|
int life=0;IEntity gadget=nullptr,weapon=nullptr;
|
|
int GetLifeState(){return life;}IEntity GetAttachedGadgetAtLeftHandSlot(){return gadget;}IEntity GetCurrentItemInHands(){return weapon;}
|
|
};
|
|
struct vector {float x=0;static float Distance(vector a,vector b){return std::abs(a.x-b.x);}};
|
|
struct Entity {
|
|
bool character=true,player=false,shovel=false,aboard=false,deleted=false,controllerExists=true;
|
|
vector pos;CharacterControllerComponent controller;
|
|
static Entity* Cast(IEntity e){return e&&e->character&&!e->deleted?e:nullptr;}
|
|
CharacterControllerComponent* GetCharacterController(){return controllerExists?&controller:nullptr;}
|
|
void* FindComponent(int){return shovel?this:nullptr;}vector GetOrigin(){return pos;}
|
|
};
|
|
using ChimeraCharacter=Entity;
|
|
struct Roster {IEntity admitted=nullptr;bool CurrentActor(IEntity e){return e&&e==admitted&&!e->deleted;}};
|
|
struct ERR_GameMode {bool active=true,rosterExists=true;Roster roster;static ERR_GameMode* current;static ERR_GameMode* Get(){return current;}bool Active(){return active;}Roster* Players(){return rosterExists?&roster:nullptr;}};
|
|
ERR_GameMode* ERR_GameMode::current=nullptr;
|
|
namespace ERR_Actors {bool Player(IEntity e){return e&&!e->deleted&&e->player;}bool CanFight(IEntity e){return e&&!e->deleted&&e->controller.life==ECharacterLifeState::ALIVE;}}
|
|
namespace CompartmentAccessComponent {bool GetVehicleIn(IEntity e){return e&&e->aboard;}}
|
|
namespace Replication {bool server=true;bool IsServer(){return server;}}
|
|
namespace SCR_EntityHelper {int deletions=0;void DeleteEntityAndChildren(IEntity e){assert(e&&!e->deleted);e->deleted=true;deletions++;}}
|
|
struct ERR_Burial {static bool clear;static bool Clear(IEntity,IEntity){return clear;}
|
|
''' + methods + r'''
|
|
};bool ERR_Burial::clear=true;
|
|
int main(){
|
|
Entity player,corpse,shovel,rifle;player.player=true;corpse.controller.life=2;shovel.shovel=true;shovel.character=false;rifle.character=false;
|
|
ERR_GameMode mode;ERR_GameMode::current=&mode;mode.roster.admitted=&player;
|
|
assert(ERR_Burial::Dead(&corpse)&&!ERR_Burial::Dead(nullptr)&&!ERR_Burial::Dead(&shovel));
|
|
assert(!ERR_Burial::ShovelHeld(nullptr)&&!ERR_Burial::ShovelHeld(&player));
|
|
player.controller.weapon=&rifle;assert(!ERR_Burial::ShovelHeld(&player));
|
|
player.controller.gadget=&shovel;assert(ERR_Burial::ShovelHeld(&player));
|
|
assert(ERR_Burial::Permitted(&player,&corpse));
|
|
for(int variation=0;variation<17;variation++){
|
|
if(variation==0)Replication::server=false;
|
|
if(variation==1)ERR_GameMode::current=nullptr;
|
|
if(variation==2)mode.active=false;
|
|
if(variation==3)mode.rosterExists=false;
|
|
if(variation==4)mode.roster.admitted=nullptr;
|
|
if(variation==5)player.player=false;
|
|
if(variation==6)player.controller.life=1;
|
|
if(variation==7)player.controller.life=2;
|
|
if(variation==8)corpse.controller.life=0;
|
|
if(variation==9)corpse.controller.life=1;
|
|
if(variation==10)player.controller.gadget=nullptr;
|
|
if(variation==11)player.aboard=true;
|
|
if(variation==12)corpse.aboard=true;
|
|
if(variation==13)corpse.pos.x=2.501;
|
|
if(variation==14)ERR_Burial::clear=false;
|
|
if(variation==15)corpse.character=false;
|
|
if(variation==16)player.controllerExists=false;
|
|
assert(!ERR_Burial::Permitted(&player,&corpse));ERR_Burial::Complete(&player,&corpse);assert(!corpse.deleted&&SCR_EntityHelper::deletions==0);
|
|
Replication::server=true;ERR_GameMode::current=&mode;mode.active=true;mode.rosterExists=true;mode.roster.admitted=&player;
|
|
player.player=true;player.controller.life=0;corpse.controller.life=2;player.controller.gadget=&shovel;
|
|
player.aboard=false;corpse.aboard=false;corpse.pos.x=0;ERR_Burial::clear=true;corpse.character=true;player.controllerExists=true;
|
|
}
|
|
assert(!ERR_Burial::Permitted(&player,nullptr)&&!ERR_Burial::Permitted(&player,&player));
|
|
assert(ERR_Burial::Reach(2.5)&&!ERR_Burial::Reach(-1)&&!ERR_Burial::Reach(std::numeric_limits<float>::quiet_NaN()));
|
|
corpse.pos.x=2.5;ERR_Burial::Complete(&player,&corpse);
|
|
assert(corpse.deleted&&!player.deleted&&!shovel.deleted&&SCR_EntityHelper::deletions==1);
|
|
ERR_Burial::Complete(&player,&corpse);assert(SCR_EntityHelper::deletions==1);
|
|
}
|
|
''')
|
|
# Verify native wiring is additive and that completion revalidates after delay.
|
|
s=p.read_text();action=body(p,'override void PerformAction(')
|
|
assert 'pOwnerEntity != GetOwner()' in action and 'ERR_Burial.Permitted(pUserEntity, pOwnerEntity)' in action
|
|
assert 'CallLater(ERR_Burial.Complete' in action
|
|
prefab=(ROOT/'addons/core/Prefabs/Characters/Core/Character_Base.et').read_text()
|
|
assert 'ERR_BuryBodyAction' in prefab and 'Duration 8' in prefab and '"Chest" "LowerTorso"' in prefab
|
|
assert 'SCR_BandageUserAction' not in prefab # minimal inherited addition, no replacement action list
|
|
assert 'override bool CanBroadcastScript() { return false; }' in s
|
|
assert 'override bool CheckOnServerFirstScript() { return true; }' in s
|
|
print('PASS: burial requires a conscious current player, actual held shovel, dead nearby unobstructed corpse and no vehicle; authority and duplicate deletion guards preserve player/tool')
|