From 1b1a8b5173e4a266ed86df32f7e7d6908d297267 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20=C5=BD=C3=A1=C4=8Dek?= Date: Wed, 23 Sep 2026 15:07:14 +0200 Subject: [PATCH] Add mission customization, HQ support and aggression-driven AI Integrate faction and random settings menus, generated objectives, scouts, convoys, air support, mortar stations and body-intel recovery. Add identified-body aggression, finite hunter UAZ deployment, dedicated objective defence and maximum AI skill with separate reduced aim accuracy. Include policy tests, native probes, evidence and documentation. --- addons/core/Configs/ERR/Content/Registry.conf | 34 + .../Configs/ERR/Content/Registry.conf.meta | 7 + addons/core/Configs/ERR/EveronSites.conf | 93 +- .../core/Configs/ERR/Tests/LegacySites.conf | 152 ++++ .../Configs/ERR/Tests/LegacySites.conf.meta | 7 + addons/core/Prefabs/ERR/AssaultParachute.et | 10 + .../core/Prefabs/ERR/AssaultParachute.et.meta | 7 + addons/core/Prefabs/ERR/FactionManager.et | 16 + addons/core/Prefabs/ERR/PrisonBackpack.et | 7 + .../core/Prefabs/ERR/PrisonBackpack.et.meta | 9 + addons/core/Prefabs/ERR/PrisonPatrol.et | 7 + addons/core/Prefabs/ERR/PrisonPatrol.et.meta | 7 + addons/core/Prefabs/ERR/RadioCamp.et | 3 + addons/core/Prefabs/ERR/RadioCamp.et.meta | 7 + addons/core/Prefabs/ERR/ReconCrew.et | 7 + addons/core/Prefabs/ERR/ReconCrew.et.meta | 7 + addons/core/Prefabs/ERR/ReconHelicopter.et | 14 + .../core/Prefabs/ERR/ReconHelicopter.et.meta | 7 + addons/core/Prefabs/ERR/ReconPilotEast.et | 12 + .../core/Prefabs/ERR/ReconPilotEast.et.meta | 7 + addons/core/Prefabs/ERR/ReconPilotWest.et | 12 + .../core/Prefabs/ERR/ReconPilotWest.et.meta | 7 + addons/core/Prefabs/ERR/ScoutEast.et | 23 + addons/core/Prefabs/ERR/ScoutEast.et.meta | 7 + addons/core/Prefabs/ERR/ScoutGroup.et | 7 + addons/core/Prefabs/ERR/ScoutGroup.et.meta | 7 + addons/core/Prefabs/ERR/ScoutRadioPack.et | 34 + .../core/Prefabs/ERR/ScoutRadioPack.et.meta | 7 + addons/core/Prefabs/ERR/ScoutWest.et | 23 + addons/core/Prefabs/ERR/ScoutWest.et.meta | 7 + .../Scripts/Game/ERR/00_Core/ERR_Actors.c | 20 +- .../Scripts/Game/ERR/00_Core/ERR_AdminMenu.c | 68 +- .../Game/ERR/00_Core/ERR_AdminPlayerTools.c | 17 +- .../Game/ERR/00_Core/ERR_AdminService.c | 38 +- .../Game/ERR/00_Core/ERR_AdminSession.c | 5 + .../Game/ERR/00_Core/ERR_AirfieldPlacement.c | 32 + .../Game/ERR/00_Core/ERR_ContentDefinition.c | 103 +++ .../Game/ERR/00_Core/ERR_ContentMenu.c | 118 +++ .../Game/ERR/00_Core/ERR_ContentPolicy.c | 136 +++ .../Game/ERR/00_Core/ERR_ContentSettings.c | 86 ++ .../Scripts/Game/ERR/00_Core/ERR_DebugAI.c | 43 + .../Scripts/Game/ERR/00_Core/ERR_DebugIntel.c | 30 + .../Game/ERR/00_Core/ERR_DiscoveryMap.c | 50 +- .../Game/ERR/00_Core/ERR_DiscoveryService.c | 10 +- .../Game/ERR/00_Core/ERR_EnvironmentService.c | 39 +- .../Game/ERR/00_Core/ERR_FactionMenu.c | 96 +++ .../Game/ERR/00_Core/ERR_FactionSelection.c | 268 ++++++ .../Game/ERR/00_Core/ERR_ForceLedger.c | 4 +- .../Scripts/Game/ERR/00_Core/ERR_GameMode.c | 38 +- .../Game/ERR/00_Core/ERR_GeneratedSites.c | 148 ++++ .../Scripts/Game/ERR/00_Core/ERR_Location.c | 2 +- .../ERR/00_Core/ERR_NativeAdminMenuProbe.c | 188 +++- .../00_Core/ERR_NativeAdminSettingsProbe.c | 62 ++ .../ERR/00_Core/ERR_NativeAggressionProbe.c | 121 +++ .../00_Core/ERR_NativeAirfieldMarkersProbe.c | 205 +++++ .../Game/ERR/00_Core/ERR_NativeBaseSmoke.c | 7 +- .../Game/ERR/00_Core/ERR_NativeContentProbe.c | 71 ++ .../ERR/00_Core/ERR_NativeContractsProbe.c | 4 +- .../ERR/00_Core/ERR_NativeDefinitionProbe.c | 2 +- .../00_Core/ERR_NativeFactionCatalogProbe.c | 2 +- .../00_Core/ERR_NativeFactionSelectionProbe.c | 53 ++ .../00_Core/ERR_NativeGeneratedSitesProbe.c | 138 +++ .../ERR/00_Core/ERR_NativeOpeningToolsProbe.c | 109 +++ .../Game/ERR/00_Core/ERR_NativePatrolProbe.c | 2 +- .../ERR/00_Core/ERR_NativeRadioCampProbe.c | 17 + .../ERR/00_Core/ERR_NativeTransportProbe.c | 4 +- .../ERR/00_Core/ERR_NativeTransportSurvey.c | 2 +- .../Game/ERR/00_Core/ERR_ObjectiveText.c | 4 +- .../Scripts/Game/ERR/00_Core/ERR_PrisonAI.c | 2 +- .../ERR/00_Core/ERR_PrisonEscapeService.c | 4 +- .../Game/ERR/00_Core/ERR_PrisonPatrol.c | 106 +++ .../ERR/00_Core/ERR_RadioDefenceService.c | 2 +- .../Game/ERR/00_Core/ERR_ScenarioComponent.c | 33 +- .../Scripts/Game/ERR/00_Core/ERR_Settings.c | 61 +- .../Game/ERR/00_Core/ERR_SiteDefinition.c | 21 +- .../Game/ERR/00_Core/ERR_SiteDiscoveryRules.c | 2 +- .../Game/ERR/00_Core/ERR_SiteService.c | 88 +- .../Scripts/Game/ERR/00_Core/ERR_SpawnLogic.c | 6 +- .../Game/ERR/00_Core/ERR_SpawnPlacement.c | 39 +- .../Game/ERR/00_Core/ERR_TimeService.c | 19 +- .../Game/ERR/10_AI/ERR_AirAmmoMission.c | 239 ++++++ .../Game/ERR/10_AI/ERR_AirAssaultLoad.c | 350 ++++++++ .../Game/ERR/10_AI/ERR_AirAssaultSystem.c | 223 +++++ .../Game/ERR/10_AI/ERR_AirReconSystem.c | 109 +++ .../Game/ERR/10_AI/ERR_AirSupportPolicy.c | 79 ++ .../Scripts/Game/ERR/10_AI/ERR_AircraftAmmo.c | 90 ++ .../Game/ERR/10_AI/ERR_AirfieldSupport.c | 196 +++++ .../Game/ERR/10_AI/ERR_AssaultParachute.c | 321 +++++++ .../Scripts/Game/ERR/10_AI/ERR_BodyRecovery.c | 300 +++++++ .../Scripts/Game/ERR/10_AI/ERR_ConvoyBudget.c | 35 +- .../Scripts/Game/ERR/10_AI/ERR_ConvoyCombat.c | 1 + .../Game/ERR/10_AI/ERR_ConvoyService.c | 29 +- .../Game/ERR/10_AI/ERR_EnemyEquipment.c | 7 +- .../Game/ERR/10_AI/ERR_EnemyGunnerSkill.c | 16 +- .../Scripts/Game/ERR/10_AI/ERR_EnemyOptics.c | 1 + .../Game/ERR/10_AI/ERR_EnemySkillAwareness.c | 38 + addons/core/Scripts/Game/ERR/10_AI/ERR_HQ.c | 231 ++++- .../Game/ERR/10_AI/ERR_HQAdminProvider.c | 35 +- .../Game/ERR/10_AI/ERR_HQBodyObserver.c | 4 +- .../Scripts/Game/ERR/10_AI/ERR_HQCoverage.c | 4 +- .../Game/ERR/10_AI/ERR_HQObservation.c | 7 + .../Scripts/Game/ERR/10_AI/ERR_HQReport.c | 4 +- .../core/Scripts/Game/ERR/10_AI/ERR_HQTask.c | 2 + .../core/Scripts/Game/ERR/10_AI/ERR_HQWatch.c | 16 +- .../Game/ERR/10_AI/ERR_HunterService.c | 173 ++++ .../Game/ERR/10_AI/ERR_InfantryAmmoAccess.c | 7 +- .../Game/ERR/10_AI/ERR_InfantryAmmoTransfer.c | 3 +- .../Game/ERR/10_AI/ERR_InfantryResupply.c | 2 +- .../Game/ERR/10_AI/ERR_MortarBattery.c | 5 + .../Game/ERR/10_AI/ERR_MortarLogistics.c | 33 +- .../Scripts/Game/ERR/10_AI/ERR_MortarSalvo.c | 2 +- .../Game/ERR/10_AI/ERR_MortarStation.c | 126 +++ .../Scripts/Game/ERR/10_AI/ERR_MortarSystem.c | 27 +- .../ERR/10_AI/ERR_NativeAirAssaultProbe.c | 114 +++ .../ERR/10_AI/ERR_NativeAirLogisticsProbe.c | 174 ++++ .../Game/ERR/10_AI/ERR_NativeAirReconProbe.c | 169 ++++ .../ERR/10_AI/ERR_NativeMortarStationProbe.c | 103 +++ .../Game/ERR/10_AI/ERR_NativeScoutProbe.c | 54 ++ .../Game/ERR/10_AI/ERR_ObjectiveDefence.c | 105 +++ .../Game/ERR/10_AI/ERR_ReconAirports.c | 118 +++ .../Game/ERR/10_AI/ERR_ReconCrewLocks.c | 19 + .../Game/ERR/10_AI/ERR_ReconFlightComponent.c | 359 ++++++++ .../Scripts/Game/ERR/10_AI/ERR_ScoutSystem.c | 305 +++++++ .../Game/ERR/10_AI/ERR_SupplyConvoyService.c | 227 +++++ .../Game/ERR/10_AI/ERR_SupplyConvoySystem.c | 133 +++ .../Game/ERR/10_AI/ERR_SupplyConvoyTactics.c | 404 +++++++++ .../Game/ERR/10_AI/ERR_SupportScenario.c | 6 + .../ERR/20_Intel/ERR_IntelDiscoveryFeedback.c | 44 +- .../Game/ERR/20_Intel/ERR_IntelEvidence.c | 197 +++++ .../Game/ERR/20_Intel/ERR_IntelReroll.c | 1 + .../Game/ERR/20_Intel/ERR_IntelService.c | 5 +- .../Game/ERR/40_Chat/ERR_NativeSmoke.c | 12 +- .../ERR/40_Chat/ERR_NativeSupplyConvoyProbe.c | 156 ++++ addons/core/UI/layouts/ERR/AdminMenu.layout | 802 ++++++++++-------- addons/core/UI/layouts/ERR/AdminValue.layout | 21 + .../UI/layouts/ERR/AdminValue.layout.meta | 11 + addons/core/UI/layouts/ERR/ContentRow.layout | 8 + .../UI/layouts/ERR/ContentRow.layout.meta | 11 + .../UI/layouts/ERR/PauseModsButton.layout | 9 + .../layouts/ERR/PauseModsButton.layout.meta | 11 + addons/core/addon.gproj | 1 + docs/aggression-ai.md | 59 ++ docs/ai-equipment-migration.md | 2 + docs/ai-feature-migration.json | 76 +- docs/ai-migration-progress.md | 3 + docs/airfield-extraction-and-map-icons.md | 48 ++ docs/configuration.md | 104 ++- docs/content-packs.md | 133 +++ docs/convoy-migration.md | 3 + docs/convoy-startup.md | 3 + docs/discovery-map-usability.md | 7 + .../evidence/admin-pages-2026-09-22/README.md | 25 + .../native-menu-checks.txt | 47 + .../admin-pages-2026-09-22/page-0.png | Bin 0 -> 150185 bytes .../admin-pages-2026-09-22/page-1.png | Bin 0 -> 151142 bytes .../admin-pages-2026-09-22/page-2.png | Bin 0 -> 156185 bytes .../admin-pages-2026-09-22/page-3.png | Bin 0 -> 151297 bytes .../admin-pages-2026-09-22/page-4.png | Bin 0 -> 150228 bytes .../admin-pages-2026-09-22/page-5.png | Bin 0 -> 151557 bytes .../admin-pages-2026-09-22/page-6.png | Bin 0 -> 150535 bytes .../admin-pages-2026-09-22/page-7.png | Bin 0 -> 151875 bytes .../repository-checks.txt | 476 +++++++++++ .../admin-pages-2026-09-22/sources.json | 10 + .../hq-air-support-2026-09-22/README.md | 21 + .../airborne-native5-excerpt.log | 14 + .../airborne-native5-source-sha256.json | 14 + .../cargo-native7-excerpt.log | 33 + .../cargo-native7-source-sha256.json | 13 + .../recovery-native3-excerpt.log | 16 + .../recovery-native3-source-sha256.json | 13 + docs/external-addons.json | 48 +- docs/generated-sites.md | 85 ++ docs/hill-scouts.md | 80 ++ docs/hq-air-support.md | 93 ++ docs/migration-provenance.json | 62 +- docs/mortar-intel-and-prison-map.md | 68 ++ docs/mortar-stations.md | 46 + docs/prison-patrol-and-debug-intel.md | 45 + docs/radio-camp-security.md | 40 + docs/search-helicopter.md | 95 +++ docs/supply-convoys.md | 43 + docs/vanilla-resources.json | 227 ++--- docs/vehicle-maintenance.md | 10 +- tests/mortar_salvo_regression.py | 10 +- tests/test_admin_menu.py | 14 +- tests/test_admin_player_tools.py | 10 +- tests/test_admin_providers.py | 2 +- tests/test_air_logistics_orders.py | 55 ++ tests/test_air_recon.py | 64 ++ tests/test_air_support_policy.py | 57 ++ tests/test_content_policy.py | 48 ++ tests/test_convoy_auto_settings.py | 4 +- tests/test_convoy_budget.py | 14 + tests/test_convoy_dispatch.py | 5 +- tests/test_convoy_startup.py | 7 +- tests/test_debug_ai.py | 18 + tests/test_dedicated_native.py | 2 +- tests/test_enemy_awareness.py | 41 + tests/test_enemy_equipment.py | 14 +- tests/test_enemy_gunner_skill.py | 27 +- tests/test_enemy_optics.py | 5 +- tests/test_external_addons.py | 2 +- tests/test_faction_selection.py | 50 ++ tests/test_force_ledger.py | 12 +- tests/test_generated_sites.py | 36 + tests/test_hq_ammo_dispatch.py | 4 +- tests/test_hq_assignment_lifecycle.py | 6 +- tests/test_hq_body_observer.py | 8 +- tests/test_hq_convoy_combat.py | 19 +- tests/test_hq_convoy_dispatch.py | 31 +- tests/test_hq_coverage.py | 10 +- tests/test_hq_delivered_task.py | 9 +- tests/test_hq_local_handoff_intake.py | 4 +- tests/test_hq_uplink_fairness.py | 8 +- tests/test_hq_watch.py | 31 +- tests/test_hunter_lifecycle.py | 44 + tests/test_infantry_ammo_access.py | 10 +- tests/test_infantry_ammo_transfer.py | 3 +- tests/test_intel_body_inspection.py | 88 ++ tests/test_intel_discovery_feedback.py | 20 +- tests/test_intel_registration.py | 28 +- tests/test_intel_reroll.py | 7 +- tests/test_mortar_activity_completion.py | 6 +- tests/test_mortar_logistics.py | 45 + tests/test_mortar_station.py | 35 + tests/test_native_end_lifecycle.py | 2 +- tests/test_native_package_external.py | 6 +- tests/test_packed_external_game.py | 4 +- tests/test_participant_selection.py | 4 +- tests/test_prison_ai.py | 2 +- tests/test_prison_placement_policy.py | 38 +- tests/test_random_settings.py | 47 + tests/test_rough_intel_feedback.py | 4 +- tests/test_scouts.py | 79 ++ tests/test_settings_migration.py | 8 +- tests/test_site_discovery_policy.py | 3 +- tests/test_supply_convoys.py | 251 ++++++ tests/test_vehicle_maintenance_stock.py | 13 +- tools/check.py | 2 +- tools/external_addons.py | 3 +- tools/headless_workbench.py | 8 +- tools/import_settings.py | 6 +- 242 files changed, 12153 insertions(+), 875 deletions(-) create mode 100644 addons/core/Configs/ERR/Content/Registry.conf create mode 100644 addons/core/Configs/ERR/Content/Registry.conf.meta create mode 100644 addons/core/Configs/ERR/Tests/LegacySites.conf create mode 100644 addons/core/Configs/ERR/Tests/LegacySites.conf.meta create mode 100644 addons/core/Prefabs/ERR/AssaultParachute.et create mode 100644 addons/core/Prefabs/ERR/AssaultParachute.et.meta create mode 100644 addons/core/Prefabs/ERR/PrisonBackpack.et create mode 100644 addons/core/Prefabs/ERR/PrisonBackpack.et.meta create mode 100644 addons/core/Prefabs/ERR/PrisonPatrol.et create mode 100644 addons/core/Prefabs/ERR/PrisonPatrol.et.meta create mode 100644 addons/core/Prefabs/ERR/RadioCamp.et create mode 100644 addons/core/Prefabs/ERR/RadioCamp.et.meta create mode 100644 addons/core/Prefabs/ERR/ReconCrew.et create mode 100644 addons/core/Prefabs/ERR/ReconCrew.et.meta create mode 100644 addons/core/Prefabs/ERR/ReconHelicopter.et create mode 100644 addons/core/Prefabs/ERR/ReconHelicopter.et.meta create mode 100644 addons/core/Prefabs/ERR/ReconPilotEast.et create mode 100644 addons/core/Prefabs/ERR/ReconPilotEast.et.meta create mode 100644 addons/core/Prefabs/ERR/ReconPilotWest.et create mode 100644 addons/core/Prefabs/ERR/ReconPilotWest.et.meta create mode 100644 addons/core/Prefabs/ERR/ScoutEast.et create mode 100644 addons/core/Prefabs/ERR/ScoutEast.et.meta create mode 100644 addons/core/Prefabs/ERR/ScoutGroup.et create mode 100644 addons/core/Prefabs/ERR/ScoutGroup.et.meta create mode 100644 addons/core/Prefabs/ERR/ScoutRadioPack.et create mode 100644 addons/core/Prefabs/ERR/ScoutRadioPack.et.meta create mode 100644 addons/core/Prefabs/ERR/ScoutWest.et create mode 100644 addons/core/Prefabs/ERR/ScoutWest.et.meta create mode 100644 addons/core/Scripts/Game/ERR/00_Core/ERR_AirfieldPlacement.c create mode 100644 addons/core/Scripts/Game/ERR/00_Core/ERR_ContentDefinition.c create mode 100644 addons/core/Scripts/Game/ERR/00_Core/ERR_ContentMenu.c create mode 100644 addons/core/Scripts/Game/ERR/00_Core/ERR_ContentPolicy.c create mode 100644 addons/core/Scripts/Game/ERR/00_Core/ERR_ContentSettings.c create mode 100644 addons/core/Scripts/Game/ERR/00_Core/ERR_DebugAI.c create mode 100644 addons/core/Scripts/Game/ERR/00_Core/ERR_DebugIntel.c create mode 100644 addons/core/Scripts/Game/ERR/00_Core/ERR_FactionMenu.c create mode 100644 addons/core/Scripts/Game/ERR/00_Core/ERR_FactionSelection.c create mode 100644 addons/core/Scripts/Game/ERR/00_Core/ERR_GeneratedSites.c create mode 100644 addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAggressionProbe.c create mode 100644 addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAirfieldMarkersProbe.c create mode 100644 addons/core/Scripts/Game/ERR/00_Core/ERR_NativeContentProbe.c create mode 100644 addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFactionSelectionProbe.c create mode 100644 addons/core/Scripts/Game/ERR/00_Core/ERR_NativeGeneratedSitesProbe.c create mode 100644 addons/core/Scripts/Game/ERR/00_Core/ERR_NativeOpeningToolsProbe.c create mode 100644 addons/core/Scripts/Game/ERR/00_Core/ERR_NativeRadioCampProbe.c create mode 100644 addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonPatrol.c create mode 100644 addons/core/Scripts/Game/ERR/10_AI/ERR_AirAmmoMission.c create mode 100644 addons/core/Scripts/Game/ERR/10_AI/ERR_AirAssaultLoad.c create mode 100644 addons/core/Scripts/Game/ERR/10_AI/ERR_AirAssaultSystem.c create mode 100644 addons/core/Scripts/Game/ERR/10_AI/ERR_AirReconSystem.c create mode 100644 addons/core/Scripts/Game/ERR/10_AI/ERR_AirSupportPolicy.c create mode 100644 addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftAmmo.c create mode 100644 addons/core/Scripts/Game/ERR/10_AI/ERR_AirfieldSupport.c create mode 100644 addons/core/Scripts/Game/ERR/10_AI/ERR_AssaultParachute.c create mode 100644 addons/core/Scripts/Game/ERR/10_AI/ERR_BodyRecovery.c create mode 100644 addons/core/Scripts/Game/ERR/10_AI/ERR_EnemySkillAwareness.c create mode 100644 addons/core/Scripts/Game/ERR/10_AI/ERR_HunterService.c create mode 100644 addons/core/Scripts/Game/ERR/10_AI/ERR_MortarStation.c create mode 100644 addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirAssaultProbe.c create mode 100644 addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirLogisticsProbe.c create mode 100644 addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirReconProbe.c create mode 100644 addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarStationProbe.c create mode 100644 addons/core/Scripts/Game/ERR/10_AI/ERR_NativeScoutProbe.c create mode 100644 addons/core/Scripts/Game/ERR/10_AI/ERR_ObjectiveDefence.c create mode 100644 addons/core/Scripts/Game/ERR/10_AI/ERR_ReconAirports.c create mode 100644 addons/core/Scripts/Game/ERR/10_AI/ERR_ReconCrewLocks.c create mode 100644 addons/core/Scripts/Game/ERR/10_AI/ERR_ReconFlightComponent.c create mode 100644 addons/core/Scripts/Game/ERR/10_AI/ERR_ScoutSystem.c create mode 100644 addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoyService.c create mode 100644 addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoySystem.c create mode 100644 addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoyTactics.c create mode 100644 addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelEvidence.c create mode 100644 addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSupplyConvoyProbe.c create mode 100644 addons/core/UI/layouts/ERR/AdminValue.layout create mode 100644 addons/core/UI/layouts/ERR/AdminValue.layout.meta create mode 100644 addons/core/UI/layouts/ERR/ContentRow.layout create mode 100644 addons/core/UI/layouts/ERR/ContentRow.layout.meta create mode 100644 addons/core/UI/layouts/ERR/PauseModsButton.layout create mode 100644 addons/core/UI/layouts/ERR/PauseModsButton.layout.meta create mode 100644 docs/aggression-ai.md create mode 100644 docs/airfield-extraction-and-map-icons.md create mode 100644 docs/content-packs.md create mode 100644 docs/evidence/admin-pages-2026-09-22/README.md create mode 100644 docs/evidence/admin-pages-2026-09-22/native-menu-checks.txt create mode 100644 docs/evidence/admin-pages-2026-09-22/page-0.png create mode 100644 docs/evidence/admin-pages-2026-09-22/page-1.png create mode 100644 docs/evidence/admin-pages-2026-09-22/page-2.png create mode 100644 docs/evidence/admin-pages-2026-09-22/page-3.png create mode 100644 docs/evidence/admin-pages-2026-09-22/page-4.png create mode 100644 docs/evidence/admin-pages-2026-09-22/page-5.png create mode 100644 docs/evidence/admin-pages-2026-09-22/page-6.png create mode 100644 docs/evidence/admin-pages-2026-09-22/page-7.png create mode 100644 docs/evidence/admin-pages-2026-09-22/repository-checks.txt create mode 100644 docs/evidence/admin-pages-2026-09-22/sources.json create mode 100644 docs/evidence/hq-air-support-2026-09-22/README.md create mode 100644 docs/evidence/hq-air-support-2026-09-22/airborne-native5-excerpt.log create mode 100644 docs/evidence/hq-air-support-2026-09-22/airborne-native5-source-sha256.json create mode 100644 docs/evidence/hq-air-support-2026-09-22/cargo-native7-excerpt.log create mode 100644 docs/evidence/hq-air-support-2026-09-22/cargo-native7-source-sha256.json create mode 100644 docs/evidence/hq-air-support-2026-09-22/recovery-native3-excerpt.log create mode 100644 docs/evidence/hq-air-support-2026-09-22/recovery-native3-source-sha256.json create mode 100644 docs/generated-sites.md create mode 100644 docs/hill-scouts.md create mode 100644 docs/hq-air-support.md create mode 100644 docs/mortar-intel-and-prison-map.md create mode 100644 docs/mortar-stations.md create mode 100644 docs/prison-patrol-and-debug-intel.md create mode 100644 docs/radio-camp-security.md create mode 100644 docs/search-helicopter.md create mode 100644 docs/supply-convoys.md create mode 100644 tests/test_air_logistics_orders.py create mode 100644 tests/test_air_recon.py create mode 100644 tests/test_air_support_policy.py create mode 100644 tests/test_content_policy.py create mode 100644 tests/test_debug_ai.py create mode 100644 tests/test_enemy_awareness.py create mode 100644 tests/test_faction_selection.py create mode 100644 tests/test_generated_sites.py create mode 100644 tests/test_hunter_lifecycle.py create mode 100644 tests/test_intel_body_inspection.py create mode 100644 tests/test_mortar_station.py create mode 100644 tests/test_random_settings.py create mode 100644 tests/test_scouts.py create mode 100644 tests/test_supply_convoys.py diff --git a/addons/core/Configs/ERR/Content/Registry.conf b/addons/core/Configs/ERR/Content/Registry.conf new file mode 100644 index 0000000..9879164 --- /dev/null +++ b/addons/core/Configs/ERR/Content/Registry.conf @@ -0,0 +1,34 @@ +ERR_ContentDefinition { + Options { + ERR_ContentOption { + Id "rhs" + Label "RHS: Status Quo" + DefaultEnabled 1 + EquipmentGuids { "A1D5833FF10C6503" "695AAA77F84EB238" "333A794F0B55C019" "8D4BAA235F7EDBEA" } + } + ERR_ContentOption { + Id "rhs_usmc" + Label "RHS / US Marines" + Parent "rhs" + DefaultEnabled 1 + NativeFactionKey "RHS_USAF" + GuardGroup "{19843E954790DF28}Prefabs/Groups/BLUFOR/RHS_USAF/RHS_USAF_USMC_MEF/Group_USAF_USMC_MEF_FireTeam.et" + } + ERR_ContentOption { + Id "rhs_afrf" + Label "RHS / Russian Armed Forces" + Parent "rhs" + DefaultEnabled 1 + NativeFactionKey "RHS_AFRF" + GuardGroup "{AB905EF799E0A0AE}Prefabs/Groups/OPFOR/RHS_AFRF/MSV/Flora/Group_RHS_RF_MSV_Flora_FireGroup.et" + } + ERR_ContentOption { + Id "rhs_ion" + Label "RHS / ION" + Parent "rhs" + DefaultEnabled 1 + NativeFactionKey "RHS_ION" + GuardGroup "{516C8C7400DF2C4D}Prefabs/Groups/INDFOR/RHS_ION/RHS_ION_COY/Group_RHS_ION_COY_StaticSecurityTeam.et" + } + } +} diff --git a/addons/core/Configs/ERR/Content/Registry.conf.meta b/addons/core/Configs/ERR/Content/Registry.conf.meta new file mode 100644 index 0000000..d2a2d26 --- /dev/null +++ b/addons/core/Configs/ERR/Content/Registry.conf.meta @@ -0,0 +1,7 @@ +MetaFileClass { + Name "{64BF38F9F92CE016}Configs/ERR/Content/Registry.conf" + Configurations { + ResourceClass PC { } + ResourceClass HEADLESS : PC { } + } +} diff --git a/addons/core/Configs/ERR/EveronSites.conf b/addons/core/Configs/ERR/EveronSites.conf index acac538..3b3c6fd 100644 --- a/addons/core/Configs/ERR/EveronSites.conf +++ b/addons/core/Configs/ERR/EveronSites.conf @@ -1,15 +1,17 @@ ERR_ScenarioDefinition { MinimumRadioSources 2 + ScoutCount 10 Sites { ERR_SiteDefinition { Id "everon-prison-1" + RandomClear 1 Label "Prison" Kind 0 Prefab "{BE6B8D56349038A6}Prefabs/ERR/Prison.et" Position 6090 0 7160 Guarded 1 GuardOffset 35 0 0 - Container "{40986810D0B1F4AE}Prefabs/ERR/SupplyCache.et" + Container "{D93480F29E73C1AB}Prefabs/ERR/PrisonBackpack.et" ContainerOffset -4 0 0 Stock { ERR_SiteStock { Prefab "{C0F7DD85A86B2900}Prefabs/Weapons/Handguns/PM/Handgun_PM.et" Count 5 } @@ -19,6 +21,7 @@ ERR_ScenarioDefinition { } ERR_SiteDefinition { Id "everon-supply-1" + AllowFactionPool 1 Label "Southern supply cache" Kind 4 Prefab "{7C3D16C17C24D351}Prefabs/ERR/SupplySite.et" @@ -38,11 +41,20 @@ ERR_ScenarioDefinition { } ERR_SiteDefinition { Id "everon-radio-1" + RandomClear 1 + RootHeight 0.8 Label "Radio station" DiscoverRadius 8 Kind 1 - Prefab "{F7E7E3D6ACF0C860}Prefabs/ERR/Radio.et" + Prefab "{47D725F56A904ACE}Prefabs/ERR/RadioCamp.et" Position 6500 0 7200 + Props { + ERR_SiteProp { Prefab "{53506DCB398C7EBE}Prefabs/Props/Furniture/Table_01.et" Offset 0 0 0 } + ERR_SiteProp { Prefab "{B3949F6D215A9F78}Prefabs/Props/Military/Antennas/Antenna_FIA_02/Antenna_FIA_02_base.et" Offset -7 0 2 } + ERR_SiteProp { Prefab "{BE5D5CFA90224646}Prefabs/Structures/Military/Camps/TentUSSR_01/TentUSSR_01_base.et" Offset -1.5 0 0 } + ERR_SiteProp { Prefab "{CFFEB23FBEA00322}Prefabs/Props/Military/Sandbags/Sandbag_01_short_burlap.et" Offset -4.5 0 -6 } + ERR_SiteProp { Prefab "{CFFEB23FBEA00322}Prefabs/Props/Military/Sandbags/Sandbag_01_short_burlap.et" Offset 4.5 0 -6 } + } Guarded 1 GuardOffset 30 0 0 } @@ -51,44 +63,12 @@ ERR_ScenarioDefinition { Label "Initial helicopter pickup site" Kind 2 Prefab "{033503110AC34EAC}Prefabs/ERR/Extraction.et" - Position 7000 0 7500 + Position 4800.953 0 11487.412 + AircraftOffset 0 0 0 + RequireAirfield 1 Guarded 1 GuardOffset 30 0 0 } - ERR_SiteDefinition { - Id "everon-supply-2" - Label "Western supply cache (vehicle maintenance)" - Kind 4 - Prefab "{7C3D16C17C24D351}Prefabs/ERR/SupplySite.et" - Position 5960 0 7220 - Guarded 1 - GuardOffset 16 0 0 - Patrol { - ERR_SitePatrolPoint { Offset 18 0 0 } - ERR_SitePatrolPoint { Offset 18 0 24 } - ERR_SitePatrolPoint { Offset -6 0 24 } - ERR_SitePatrolPoint { Offset -6 0 0 } - } - Container "{40986810D0B1F4AE}Prefabs/ERR/SupplyCache.et" - DiscoverRadius 25 - RevealOnEscape 1 - Transport ERR_SiteTransport { - Prefab "{FA65287C19DE304B}Prefabs/ERR/Vehicles/SupplyUAZ.et" - Offset 0 0 -8 - Heading 180 - ClearanceRadius 4 - MaximumTerrainRange 1 - } - Stock { - ERR_SiteStock { Prefab "{C09C7C97EFA34909}Prefabs/ERR/Items/EmergencyRepairKit.et" Count 1 } - ERR_SiteStock { Prefab "{12D5AD21E383B768}Prefabs/Items/Fuel/Jerrycan_01/Jerrycan_01_item.et" Count 2 } - ERR_SiteStock { Prefab "{FA5C25BF66A53DCF}Prefabs/Weapons/Rifles/AK74/Rifle_AK74.et" Count 4 } - ERR_SiteStock { Prefab "{BBB50A815A2F916B}Prefabs/Weapons/Magazines/Magazine_545x39_AK_30rnd_Ball.et" Count 8 } - ERR_SiteStock { Prefab "{C3F1FA1E2EC2B345}Prefabs/Items/Medicine/FieldDressing_01/FieldDressing_USSR_01.et" Count 6 } - ERR_SiteStock { Prefab "{13772C903CB5E4F7}Prefabs/Items/Equipment/Maps/Map_Paper_01/PaperMap_01_folded.et" Count 1 } - ERR_SiteStock { Prefab "{554159A6740C3F3E}Prefabs/ERR/ObjectiveDocument.et" Count 2 TargetId "everon-radio-1" } - } - } ERR_SiteDefinition { Id "everon-medical-1" Label "Medical stash" @@ -99,8 +79,9 @@ ERR_ScenarioDefinition { GuardOffset 16 0 0 Container "{40986810D0B1F4AE}Prefabs/ERR/SupplyCache.et" DiscoverRadius 25 - RevealOnEscape 0 + RevealOnEscape 1 Stock { + ERR_SiteStock { Prefab "{554159A6740C3F3E}Prefabs/ERR/ObjectiveDocument.et" Count 2 TargetId "everon-radio-1" } ERR_SiteStock { Prefab "{C3F1FA1E2EC2B345}Prefabs/Items/Medicine/FieldDressing_01/FieldDressing_USSR_01.et" Count 12 } ERR_SiteStock { Prefab "{527D7C5D2E476BDC}Prefabs/Items/Medicine/SalineBag_01/SalineBag_USSR_01.et" Count 6 } ERR_SiteStock { Prefab "{0D9A5DCF89AE7AA9}Prefabs/Items/Medicine/MorphineInjection_01/MorphineInjection_01.et" Count 6 } @@ -136,5 +117,41 @@ ERR_ScenarioDefinition { ERR_SiteProp { Prefab "{4B6AC1D8701C35A1}Prefabs/ERR/FieldCover.et" Offset 4 0 0 Angles 90 0 0 } } } + ERR_SiteDefinition { + Id "everon-mortar-1" + Label "Mortar site 1" + Kind 5 + Prefab "{7C3D16C17C24D351}Prefabs/ERR/SupplySite.et" + Position 6000 0 7000 + RandomClear 1 + DiscoverRadius 35 + } + ERR_SiteDefinition { + Id "everon-mortar-2" + Label "Mortar site 2" + Kind 5 + Prefab "{7C3D16C17C24D351}Prefabs/ERR/SupplySite.et" + Position 4500 0 6500 + RandomClear 1 + DiscoverRadius 35 + } + ERR_SiteDefinition { + Id "everon-mortar-3" + Label "Mortar site 3" + Kind 5 + Prefab "{7C3D16C17C24D351}Prefabs/ERR/SupplySite.et" + Position 7000 0 9500 + RandomClear 1 + DiscoverRadius 35 + } + ERR_SiteDefinition { + Id "everon-mortar-4" + Label "Mortar site 4" + Kind 5 + Prefab "{7C3D16C17C24D351}Prefabs/ERR/SupplySite.et" + Position 4000 0 10500 + RandomClear 1 + DiscoverRadius 35 + } } } diff --git a/addons/core/Configs/ERR/Tests/LegacySites.conf b/addons/core/Configs/ERR/Tests/LegacySites.conf new file mode 100644 index 0000000..8ce639b --- /dev/null +++ b/addons/core/Configs/ERR/Tests/LegacySites.conf @@ -0,0 +1,152 @@ +ERR_ScenarioDefinition { + MinimumRadioSources 2 + Sites { + ERR_SiteDefinition { + Id "everon-prison-1" + RandomClear 1 + Label "Prison" + Kind 0 + Prefab "{BE6B8D56349038A6}Prefabs/ERR/Prison.et" + Position 6090 0 7160 + Guarded 1 + GuardOffset 35 0 0 + Container "{D93480F29E73C1AB}Prefabs/ERR/PrisonBackpack.et" + ContainerOffset -4 0 0 + Stock { + ERR_SiteStock { Prefab "{C0F7DD85A86B2900}Prefabs/Weapons/Handguns/PM/Handgun_PM.et" Count 5 } + ERR_SiteStock { Prefab "{8B853CDD11BA916E}Prefabs/Weapons/Magazines/Magazine_9x18_PM_8rnd_Ball.et" Count 8 } + ERR_SiteStock { Prefab "{13772C903CB5E4F7}Prefabs/Items/Equipment/Maps/Map_Paper_01/PaperMap_01_folded.et" Count 1 } + } + } + ERR_SiteDefinition { + Id "everon-supply-1" + AllowFactionPool 1 + Label "Southern supply cache" + Kind 4 + Prefab "{7C3D16C17C24D351}Prefabs/ERR/SupplySite.et" + Position 6150 0 7050 + Guarded 1 + GuardOffset 18 0 0 + Container "{40986810D0B1F4AE}Prefabs/ERR/SupplyCache.et" + ContainerOffset 0 0 0 + Stock { + ERR_SiteStock { Prefab "{FA5C25BF66A53DCF}Prefabs/Weapons/Rifles/AK74/Rifle_AK74.et" Count 8 } + ERR_SiteStock { Prefab "{BBB50A815A2F916B}Prefabs/Weapons/Magazines/Magazine_545x39_AK_30rnd_Ball.et" Count 16 } + ERR_SiteStock { Prefab "{C3F1FA1E2EC2B345}Prefabs/Items/Medicine/FieldDressing_01/FieldDressing_USSR_01.et" Count 12 } + ERR_SiteStock { Prefab "{13772C903CB5E4F7}Prefabs/Items/Equipment/Maps/Map_Paper_01/PaperMap_01_folded.et" Count 1 } + ERR_SiteStock { Prefab "{554159A6740C3F3E}Prefabs/ERR/ObjectiveDocument.et" Count 2 TargetId "everon-radio-1" } + } + RevealOnEscape 1 + } + ERR_SiteDefinition { + Id "everon-radio-1" + RandomClear 1 + RootHeight 0.8 + Label "Radio station" + DiscoverRadius 8 + Kind 1 + Prefab "{47D725F56A904ACE}Prefabs/ERR/RadioCamp.et" + Position 6500 0 7200 + Props { + ERR_SiteProp { Prefab "{53506DCB398C7EBE}Prefabs/Props/Furniture/Table_01.et" Offset 0 0 0 } + ERR_SiteProp { Prefab "{B3949F6D215A9F78}Prefabs/Props/Military/Antennas/Antenna_FIA_02/Antenna_FIA_02_base.et" Offset -4 0 2 } + ERR_SiteProp { Prefab "{01AE5FD77A9A4C21}Prefabs/Structures/Military/Camps/TentSmallUS_01/TentSmallUS_01.et" Offset 4 0 3 } + ERR_SiteProp { Prefab "{CFFEB23FBEA00322}Prefabs/Props/Military/Sandbags/Sandbag_01_short_burlap.et" Offset -3 0 -4 } + ERR_SiteProp { Prefab "{CFFEB23FBEA00322}Prefabs/Props/Military/Sandbags/Sandbag_01_short_burlap.et" Offset 3 0 -4 } + } + Guarded 1 + GuardOffset 30 0 0 + } + ERR_SiteDefinition { + Id "everon-extraction-1" + Label "Initial helicopter pickup site" + Kind 2 + Prefab "{033503110AC34EAC}Prefabs/ERR/Extraction.et" + Position 7000 0 7500 + Guarded 1 + GuardOffset 30 0 0 + } + ERR_SiteDefinition { + Id "everon-supply-2" + AllowFactionPool 1 + Label "Western supply cache (vehicle maintenance)" + Kind 4 + Prefab "{7C3D16C17C24D351}Prefabs/ERR/SupplySite.et" + Position 5960 0 7220 + Guarded 1 + GuardOffset 16 0 0 + Patrol { + ERR_SitePatrolPoint { Offset 18 0 0 } + ERR_SitePatrolPoint { Offset 18 0 24 } + ERR_SitePatrolPoint { Offset -6 0 24 } + ERR_SitePatrolPoint { Offset -6 0 0 } + } + Container "{40986810D0B1F4AE}Prefabs/ERR/SupplyCache.et" + DiscoverRadius 25 + RevealOnEscape 1 + Transport ERR_SiteTransport { + Prefab "{FA65287C19DE304B}Prefabs/ERR/Vehicles/SupplyUAZ.et" + Offset 0 0 -8 + Heading 180 + ClearanceRadius 4 + MaximumTerrainRange 1 + } + Stock { + ERR_SiteStock { Prefab "{C09C7C97EFA34909}Prefabs/ERR/Items/EmergencyRepairKit.et" Count 1 } + ERR_SiteStock { Prefab "{12D5AD21E383B768}Prefabs/Items/Fuel/Jerrycan_01/Jerrycan_01_item.et" Count 2 } + ERR_SiteStock { Prefab "{FA5C25BF66A53DCF}Prefabs/Weapons/Rifles/AK74/Rifle_AK74.et" Count 4 } + ERR_SiteStock { Prefab "{BBB50A815A2F916B}Prefabs/Weapons/Magazines/Magazine_545x39_AK_30rnd_Ball.et" Count 8 } + ERR_SiteStock { Prefab "{C3F1FA1E2EC2B345}Prefabs/Items/Medicine/FieldDressing_01/FieldDressing_USSR_01.et" Count 6 } + ERR_SiteStock { Prefab "{13772C903CB5E4F7}Prefabs/Items/Equipment/Maps/Map_Paper_01/PaperMap_01_folded.et" Count 1 } + ERR_SiteStock { Prefab "{554159A6740C3F3E}Prefabs/ERR/ObjectiveDocument.et" Count 2 TargetId "everon-radio-1" } + } + } + ERR_SiteDefinition { + Id "everon-medical-1" + Label "Medical stash" + Kind 4 + Prefab "{7C3D16C17C24D351}Prefabs/ERR/SupplySite.et" + Position 6340 0 7400 + Guarded 0 + GuardOffset 16 0 0 + Container "{40986810D0B1F4AE}Prefabs/ERR/SupplyCache.et" + DiscoverRadius 25 + RevealOnEscape 0 + Stock { + ERR_SiteStock { Prefab "{C3F1FA1E2EC2B345}Prefabs/Items/Medicine/FieldDressing_01/FieldDressing_USSR_01.et" Count 12 } + ERR_SiteStock { Prefab "{527D7C5D2E476BDC}Prefabs/Items/Medicine/SalineBag_01/SalineBag_USSR_01.et" Count 6 } + ERR_SiteStock { Prefab "{0D9A5DCF89AE7AA9}Prefabs/Items/Medicine/MorphineInjection_01/MorphineInjection_01.et" Count 6 } + ERR_SiteStock { Prefab "{13772C903CB5E4F7}Prefabs/Items/Equipment/Maps/Map_Paper_01/PaperMap_01_folded.et" Count 3 } + } + } + ERR_SiteDefinition { + Id "everon-outpost-1" + Label "Eastern guard outpost" + Kind 3 + Prefab "{7C3D16C17C24D351}Prefabs/ERR/SupplySite.et" + Position 6740 0 7300 + Guarded 1 + GuardOffset 16 0 0 + Patrol { + ERR_SitePatrolPoint { Offset 18 0 0 } + ERR_SitePatrolPoint { Offset 18 0 24 } + ERR_SitePatrolPoint { Offset -6 0 24 } + ERR_SitePatrolPoint { Offset -6 0 0 } + } + Container "{40986810D0B1F4AE}Prefabs/ERR/SupplyCache.et" + DiscoverRadius 35 + RevealOnEscape 0 + Stock { + ERR_SiteStock { Prefab "{FA5C25BF66A53DCF}Prefabs/Weapons/Rifles/AK74/Rifle_AK74.et" Count 2 } + ERR_SiteStock { Prefab "{BBB50A815A2F916B}Prefabs/Weapons/Magazines/Magazine_545x39_AK_30rnd_Ball.et" Count 10 } + ERR_SiteStock { Prefab "{243948B23D90BECB}Prefabs/Items/Equipment/Binoculars/Binoculars_B8/Binoculars_B8.et" Count 2 } + ERR_SiteStock { Prefab "{C3F1FA1E2EC2B345}Prefabs/Items/Medicine/FieldDressing_01/FieldDressing_USSR_01.et" Count 4 } + } + Props { + ERR_SiteProp { Prefab "{4B6AC1D8701C35A1}Prefabs/ERR/FieldCover.et" Offset 0 0 -4 } + ERR_SiteProp { Prefab "{4B6AC1D8701C35A1}Prefabs/ERR/FieldCover.et" Offset -4 0 0 Angles 90 0 0 } + ERR_SiteProp { Prefab "{4B6AC1D8701C35A1}Prefabs/ERR/FieldCover.et" Offset 4 0 0 Angles 90 0 0 } + } + } + } +} diff --git a/addons/core/Configs/ERR/Tests/LegacySites.conf.meta b/addons/core/Configs/ERR/Tests/LegacySites.conf.meta new file mode 100644 index 0000000..f8fc44b --- /dev/null +++ b/addons/core/Configs/ERR/Tests/LegacySites.conf.meta @@ -0,0 +1,7 @@ +MetaFileClass { + Name "{ACA98B44E2173605}Configs/ERR/Tests/LegacySites.conf" + Configurations { + ResourceClass PC {} + ResourceClass HEADLESS : PC {} + } +} diff --git a/addons/core/Prefabs/ERR/AssaultParachute.et b/addons/core/Prefabs/ERR/AssaultParachute.et new file mode 100644 index 0000000..6c87bbc --- /dev/null +++ b/addons/core/Prefabs/ERR/AssaultParachute.et @@ -0,0 +1,10 @@ +ERR_AssaultParachute : "{9ADD554959C09197}Prefabs/DeployedParachutes/Core/DeployedParachuteMK4.et" { + ID "C31F210ABE0781A1" + components { + SCR_AIVehicleUsageComponent "{C31F210ABE0781A2}" { + m_eVehicleType AIRCRAFT_HELICOPTER + m_bCanBePiloted 0 + } + } + m_DebugMode 0 +} diff --git a/addons/core/Prefabs/ERR/AssaultParachute.et.meta b/addons/core/Prefabs/ERR/AssaultParachute.et.meta new file mode 100644 index 0000000..cfdaeb2 --- /dev/null +++ b/addons/core/Prefabs/ERR/AssaultParachute.et.meta @@ -0,0 +1,7 @@ +MetaFileClass { + Name "{C31F210ABE0781A0}Prefabs/ERR/AssaultParachute.et" + Configurations { + EntityTemplateResourceClass PC {} + EntityTemplateResourceClass HEADLESS {} + } +} diff --git a/addons/core/Prefabs/ERR/FactionManager.et b/addons/core/Prefabs/ERR/FactionManager.et index d944b02..c55544a 100644 --- a/addons/core/Prefabs/ERR/FactionManager.et +++ b/addons/core/Prefabs/ERR/FactionManager.et @@ -1,11 +1,27 @@ SCR_FactionManager : "{A242612865F2A48E}Prefabs/MP/Managers/Factions/FactionManager_Base.et" { ID "9D8B772E349A5ED5" + m_bCanChangeFactionsPlayable 1 Factions { + SCR_Faction : "{8053DB656DD18B14}Configs/Factions/FIA.conf" { + m_aFriendlyFactionsIds { } + } SCR_Faction : "{5C67A1DDE0044806}Configs/ERR/Factions/US.conf" { m_sFactionBackground "{F8AC305446D5D480}UI/Textures/DeployMenu/Loadout-BG/Loadout_US_BG.imageset" } SCR_Faction : "{D7A5CFA62A36480D}Configs/ERR/Factions/USSR.conf" { m_sFactionBackground "{21533F2089005056}UI/Textures/DeployMenu/Loadout-BG/Loadout_BG_USSR.imageset" } + SCR_Faction : "{F33C7BF22CBF3A8A}Configs/Factions/RHS_US_USMC.conf" { + m_aFriendlyFactionsIds { } + m_bIsPlayable 0 + } + SCR_Faction : "{627A8CDE681D223D}Configs/Factions/RHS_RF_MSV.conf" { + m_aFriendlyFactionsIds { } + m_bIsPlayable 0 + } + SCR_Faction : "{CB76A36EACFBDF35}Configs/Factions/RHS_ION.conf" { + m_aFriendlyFactionsIds { } + m_bIsPlayable 0 + } } } diff --git a/addons/core/Prefabs/ERR/PrisonBackpack.et b/addons/core/Prefabs/ERR/PrisonBackpack.et new file mode 100644 index 0000000..309e68c --- /dev/null +++ b/addons/core/Prefabs/ERR/PrisonBackpack.et @@ -0,0 +1,7 @@ +GenericEntity : "{41A9C55B61F375F0}Prefabs/Items/Equipment/Backpacks/Backpack_Kolobok.et" { + ID "ED14790A26F68453" + components { + InventoryStorageManagerComponent "{BF182CDF2D660373}" { + } + } +} diff --git a/addons/core/Prefabs/ERR/PrisonBackpack.et.meta b/addons/core/Prefabs/ERR/PrisonBackpack.et.meta new file mode 100644 index 0000000..89dd379 --- /dev/null +++ b/addons/core/Prefabs/ERR/PrisonBackpack.et.meta @@ -0,0 +1,9 @@ +MetaFileClass { + Name "{D93480F29E73C1AB}Prefabs/ERR/PrisonBackpack.et" + Configurations { + ResourceClass PC { + } + ResourceClass HEADLESS : PC { + } + } +} diff --git a/addons/core/Prefabs/ERR/PrisonPatrol.et b/addons/core/Prefabs/ERR/PrisonPatrol.et new file mode 100644 index 0000000..efde958 --- /dev/null +++ b/addons/core/Prefabs/ERR/PrisonPatrol.et @@ -0,0 +1,7 @@ +SCR_AIGroup : "{000CD338713F2B5A}Prefabs/AI/Groups/Group_Base.et" { + ID "B3AC840A219FD076" + m_faction "USSR" + m_bSpawnImmediately 0 + m_aUnitPrefabSlots { + } +} diff --git a/addons/core/Prefabs/ERR/PrisonPatrol.et.meta b/addons/core/Prefabs/ERR/PrisonPatrol.et.meta new file mode 100644 index 0000000..5e91185 --- /dev/null +++ b/addons/core/Prefabs/ERR/PrisonPatrol.et.meta @@ -0,0 +1,7 @@ +MetaFileClass { + Name "{EC9F1AA42D0B7863}Prefabs/ERR/PrisonPatrol.et" + Configurations { + EntityTemplateResourceClass PC {} + EntityTemplateResourceClass HEADLESS {} + } +} diff --git a/addons/core/Prefabs/ERR/RadioCamp.et b/addons/core/Prefabs/ERR/RadioCamp.et new file mode 100644 index 0000000..8d8b3b6 --- /dev/null +++ b/addons/core/Prefabs/ERR/RadioCamp.et @@ -0,0 +1,3 @@ +GenericEntity : "{F7E7E3D6ACF0C860}Prefabs/ERR/Radio.et" { + ID "B7AD3B63842692C1" +} diff --git a/addons/core/Prefabs/ERR/RadioCamp.et.meta b/addons/core/Prefabs/ERR/RadioCamp.et.meta new file mode 100644 index 0000000..af5c238 --- /dev/null +++ b/addons/core/Prefabs/ERR/RadioCamp.et.meta @@ -0,0 +1,7 @@ +MetaFileClass { + Name "{47D725F56A904ACE}Prefabs/ERR/RadioCamp.et" + Configurations { + EntityTemplateResourceClass PC {} + EntityTemplateResourceClass HEADLESS : PC {} + } +} diff --git a/addons/core/Prefabs/ERR/ReconCrew.et b/addons/core/Prefabs/ERR/ReconCrew.et new file mode 100644 index 0000000..8aa349b --- /dev/null +++ b/addons/core/Prefabs/ERR/ReconCrew.et @@ -0,0 +1,7 @@ +SCR_AIGroup : "{000CD338713F2B5A}Prefabs/AI/Groups/Group_Base.et" { + ID "C31F210ABE078196" + m_faction "USSR" + m_bSpawnImmediately 0 + m_aUnitPrefabSlots { + } +} diff --git a/addons/core/Prefabs/ERR/ReconCrew.et.meta b/addons/core/Prefabs/ERR/ReconCrew.et.meta new file mode 100644 index 0000000..12dde5b --- /dev/null +++ b/addons/core/Prefabs/ERR/ReconCrew.et.meta @@ -0,0 +1,7 @@ +MetaFileClass { + Name "{C31F210ABE078195}Prefabs/ERR/ReconCrew.et" + Configurations { + EntityTemplateResourceClass PC {} + EntityTemplateResourceClass HEADLESS {} + } +} diff --git a/addons/core/Prefabs/ERR/ReconHelicopter.et b/addons/core/Prefabs/ERR/ReconHelicopter.et new file mode 100644 index 0000000..b9d6c49 --- /dev/null +++ b/addons/core/Prefabs/ERR/ReconHelicopter.et @@ -0,0 +1,14 @@ +Vehicle : "{7BD282AF716ED639}Prefabs/Vehicles/Helicopters/Mi8MT/Mi8MT_armed.et" { + ID "C31F210ABE078193" + components { + ERR_ReconFlightComponent "{C31F210ABE078194}" { + } + VehicleHelicopterSimulation "{51FAEE57F7DA270E}" { + Simulation Helicopter "{51FAED9EF37A2D29}" { + Engine HelicopterEngine "{51FAED9EF37A2D2B}" { + StartUpTime 0 + } + } + } + } +} diff --git a/addons/core/Prefabs/ERR/ReconHelicopter.et.meta b/addons/core/Prefabs/ERR/ReconHelicopter.et.meta new file mode 100644 index 0000000..cd7a19e --- /dev/null +++ b/addons/core/Prefabs/ERR/ReconHelicopter.et.meta @@ -0,0 +1,7 @@ +MetaFileClass { + Name "{C31F210ABE078192}Prefabs/ERR/ReconHelicopter.et" + Configurations { + EntityTemplateResourceClass PC {} + EntityTemplateResourceClass HEADLESS {} + } +} diff --git a/addons/core/Prefabs/ERR/ReconPilotEast.et b/addons/core/Prefabs/ERR/ReconPilotEast.et new file mode 100644 index 0000000..1e7e5bf --- /dev/null +++ b/addons/core/Prefabs/ERR/ReconPilotEast.et @@ -0,0 +1,12 @@ +SCR_ChimeraCharacter : "{A62FA97C4EC64F14}Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_HeliPilot.et" { + ID "C31F210ABE078198" + components { + BaseLoadoutManagerComponent "{520EA1D2DB11821E}" { + Slots { + LoadoutSlotInfo Back { + Prefab "{54C68E438DD34265}Prefabs/Items/Equipment/Radios/Radio_R107M.et" + } + } + } + } +} diff --git a/addons/core/Prefabs/ERR/ReconPilotEast.et.meta b/addons/core/Prefabs/ERR/ReconPilotEast.et.meta new file mode 100644 index 0000000..c1365a3 --- /dev/null +++ b/addons/core/Prefabs/ERR/ReconPilotEast.et.meta @@ -0,0 +1,7 @@ +MetaFileClass { + Name "{C31F210ABE078197}Prefabs/ERR/ReconPilotEast.et" + Configurations { + EntityTemplateResourceClass PC {} + EntityTemplateResourceClass HEADLESS {} + } +} diff --git a/addons/core/Prefabs/ERR/ReconPilotWest.et b/addons/core/Prefabs/ERR/ReconPilotWest.et new file mode 100644 index 0000000..c8d6d8b --- /dev/null +++ b/addons/core/Prefabs/ERR/ReconPilotWest.et @@ -0,0 +1,12 @@ +SCR_ChimeraCharacter : "{42A502E3BB727CEB}Prefabs/Characters/Factions/BLUFOR/US_Army/Character_US_HeliPilot.et" { + ID "C31F210ABE07819A" + components { + BaseLoadoutManagerComponent "{520EA1D2DB11821E}" { + Slots { + LoadoutSlotInfo Back { + Prefab "{54C68E438DD34265}Prefabs/Items/Equipment/Radios/Radio_R107M.et" + } + } + } + } +} diff --git a/addons/core/Prefabs/ERR/ReconPilotWest.et.meta b/addons/core/Prefabs/ERR/ReconPilotWest.et.meta new file mode 100644 index 0000000..120fb96 --- /dev/null +++ b/addons/core/Prefabs/ERR/ReconPilotWest.et.meta @@ -0,0 +1,7 @@ +MetaFileClass { + Name "{C31F210ABE078199}Prefabs/ERR/ReconPilotWest.et" + Configurations { + EntityTemplateResourceClass PC {} + EntityTemplateResourceClass HEADLESS {} + } +} diff --git a/addons/core/Prefabs/ERR/ScoutEast.et b/addons/core/Prefabs/ERR/ScoutEast.et new file mode 100644 index 0000000..26e6cc2 --- /dev/null +++ b/addons/core/Prefabs/ERR/ScoutEast.et @@ -0,0 +1,23 @@ +SCR_ChimeraCharacter : "{976AC400219898FA}Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_Sharpshooter.et" { + ID "EF871ED195094E29" + components { + SCR_CharacterInventoryStorageComponent "{520EA1D2DB118DAC}" { + components { + SCR_EquipmentStorageComponent "{56B49DA9722B635D}" { + InitialStorageSlots { + SCR_EquipmentStorageSlot BinocularSlot { + Prefab "{243948B23D90BECB}Prefabs/Items/Equipment/Binoculars/Binoculars_B8/Binoculars_B8.et" + } + } + } + } + } + BaseLoadoutManagerComponent "{520EA1D2DB11821E}" { + Slots { + LoadoutSlotInfo Back { + Prefab "{CF862ED195094E23}Prefabs/ERR/ScoutRadioPack.et" + } + } + } + } +} diff --git a/addons/core/Prefabs/ERR/ScoutEast.et.meta b/addons/core/Prefabs/ERR/ScoutEast.et.meta new file mode 100644 index 0000000..bcb0f02 --- /dev/null +++ b/addons/core/Prefabs/ERR/ScoutEast.et.meta @@ -0,0 +1,7 @@ +MetaFileClass { + Name "{CF862ED195094E28}Prefabs/ERR/ScoutEast.et" + Configurations { + EntityTemplateResourceClass PC {} + EntityTemplateResourceClass HEADLESS {} + } +} diff --git a/addons/core/Prefabs/ERR/ScoutGroup.et b/addons/core/Prefabs/ERR/ScoutGroup.et new file mode 100644 index 0000000..1fe336f --- /dev/null +++ b/addons/core/Prefabs/ERR/ScoutGroup.et @@ -0,0 +1,7 @@ +SCR_AIGroup : "{000CD338713F2B5A}Prefabs/AI/Groups/Group_Base.et" { + ID "EF871ED195094E22" + m_faction "USSR" + m_bSpawnImmediately 0 + m_aUnitPrefabSlots { + } +} diff --git a/addons/core/Prefabs/ERR/ScoutGroup.et.meta b/addons/core/Prefabs/ERR/ScoutGroup.et.meta new file mode 100644 index 0000000..5f7f6dc --- /dev/null +++ b/addons/core/Prefabs/ERR/ScoutGroup.et.meta @@ -0,0 +1,7 @@ +MetaFileClass { + Name "{DF862ED195094E21}Prefabs/ERR/ScoutGroup.et" + Configurations { + EntityTemplateResourceClass PC {} + EntityTemplateResourceClass HEADLESS {} + } +} diff --git a/addons/core/Prefabs/ERR/ScoutRadioPack.et b/addons/core/Prefabs/ERR/ScoutRadioPack.et new file mode 100644 index 0000000..525455f --- /dev/null +++ b/addons/core/Prefabs/ERR/ScoutRadioPack.et @@ -0,0 +1,34 @@ +GenericEntity : "{41A9C55B61F375F0}Prefabs/Items/Equipment/Backpacks/Backpack_Kolobok.et" { + ID "EF871ED195094E24" + components { + BaseRadioComponent "{EF871ED195094E25}" { + "Turned on" 1 + Transceivers { + RadioTransceiver "{EF871ED195094E26}" { + ChannelFrequency 48000 + "Transmitting Range" 2000 + "Min tunable frequency" 20000 + "Max tunable frequency" 76000 + "Frequency resolution" 200 + } + } + } + SCR_RadioComponent "{EF871ED195094E27}" { + m_bCanBeHeld 0 + m_iRadioCategory MANPACK + m_iRadioType R107M + } + SCR_UniversalInventoryStorageComponent "{5222CB03A40528FA}" { + Attributes SCR_ItemAttributeCollection "{5222CB039E9715D1}" { + ItemDisplayName UIInfo "{5222CB03904B414C}" { + Name "Scout radio pack" + Description "Long-range field radio with a compartment for spare rifle magazines." + } + ItemPhysAttributes ItemPhysicalAttributes PhysicalAttributes { + Weight 10 + } + } + MaxCumulativeVolume 6000 + } + } +} diff --git a/addons/core/Prefabs/ERR/ScoutRadioPack.et.meta b/addons/core/Prefabs/ERR/ScoutRadioPack.et.meta new file mode 100644 index 0000000..6521a5c --- /dev/null +++ b/addons/core/Prefabs/ERR/ScoutRadioPack.et.meta @@ -0,0 +1,7 @@ +MetaFileClass { + Name "{CF862ED195094E23}Prefabs/ERR/ScoutRadioPack.et" + Configurations { + EntityTemplateResourceClass PC {} + EntityTemplateResourceClass HEADLESS {} + } +} diff --git a/addons/core/Prefabs/ERR/ScoutWest.et b/addons/core/Prefabs/ERR/ScoutWest.et new file mode 100644 index 0000000..960ca7d --- /dev/null +++ b/addons/core/Prefabs/ERR/ScoutWest.et @@ -0,0 +1,23 @@ +SCR_ChimeraCharacter : "{0F6689B491641155}Prefabs/Characters/Factions/BLUFOR/US_Army/Character_US_Sniper.et" { + ID "EF871ED195094E2B" + components { + SCR_CharacterInventoryStorageComponent "{520EA1D2DB118DAC}" { + components { + SCR_EquipmentStorageComponent "{56B49DA9722B635D}" { + InitialStorageSlots { + SCR_EquipmentStorageSlot BinocularSlot { + Prefab "{243948B23D90BECB}Prefabs/Items/Equipment/Binoculars/Binoculars_B8/Binoculars_B8.et" + } + } + } + } + } + BaseLoadoutManagerComponent "{520EA1D2DB11821E}" { + Slots { + LoadoutSlotInfo Back { + Prefab "{CF862ED195094E23}Prefabs/ERR/ScoutRadioPack.et" + } + } + } + } +} diff --git a/addons/core/Prefabs/ERR/ScoutWest.et.meta b/addons/core/Prefabs/ERR/ScoutWest.et.meta new file mode 100644 index 0000000..a0b29b7 --- /dev/null +++ b/addons/core/Prefabs/ERR/ScoutWest.et.meta @@ -0,0 +1,7 @@ +MetaFileClass { + Name "{CF862ED195094E2A}Prefabs/ERR/ScoutWest.et" + Configurations { + EntityTemplateResourceClass PC {} + EntityTemplateResourceClass HEADLESS {} + } +} diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_Actors.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_Actors.c index cba3e85..251753c 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_Actors.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_Actors.c @@ -38,9 +38,27 @@ class ERR_Actors params.TransformMode = ETransformMode.WORLD; Math3D.AnglesToMatrix(angles, params.Transform); params.Transform[3] = position; - return GetGame().SpawnEntityPrefab(resource, GetGame().GetWorld(), params); + IEntity entity = GetGame().SpawnEntityPrefab(resource, GetGame().GetWorld(), params); + ERR_GameMode mode = ERR_GameMode.Get(); + if (mode && mode.FactionSelection() && mode.FactionSelection().Ready() && entity) + { + SCR_AIGroup group = SCR_AIGroup.Cast(entity); + if (group && (prefab.Contains("Prefabs/ERR/ConvoyCrew.et") || prefab.Contains("Prefabs/ERR/MortarCrew.et"))) group.SetFaction(mode.EnemyFaction()); + if (prefab == mode.Factions().PrisonerPrefab) SetFaction(entity, mode.PlayerFaction()); + } + return entity; } + static bool SetFaction(IEntity entity, Faction faction) + { + if (!Replication.IsServer() || !entity || !faction) return false; + // Characters derive directly from the native base, not SCR_FactionAffiliationComponent. + FactionAffiliationComponent affiliation = FactionAffiliationComponent.Cast(entity.FindComponent(FactionAffiliationComponent)); + if (!affiliation) return false; + affiliation.SetAffiliatedFaction(faction); + return affiliation.GetAffiliatedFaction() == faction; + } + static void DeleteSpawned(IEntity entity) { if (!Replication.IsServer() || !entity || Player(entity)) return; diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminMenu.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminMenu.c index 3168352..1fc8d70 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminMenu.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminMenu.c @@ -8,12 +8,12 @@ class ERR_AdminMenuFields { static array Keys() { - return {"radioDefenceSeconds", "aiIntelChancePercent", "intelRevealChancePercent", "startTimeMinutes", "timeMultiplier", "startDateCode", "weatherProfile", "reportIntervalSeconds", "supportSquadLimit", "responseRadiusMetres"}; + return {"radioDefenceSeconds", "aiIntelChancePercent", "intelRevealChancePercent", "startTimeMinutes", "timeMultiplier", "startDateCode", "weatherProfile", "reportIntervalSeconds", "supportSquadLimit", "responseRadiusMetres", "convoyCount"}; } static bool Available(string key, bool hq, bool intel) { if (key == "aiIntelChancePercent") return intel; - if (key == "reportIntervalSeconds" || key == "supportSquadLimit" || key == "responseRadiusMetres") return hq; + if (key == "convoyCount" || key == "reportIntervalSeconds" || key == "supportSquadLimit" || key == "responseRadiusMetres") return hq; return Keys().Contains(key); } // A short journal has no older off-screen lines, even if its slider is zero. @@ -30,6 +30,7 @@ class ERR_AdminMenuFields } static string Display(string key, string value) { + if (value == "-1" || value == "-2") return ERR_Settings.SelectionText(value.ToInt()); if (key == "startTimeMinutes") return ERR_TimeService.Clock(value.ToInt()); if (key == "startDateCode") return ERR_EnvironmentService.Date(value.ToInt()); if (key == "weatherProfile") return ERR_EnvironmentService.ProfileName(value.ToInt()); @@ -48,6 +49,7 @@ class ERR_AdminMenuFields else if (key == "reportIntervalSeconds") prefix = "hq interval"; else if (key == "supportSquadLimit") prefix = "hq squads"; else if (key == "responseRadiusMetres") prefix = "hq radius"; + else if (key == "convoyCount") prefix = "hq convoy count"; value = value.Trim(); if (prefix.IsEmpty() || value.IsEmpty() || value.Length() > 32) return ""; return prefix + " set " + value; @@ -96,8 +98,13 @@ class ERR_AdminMenu : ChimeraMenuBase m_Controller = SCR_PlayerController.Cast(GetGame().GetPlayerController()); m_Mode = ERR_GameMode.Cast(GetGame().GetGameMode()); if (!m_Controller) { Close(); return; } - array names = {"Close", "OpenHQ", "BackSettings", "OpenJournal", "BackHQ", "PauseJournal", "LatestJournal", "IntelSummary", "RerollIntel"}; - foreach (string key : ERR_AdminMenuFields.Keys()) names.Insert("Apply_" + key); + array names = {"Close", "OpenSettings", "OpenWorld", "OpenFactions", "OpenHQ", "OpenJournal", "PauseJournal", "LatestJournal", "IntelSummary", "RerollIntel", "OpenMods", "OpenIntel", "OpenStatus"}; + names.Insert("RandomDay_startTimeMinutes"); + foreach (string key : ERR_AdminMenuFields.Keys()) + { + names.Insert("Apply_" + key); + names.Insert("Random_" + key); + } foreach (string name : names) { Widget widget = GetRootWidget().FindAnyWidget(name); @@ -177,7 +184,7 @@ class ERR_AdminMenu : ChimeraMenuBase SCR_EditBoxComponent edit = SCR_EditBoxComponent.GetEditBoxComponent(key, GetRootWidget()); if (edit && edit.IsInWriteMode()) return; } - if (m_Page > 0) ShowPage(m_Page - 1); + if (m_Page != 0) ShowPage(0); else Close(); } protected void SetText(string name, string value) @@ -185,28 +192,35 @@ class ERR_AdminMenu : ChimeraMenuBase TextWidget widget = TextWidget.Cast(GetRootWidget().FindAnyWidget(name)); if (widget) widget.SetText(value); } + // Stable page order is also used by the shared navigation bar and native probe. + static array Pages() { return {"SettingsPage", "HQPage", "JournalPage", "ModsPage", "FactionsPage", "WorldPage", "IntelPage", "StatusPage"}; } + static array Navigation() { return {"OpenSettings", "OpenHQ", "OpenJournal", "OpenMods", "OpenFactions", "OpenWorld", "OpenIntel", "OpenStatus"}; } protected void ShowPage(int page) { + array pages = Pages(); + array navigation = Navigation(); + if (page < 0 || page >= pages.Count()) return; m_Page = page; - GetRootWidget().FindAnyWidget("SettingsPage").SetVisible(page == 0); - GetRootWidget().FindAnyWidget("HQPage").SetVisible(page == 1); - GetRootWidget().FindAnyWidget("JournalPage").SetVisible(page == 2); - if (page == 0) SetText("Title", "Mission settings"); - if (page == 1) SetText("Title", "HQ and mission status"); - if (page == 2) { SetText("Title", "HQ activity journal"); m_LogPoll = 1; } + for (int i = 0; i < pages.Count(); i++) + { + GetRootWidget().FindAnyWidget(pages[i]).SetVisible(i == page); + GetRootWidget().FindAnyWidget("Selected_" + navigation[i]).SetVisible(i == page); + } + if (page == 2) m_LogPoll = 1; } protected void UpdateActions() { foreach (SCR_ButtonBaseComponent button : m_Buttons) { string name = button.GetRootWidget().GetName(); - if (name.IndexOf("Apply_") == 0) + if (name.IndexOf("Apply_") == 0 || name.IndexOf("Random_") == 0 || name.IndexOf("RandomDay_") == 0) { - string key = name.Substring(6, name.Length() - 6); + int prefix = name.IndexOf("_") + 1; + string key = name.Substring(prefix, name.Length() - prefix); button.SetEnabled(m_Ready && m_AvailableFields.Contains(key) && ERR_AdminMenuFields.Available(key, m_HQ, m_Intel)); } else if (name == "RerollIntel" || name == "IntelSummary") button.SetEnabled(m_Ready && m_Intel); - else if (name == "OpenJournal" || name == "LatestJournal") button.SetEnabled(m_Ready && m_HQ); + else if (name == "LatestJournal") button.SetEnabled(m_Ready && m_HQ); } } void ReceiveSnapshot(bool authorized, array values, array status) @@ -221,6 +235,12 @@ class ERR_AdminMenu : ChimeraMenuBase int divider = entry.IndexOf("="); if (divider <= 0) continue; string key = entry.Substring(0, divider); + if (key.IndexOf("resolved_") == 0) + { + string resolvedKey = key.Substring(9, key.Length() - 9); + if (ERR_AdminMenuFields.Keys().Contains(resolvedKey)) SetText("Saved_" + resolvedKey, "Saved: Random (using " + entry.Substring(divider + 1, entry.Length() - divider - 1) + ")"); + continue; + } if (!ERR_AdminMenuFields.Keys().Contains(key)) continue; string value = ERR_AdminMenuFields.Display(key, entry.Substring(divider + 1, entry.Length() - divider - 1)); m_AvailableFields.Insert(key); @@ -290,9 +310,8 @@ class ERR_AdminMenu : ChimeraMenuBase if (!button || !IsFocused()) return; string name = button.GetRootWidget().GetName(); if (name == "Close") { Close(); return; } - if (name == "OpenHQ" || name == "BackHQ") { ShowPage(1); return; } - if (name == "BackSettings") { ShowPage(0); return; } - if (name == "OpenJournal") { if (m_Ready && m_HQ) ShowPage(2); return; } + int page = Navigation().Find(name); + if (page >= 0) { ShowPage(page); return; } if (name == "PauseJournal") { m_LogPaused = !m_LogPaused; @@ -319,6 +338,21 @@ class ERR_AdminMenu : ChimeraMenuBase if (pause) pause.SetText("Pause live"); return; } + if (name.IndexOf("Random_") == 0 || name.IndexOf("RandomDay_") == 0) + { + int prefix = name.IndexOf("_") + 1; + string key = name.Substring(prefix, name.Length() - prefix); + if (!m_AvailableFields.Contains(key) || !ERR_AdminMenuFields.Available(key, m_HQ, m_Intel)) return; + SCR_EditBoxComponent edit = SCR_EditBoxComponent.GetEditBoxComponent(key, GetRootWidget()); + if (edit) + { + string choice = "Random"; + if (name.IndexOf("RandomDay_") == 0) choice = "Random day"; + edit.SetValue(choice); + SetText("Feedback", choice + " selected. Press Apply to save."); + } + return; + } string command; if (name == "IntelSummary" && m_Intel) command = "intel show"; if (name == "RerollIntel" && m_Intel) command = "intel reroll"; diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminPlayerTools.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminPlayerTools.c index 881eee3..ecb19a4 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminPlayerTools.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminPlayerTools.c @@ -78,8 +78,15 @@ class ERR_AdminPlayerTools args = args.Trim(); args.ToLower(); bool godCommand = args == "help god" || args == "god" || args == "ungod" || args.StartsWith("god "); bool itemCommand = args == "help cheat" || args == "cheat" || args.StartsWith("cheat "); - if (!godCommand && !itemCommand) return false; + bool killCommand = args == "killais" || args == "help killais"; + if (!godCommand && !itemCommand && !killCommand) return false; + if (args == "help killais") { replies.Insert("/esc killais: kill AI characters within 1000 m of your living character. Players and vehicles are preserved."); return true; } IEntity actor = CurrentBody(mode, controller); + if (killCommand && actor) + { + replies.Insert(string.Format("Killed %1 AI characters within 1000 m.", ERR_DebugAI.KillNearby(mode, actor))); + return true; + } if (!actor) { Stop(); @@ -127,8 +134,14 @@ class ERR_AdminPlayerTools } string item; if (args.Length() > 6) item = args.Substring(6, args.Length() - 6); + if (item == "intel") + { + if (ERR_DebugIntel.SpawnSix(mode, actor)) replies.Insert("Spawned 6 intel documents on the ground nearby. Pick them up to recover intel normally."); + else replies.Insert("Could not place 6 intel documents. Stand on clear ground outside a vehicle, with room nearby."); + return true; + } ResourceName prefab = ItemPrefab(item); - if (prefab.IsEmpty()) { replies.Insert("Use /esc cheat map | /esc cheat helmet | /esc cheat uniform (vanilla paper map, PASGT helmet or BDU jacket)."); return true; } + if (prefab.IsEmpty()) { replies.Insert("Use /esc cheat map | /esc cheat helmet | /esc cheat uniform | /esc cheat intel (6 documents on nearby ground; other items: vanilla paper map, PASGT helmet or BDU jacket)."); return true; } if (m_Grants.TimedOut) { replies.Insert("An inventory insertion is unresolved; further item grants are blocked for this character."); return true; } if (m_Grants.Operation) { replies.Insert("An item grant is already pending; wait for its result."); return true; } SCR_InventoryStorageManagerComponent inventory = SCR_InventoryStorageManagerComponent.Cast(actor.FindComponent(SCR_InventoryStorageManagerComponent)); diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminService.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminService.c index ee75fc6..2fa9358 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminService.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminService.c @@ -8,6 +8,15 @@ class ERR_CommandArguments if (section == "intel" && option == "reveal") return "intelRevealChancePercent"; return ""; } + static bool Selection(string key, string text, out int value) + { + if (text == "random" && ERR_Settings.Randomizable(key)) { value = -1; return true; } + if ((text == "random-day" || text == "random day") && key == "startTimeMinutes") { value = -2; return true; } + if (key == "startTimeMinutes") return ERR_TimeService.ParseClock(text, value); + if (key == "startDateCode") return ERR_EnvironmentService.ParseDate(text, value); + if (key == "weatherProfile") return ERR_EnvironmentService.ParseProfile(text, value); + return Integer(text, value); + } static bool Integer(string text, out int value) { if (text.IsEmpty() || text.Length() > 6) return false; @@ -79,35 +88,36 @@ class ERR_AdminService if (parts.Count() == 3 && parts[2] == "show") { if (mode.Time()) replies.Insert(mode.Time().Status()); - replies.Insert("Next round: " + ERR_TimeService.Clock(mode.Settings().Get("startTimeMinutes")) + ", " + mode.Settings().Get("timeMultiplier").ToString() + "x progression."); + replies.Insert("Next round: " + ERR_AdminMenuFields.Display("startTimeMinutes", mode.Settings().Get("startTimeMinutes").ToString()) + ", " + ERR_Settings.SelectionText(mode.Settings().Get("timeMultiplier")) + " progression."); return true; } int value; bool valid; if (parts.Count() == 4 && parts[2] == "set") { - if (key == "startTimeMinutes") valid = ERR_TimeService.ParseClock(parts[3], value); - else valid = ERR_CommandArguments.Integer(parts[3], value); + valid = ERR_CommandArguments.Selection(key, parts[3], value); } + if (parts.Count() == 5 && parts[2] == "set" && parts[3] == "random" && parts[4] == "day") + valid = ERR_CommandArguments.Selection(key, "random day", value); if (valid && mode.Settings().Set(key, value)) - replies.Insert("Saved for next round: " + ERR_TimeService.Clock(mode.Settings().Get("startTimeMinutes")) + ", " + mode.Settings().Get("timeMultiplier").ToString() + "x progression. Current round clock unchanged."); - else replies.Insert("Invalid time or settings could not be saved. Use mission time set HH:MM (00:00-23:59) or mission speed set N (1-24). Previous setting retained."); + replies.Insert("Saved for next round: " + ERR_AdminMenuFields.Display("startTimeMinutes", mode.Settings().Get("startTimeMinutes").ToString()) + ", " + ERR_Settings.SelectionText(mode.Settings().Get("timeMultiplier")) + " progression. Current round clock unchanged."); + else replies.Insert("Invalid time or settings could not be saved. Use mission time set HH:MM (00:00-23:59)|random|random-day or mission speed set N (1-24)|random. Previous setting retained."); return true; } protected string SettingHelp(string key) { if (key == "intelRevealChancePercent") - return "Use /esc intel reveal set N (0-100). This is the chance that a first document identifies its location exactly; otherwise it gives a rough location. A second document for that location always identifies it. Changes affect newly recovered documents immediately; known locations and spent documents remain unchanged."; + return "Use /esc intel reveal set N (0-100) or random. This is the chance that a first document identifies its location exactly; otherwise it gives a rough location. A second document for that location always identifies it. Changes affect newly recovered documents immediately; known locations and spent documents remain unchanged."; return ""; } protected void SettingCommand(ERR_Settings settings, string key, array parts, array replies) { - if (parts.Count() == 3 && parts[2] == "show") { replies.Insert(key + "=" + settings.Get(key).ToString()); return; } + if (parts.Count() == 3 && parts[2] == "show") { replies.Insert(key + "=" + ERR_Settings.SelectionText(settings.Get(key))); return; } string help = SettingHelp(key); if (parts.Count() == 3 && parts[2] == "help" && !help.IsEmpty()) { replies.Insert(help); return; } int value; - if (parts.Count() == 4 && parts[2] == "set" && ERR_CommandArguments.Integer(parts[3], value) && settings.Set(key, value)) - replies.Insert(key + "=" + value.ToString() + " saved"); + if (parts.Count() == 4 && parts[2] == "set" && ERR_CommandArguments.Selection(key, parts[3], value) && settings.Set(key, value)) + replies.Insert(key + "=" + ERR_Settings.SelectionText(value) + " saved"); else { string failure = "Invalid value or settings could not be saved; previous setting retained."; @@ -121,9 +131,9 @@ class ERR_AdminService if (provider.Help(topic, replies)) return; if (topic == "time" || topic == "mission") { - replies.Insert("/esc mission radio show|set N | mission abandon"); - replies.Insert("/esc time show|set HH:MM | mission speed show|set N; saved changes apply next round."); - replies.Insert("/esc mission date show|set YYYY-MM-DD|authored | mission weather show|set authored|clear|overcast|rain"); + replies.Insert("/esc mission radio show|set N|random | mission abandon"); + replies.Insert("/esc time show|set HH:MM|random|random-day | mission speed show|set N|random; saved changes apply next round."); + replies.Insert("/esc mission date show|set YYYY-MM-DD|authored|random | mission weather show|set authored|clear|overcast|rain|random"); return; } if (topic == "intel") @@ -137,8 +147,8 @@ class ERR_AdminService replies.Insert("This command topic is unavailable in the loaded mission: " + topic + "."); return; } - replies.Insert("/esc menu | status | settings | help mission|time|intel|hq|cheat|god"); - replies.Insert("/esc mission abandon | mission radio show|set N | time show|set HH:MM"); + replies.Insert("/esc menu | status | settings | help mission|time|intel|hq|cheat|god|killais"); + replies.Insert("/esc mission abandon | mission radio show|set N|random | time show|set HH:MM|random|random-day"); replies.Insert("/esc mission date|weather|speed show|set VALUE | intel reveal show|set N|help"); replies.Insert("/esc spectate next|previous; optional systems add their own command topics."); } diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminSession.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminSession.c index 836e0f3..a4e2925 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminSession.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_AdminSession.c @@ -93,6 +93,11 @@ class ERR_AdminSession array status = {}; if (!m_Mode.Settings()) { status.Insert("Mission settings are not ready."); m_Controller.ERR_AdminDeliverSnapshot(m_Token, true, values, status); return; } foreach (string key : ERR_Settings.Keys()) values.Insert(key + "=" + m_Mode.Settings().Get(key).ToString()); + foreach (string key : ERR_AdminMenuFields.Keys()) + { + if (key == "convoyCount" || key == "startTimeMinutes" || key == "timeMultiplier" || key == "startDateCode" || key == "weatherProfile") continue; + if (m_Mode.Settings().Get(key) == -1) values.Insert("resolved_" + key + "=" + m_Mode.Settings().Runtime(key).ToString()); + } m_Mode.Admin().Capabilities(values); m_Mode.Admin().Execute(m_Mode, true, "status", status); m_Controller.ERR_AdminDeliverSnapshot(m_Token, true, values, status); diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_AirfieldPlacement.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_AirfieldPlacement.c new file mode 100644 index 0000000..c070580 --- /dev/null +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_AirfieldPlacement.c @@ -0,0 +1,32 @@ +// Scenario authors choose a pad on their island's airfield. Never relocate an +// obstructed aircraft into nearby woods: refuse preparation before spawning it. +class ERR_AirfieldPlacement +{ + protected bool m_NearAirport; + protected bool Airport(IEntity entity) + { + if (!entity || !entity.GetPrefabData()) return true; + string path = entity.GetPrefabData().GetPrefabName(); path.ToLower(); + if (path.Contains("/runway") || path.Contains("/lightrunway_") || path.Contains("/aircontroltower") || path.Contains("/airportcontroltower") || path.Contains("/locations/eden/airport.et")) m_NearAirport = true; + return !m_NearAirport; + } + static bool Clear(vector position) + { + if (!Replication.IsServer() || position[1] < 2 || ChimeraWorldUtils.TryGetWaterSurfaceSimple(GetGame().GetWorld(), position)) return false; + ERR_AirfieldPlacement survey = new ERR_AirfieldPlacement(); + GetGame().GetWorld().QueryEntitiesBySphere(position, 600, survey.Airport, null, EQueryEntitiesFlags.ALL); + if (!survey.m_NearAirport) return false; + for (int edge = 0; edge < 4; edge++) + { + float side = edge * Math.PI / 2; + vector sample = position + Vector(Math.Cos(side) * 14, 0, Math.Sin(side) * 14); + if (Math.AbsFloat(SCR_TerrainHelper.GetTerrainY(sample) - position[1]) > 0.8) return false; + } + if (!SCR_WorldTools.TraceCilinderUtil(position + "0 2.5 0", 40, 4, TraceFlags.ENTS)) return false; + TraceBox clearance = new TraceBox(); + clearance.Start = position + "0 3 0"; clearance.End = position + "0 60 0"; + clearance.Mins = "-40 -1 -40"; clearance.Maxs = "40 1 40"; + clearance.Flags = TraceFlags.ENTS | TraceFlags.WORLD; + return GetGame().GetWorld().TraceMove(clearance, null) >= 1; + } +} diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_ContentDefinition.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_ContentDefinition.c new file mode 100644 index 0000000..8393b67 --- /dev/null +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_ContentDefinition.c @@ -0,0 +1,103 @@ +// Modder-facing registry. New packs/factions and their menu rows need data only. +[BaseContainerProps()] +class ERR_ContentOption +{ + [Attribute()] string Id; + [Attribute()] string Label; + [Attribute("", UIWidgets.EditBox, "Parent pack ID; empty for a pack")] + string Parent; + [Attribute("1", UIWidgets.CheckBox)] bool DefaultEnabled; + [Attribute("", UIWidgets.EditBox, "Native faction key; empty for a pack")] + string NativeFactionKey; + [Attribute("", UIWidgets.ResourceNamePicker, "Physical guard group belonging to this faction", "et")] + ResourceName GuardGroup; + [Attribute("", UIWidgets.EditBox, "Exact resource GUIDs for optional equipment owned by this pack")] + ref array EquipmentGuids; +} + +[BaseContainerProps()] +class ERR_ContentDefinition +{ + [Attribute()] ref array Options; + ERR_ContentOption Find(string id) + { + if (!Options) return null; + foreach (ERR_ContentOption option : Options) + if (option && option.Id == id) return option; + return null; + } + bool Valid() + { + if (!Options || Options.IsEmpty() || Options.Count() > 64) return false; + set ids = new set(); + set factions = new set(); + set groups = new set(); + set resources = new set(); + foreach (ERR_ContentOption option : Options) + { + if (!option || option.Id.IsEmpty() || option.Id.Length() > 48 || option.Label.IsEmpty() || ids.Contains(option.Id)) return false; + for (int i = 0; i < option.Id.Length(); i++) + if ("abcdefghijklmnopqrstuvwxyz0123456789_".IndexOf(option.Id.Substring(i, 1)) < 0) return false; + ids.Insert(option.Id); + if (!option.Parent.IsEmpty()) + { + ERR_ContentOption parent = Find(option.Parent); + if (!parent || !parent.Parent.IsEmpty() || !parent.NativeFactionKey.IsEmpty()) return false; + } + if (!option.NativeFactionKey.IsEmpty()) + { + if (option.Parent.IsEmpty() || option.GuardGroup.IsEmpty() || factions.Contains(option.NativeFactionKey) || groups.Contains(option.GuardGroup)) return false; + factions.Insert(option.NativeFactionKey); + groups.Insert(option.GuardGroup); + } + else if (!option.GuardGroup.IsEmpty()) return false; + if (option.EquipmentGuids) + foreach (string guid : option.EquipmentGuids) + { + if (guid.Length() != 16 || resources.Contains(guid)) return false; + for (int j = 0; j < guid.Length(); j++) + if ("0123456789ABCDEF".IndexOf(guid.Substring(j, 1)) < 0) return false; + resources.Insert(guid); + } + } + return true; + } +} + +class ERR_ContentRegistry +{ + protected static ref ERR_ContentDefinition s_Definition; + static ERR_ContentDefinition Definition() + { + if (!s_Definition) s_Definition = ERR_ContentDefinition.Cast(SCR_BaseContainerTools.CreateInstanceFromPrefab("{64BF38F9F92CE016}Configs/ERR/Content/Registry.conf")); + return s_Definition; + } + static array Ids() + { + array ids = {}; + ERR_ContentDefinition definition = Definition(); + if (definition && definition.Valid()) + foreach (ERR_ContentOption option : definition.Options) ids.Insert(option.Id); + return ids; + } + static string Key(string id) { return "content_" + id; } + static string Label(string id) + { + ERR_ContentOption option = Definition().Find(id); + if (option) return option.Label; + return id; + } + static string State(bool enabled) + { + if (enabled) return "Enabled"; + return "Disabled"; + } + static string ResourcePack(ResourceName prefab) + { + foreach (ERR_ContentOption option : Definition().Options) + if (option.EquipmentGuids) + foreach (string guid : option.EquipmentGuids) + if (prefab.Contains("{" + guid + "}")) return option.Id; + return ""; + } +} diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_ContentMenu.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_ContentMenu.c new file mode 100644 index 0000000..9967edb --- /dev/null +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_ContentMenu.c @@ -0,0 +1,118 @@ +modded class ERR_AdminMenu +{ + protected ref map m_ModRows = new map(); + protected ref map m_ModSaved = new map(); + protected ref map m_ModActive = new map(); + static void OpenMods() + { + Open(); + ERR_AdminMenu menu = GetOpenMenu(); + if (menu) menu.ShowPage(3); + } + override void OnMenuOpen() + { + super.OnMenuOpen(); + Widget list = GetRootWidget().FindAnyWidget("ModList"); + foreach (string pack : ERR_ContentRegistry.Ids()) + { + Widget row = GetGame().GetWorkspace().CreateWidgets("{F092D45656A8E02B}UI/layouts/ERR/ContentRow.layout", list); + if (!row) { Close(); return; } + m_ModRows.Set(pack, row); + TextWidget label = TextWidget.Cast(row.FindAnyWidget("PackLabel")); + if (label) label.SetText(ERR_ContentRegistry.Label(pack)); + SCR_ButtonTextComponent enable = SCR_ButtonTextComponent.GetButtonText("Enable", row); + SCR_ButtonTextComponent disable = SCR_ButtonTextComponent.GetButtonText("Disable", row); + if (!enable || !disable) { Close(); return; } + enable.m_OnClicked.Insert(OnModButton); disable.m_OnClicked.Insert(OnModButton); + } + UpdateActions(); + } + override void OnMenuClose() + { + foreach (string pack, Widget row : m_ModRows) + { + SCR_ButtonTextComponent enable = SCR_ButtonTextComponent.GetButtonText("Enable", row); + SCR_ButtonTextComponent disable = SCR_ButtonTextComponent.GetButtonText("Disable", row); + if (enable) enable.m_OnClicked.Remove(OnModButton); + if (disable) disable.m_OnClicked.Remove(OnModButton); + } + m_ModRows.Clear(); m_ModSaved.Clear(); m_ModActive.Clear(); + super.OnMenuClose(); + } + protected override void UpdateActions() + { + super.UpdateActions(); + foreach (string pack, Widget row : m_ModRows) + { + bool ready = m_Ready && m_ModSaved.Contains(pack) && m_ModActive.Contains(pack); + SCR_ButtonTextComponent enable = SCR_ButtonTextComponent.GetButtonText("Enable", row); + SCR_ButtonTextComponent disable = SCR_ButtonTextComponent.GetButtonText("Disable", row); + if (enable) enable.SetEnabled(ready && m_ModSaved.Get(pack) == 0); + if (disable) disable.SetEnabled(ready && m_ModSaved.Get(pack) == 1); + TextWidget state = TextWidget.Cast(row.FindAnyWidget("PackState")); + if (!state) continue; + if (!ready) state.SetText("Waiting for server settings..."); + else state.SetText("Current round: " + ERR_ContentRegistry.State(m_ModActive.Get(pack) == 1) + " | Saved preference: " + ERR_ContentRegistry.State(m_ModSaved.Get(pack) == 1)); + } + } + override void ReceiveSnapshot(bool authorized, array values, array status) + { + m_ModSaved.Clear(); m_ModActive.Clear(); + if (authorized && values) + foreach (string pack : ERR_ContentRegistry.Ids()) + foreach (string entry : values) + { + if (entry == ERR_ContentRegistry.Key(pack) + "=0") m_ModSaved.Set(pack, 0); + if (entry == ERR_ContentRegistry.Key(pack) + "=1") m_ModSaved.Set(pack, 1); + if (entry == "activeMod_" + pack + "=0") m_ModActive.Set(pack, 0); + if (entry == "activeMod_" + pack + "=1") m_ModActive.Set(pack, 1); + } + super.ReceiveSnapshot(authorized, values, status); + } + protected void OnModButton(SCR_ButtonBaseComponent button) + { + if (!button || !IsFocused() || !m_Controller || !m_Ready || m_Age > 6 || m_ClickDelay > 0) return; + foreach (string pack, Widget row : m_ModRows) + { + string action; + if (button.GetRootWidget() == row.FindAnyWidget("Enable")) action = "enable"; + if (button.GetRootWidget() == row.FindAnyWidget("Disable")) action = "disable"; + if (action.IsEmpty() || !m_ModSaved.Contains(pack) || !m_ModActive.Contains(pack)) continue; + m_ClickDelay = 0.3; + SetText("Feedback", "Saving selection on the server..."); + m_Controller.ERR_AdminSubmit("mods " + pack + " " + action, true); + return; + } + } +} + +// Add one mission-specific item to the existing Esc menu. The authenticated +// snapshot and command handlers still enforce access on the server. +modded class PauseMenuUI +{ + protected SCR_ButtonTextComponent m_ERRModsButton; + override void OnMenuOpen() + { + super.OnMenuOpen(); + PlayerController controller = GetGame().GetPlayerController(); + if (!ERR_GameMode.Get() || !controller || !SCR_Global.IsAdmin(controller.GetPlayerId())) return; + Widget settings = GetRootWidget().FindAnyWidget("Settings"); + if (!settings) return; + Widget widget = GetGame().GetWorkspace().CreateWidgets("{F0351A624C87DE90}UI/layouts/ERR/PauseModsButton.layout", settings.GetParent()); + if (!widget) return; + m_ERRModsButton = SCR_ButtonTextComponent.Cast(widget.FindHandler(SCR_ButtonTextComponent)); + if (m_ERRModsButton) m_ERRModsButton.m_OnClicked.Insert(ERR_OpenMods); + } + protected void ERR_OpenMods() + { + // Unpause local simulation before requesting an authenticated server snapshot. + Close(); + ERR_AdminMenu.Open(); + } + override void OnMenuClose() + { + if (m_ERRModsButton) m_ERRModsButton.m_OnClicked.Remove(ERR_OpenMods); + m_ERRModsButton = null; + super.OnMenuClose(); + } +} diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_ContentPolicy.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_ContentPolicy.c new file mode 100644 index 0000000..24982cb --- /dev/null +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_ContentPolicy.c @@ -0,0 +1,136 @@ +class ERR_ContentPolicy +{ + protected bool m_FactionsPrepared; + protected int m_GuardOffset; + protected ref map m_Active = new map(); + void ERR_ContentPolicy(ERR_ContentSettings settings) + { + foreach (string pack : ERR_ContentRegistry.Ids()) + m_Active.Set(pack, settings && settings.Enabled(pack)); + int count; + ERR_ContentDefinition definition = ERR_ContentRegistry.Definition(); + if (definition && definition.Valid()) + foreach (ERR_ContentOption option : definition.Options) + if (!option.NativeFactionKey.IsEmpty() && Enabled(option.Id)) count++; + if (count > 0) m_GuardOffset = Math.RandomInt(0, count); + } + bool Enabled(string pack) + { + if (pack.IsEmpty()) return true; // Base game / owned mission content. + if (!m_Active.Contains(pack) || !m_Active.Get(pack)) return false; + ERR_ContentOption option = ERR_ContentRegistry.Definition().Find(pack); + return option && (option.Parent.IsEmpty() || (m_Active.Contains(option.Parent) && m_Active.Get(option.Parent))); + } + bool Allows(ResourceName prefab) { return Enabled(ERR_ContentRegistry.ResourcePack(prefab)); } + bool Enemy(Faction faction) + { + if (!faction) return false; + foreach (ERR_ContentOption option : ERR_ContentRegistry.Definition().Options) + if (!option.NativeFactionKey.IsEmpty() && Enabled(option.Id) && option.NativeFactionKey == faction.GetFactionKey()) return true; + return false; + } + ResourceName GuardGroup(int index) + { + array groups = {}; + foreach (ERR_ContentOption option : ERR_ContentRegistry.Definition().Options) + if (!option.NativeFactionKey.IsEmpty() && Enabled(option.Id)) groups.Insert(option.GuardGroup); + if (groups.IsEmpty()) return ""; + return groups[(index + m_GuardOffset) % groups.Count()]; + } + string GuardFaction(ResourceName prefab) + { + foreach (ERR_ContentOption option : ERR_ContentRegistry.Definition().Options) + if (option.GuardGroup == prefab && Enabled(option.Id)) return option.NativeFactionKey; + return ""; + } + bool PrepareFactions(ERR_GameMode mode) + { + if (m_FactionsPrepared) return true; + ERR_ContentDefinition definition = ERR_ContentRegistry.Definition(); + if (!definition || !definition.Valid()) return false; + SCR_FactionManager manager = SCR_FactionManager.Cast(GetGame().GetFactionManager()); + if (!manager) return false; + array factions = {}; + SCR_Faction player = SCR_Faction.Cast(mode.PlayerFaction()); + SCR_Faction primary = SCR_Faction.Cast(mode.EnemyFaction()); + if (!player || !primary) return false; + factions.Insert(player); factions.Insert(primary); + foreach (ERR_ContentOption option : definition.Options) + { + if (option.NativeFactionKey.IsEmpty() || !Enabled(option.Id)) continue; + SCR_Faction faction = SCR_Faction.Cast(manager.GetFactionByKey(option.NativeFactionKey)); + Resource group = Resource.Load(option.GuardGroup); + if (!faction || !group || !group.IsValid()) return false; + if (factions.Contains(faction)) continue; + factions.Insert(faction); + } + // The manager mirrors both directions and persists relationships for JIP. + // Call both orders as an inherited one-way friendship may exist. + foreach (SCR_Faction a : factions) + { + manager.SetFactionsFriendly(a, a, -1, false); + foreach (SCR_Faction b : factions) + { + if (a == b) continue; + manager.SetFactionsHostile(a, b, -1, false); + manager.SetFactionsHostile(b, a, -1, false); + if (!a.IsFactionEnemy(b) || !b.IsFactionEnemy(a)) return false; + } + } + SCR_FactionManager.RequestUpdateAllTargetsFactions(); + m_FactionsPrepared = true; + return true; + } + void Snapshot(array values) + { + foreach (string pack : ERR_ContentRegistry.Ids()) + { + int enabled = 0; + if (Enabled(pack)) enabled = 1; + values.Insert("activeMod_" + pack + "=" + enabled.ToString()); + } + } +} + +// Commands inherit the existing authenticated controller/session boundary. +class ERR_ContentAdminProvider : ERR_AdminProvider +{ + protected ERR_ContentPolicy m_Policy; + void ERR_ContentAdminProvider(ERR_ContentPolicy policy) { m_Policy = policy; } + override string Id() { return "mods"; } + override void Capabilities(array values) + { + m_Policy.Snapshot(values); + ERR_GameMode mode = ERR_GameMode.Get(); + if (mode && mode.ContentSettings()) mode.ContentSettings().Snapshot(values); + } + override bool Help(string topic, array replies) + { + if (topic != "mods") return false; + replies.Insert("Use /esc mods show, or /esc mods enable|disable. Saved selections apply after mission restart. A disabled pack also disables its factions. Workshop dependencies remain installed."); + return true; + } + override bool Execute(ERR_GameMode mode, string arguments, array replies) + { + array parts = {}; + arguments.Split(" ", parts, true); + if (parts.IsEmpty() || parts[0] != "mods") return false; + if (arguments == "mods show") + { + foreach (string pack : ERR_ContentRegistry.Ids()) + replies.Insert(ERR_ContentRegistry.Label(pack) + ": current round " + ERR_ContentRegistry.State(m_Policy.Enabled(pack)) + "; saved preference " + ERR_ContentRegistry.State(mode.ContentSettings().Enabled(pack)) + "."); + return true; + } + if (parts.Count() == 3 && ERR_ContentRegistry.Ids().Contains(parts[1]) && (parts[2] == "enable" || parts[2] == "disable")) + { + int value = 0; + if (parts[2] == "enable") value = 1; + if (mode.ContentSettings().Set(parts[1], value)) + replies.Insert(ERR_ContentRegistry.Label(parts[1]) + ": " + ERR_ContentRegistry.State(value == 1) + " after mission restart. Current round unchanged."); + else replies.Insert("Could not save mod selection. Previous setting retained."); + return true; + } + Help("mods", replies); + return true; + } +} diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_ContentSettings.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_ContentSettings.c new file mode 100644 index 0000000..645caec --- /dev/null +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_ContentSettings.c @@ -0,0 +1,86 @@ +// Separate, config-driven preferences. Missing newly installed options use their +// authored defaults. Failed writes preserve both previous state and backup. +class ERR_ContentSettings +{ + static const string PATH = "$profile:EscapistsContent.json"; + protected string m_Path; + protected bool m_ReadOnly; + protected ref map m_Values = new map(); + void ERR_ContentSettings(string path = PATH) + { + m_Path = path; + ERR_ContentDefinition definition = ERR_ContentRegistry.Definition(); + if (!definition || !definition.Valid()) { m_ReadOnly = true; return; } + foreach (ERR_ContentOption option : definition.Options) + { + int value = 0; + if (option.DefaultEnabled) value = 1; + m_Values.Set(option.Id, value); + } + if (!Replication.IsServer()) { m_ReadOnly = true; return; } + map loaded; + if (Read(m_Path, loaded) || Read(m_Path + ".bak", loaded)) m_Values = loaded; + else if (FileIO.FileExists(m_Path) || FileIO.FileExists(m_Path + ".bak")) + { + m_ReadOnly = true; + Print("Escapists: invalid content preferences; authored defaults active, existing files preserved", LogLevel.ERROR); + } + } + bool Enabled(string id) { return m_Values.Contains(id) && m_Values.Get(id) == 1; } + protected bool Read(string path, out map values) + { + JsonLoadContext json = new JsonLoadContext(); + if (!json.LoadFromFile(path)) return false; + values = new map(); + foreach (ERR_ContentOption option : ERR_ContentRegistry.Definition().Options) + { + int fallback = 0; + if (option.DefaultEnabled) fallback = 1; + if (!json.DoesKeyExist(option.Id)) { values.Set(option.Id, fallback); continue; } + float number; + if (!json.ReadValue(option.Id, number) || (number != 0 && number != 1)) return false; + values.Set(option.Id, Math.Round(number)); + } + return true; + } + protected bool Matches(map values, string changed, int value) + { + if (!values) return false; + foreach (string id, int original : m_Values) + { + int expected = original; + if (id == changed) expected = value; + if (!values.Contains(id) || values.Get(id) != expected) return false; + } + return true; + } + bool Set(string id, int value) + { + if (!Replication.IsServer() || m_ReadOnly || !m_Values.Contains(id) || (value != 0 && value != 1)) return false; + JsonSaveContext json = new JsonSaveContext(); + json.EnableTypeDiscriminator(false); + foreach (string option, int original : m_Values) + { + int saved = original; + if (option == id) saved = value; + json.WriteValue(option, saved); + } + map checked; + if (!json.SaveToFile(m_Path + ".tmp") || !Read(m_Path + ".tmp", checked) || !Matches(checked, id, value)) return false; + map previous; + bool hadPrevious = Read(m_Path, previous); + if (hadPrevious && !FileIO.CopyFile(m_Path, m_Path + ".bak")) return false; + if (!FileIO.CopyFile(m_Path + ".tmp", m_Path) || !Read(m_Path, checked) || !Matches(checked, id, value)) + { + if (FileIO.FileExists(m_Path + ".bak")) FileIO.CopyFile(m_Path + ".bak", m_Path); + else if (!hadPrevious) FileIO.DeleteFile(m_Path); + return false; + } + m_Values = checked; + return true; + } + void Snapshot(array values) + { + foreach (string id, int saved : m_Values) values.Insert(ERR_ContentRegistry.Key(id) + "=" + saved.ToString()); + } +} diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_DebugAI.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_DebugAI.c new file mode 100644 index 0000000..5f301aa --- /dev/null +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_DebugAI.c @@ -0,0 +1,43 @@ +// Invoked only through the authenticated, current-body admin tool boundary. +class ERR_DebugAI +{ + static int KillNearby(ERR_GameMode mode, IEntity center) + { + if (!Replication.IsServer() || !mode || mode != ERR_GameMode.Get() || !mode.Active() || !center || !GetGame().GetAIWorld()) return 0; + array lives = {}; mode.Players().Participants(lives); + array protectedBodies = {}; + foreach (ERR_PlayerLife life : lives) if (life.Actor) protectedBodies.Insert(life.Actor); + array agents = {}; GetGame().GetAIWorld().GetAIAgents(agents); + array targets = {}; + foreach (AIAgent agent : agents) + { + if (!agent) continue; + SCR_AIGroup group = SCR_AIGroup.Cast(agent); + if (group) + { + array members = {}; group.GetAgents(members); + foreach (AIAgent member : members) if (member) Add(member.GetControlledEntity(), center, protectedBodies, targets); + } + Add(agent.GetControlledEntity(), center, protectedBodies, targets); + } + int killed; + foreach (IEntity target : targets) + { + // Recheck ownership immediately before damage; possession can change. + if (!Eligible(target, center, protectedBodies)) continue; + SCR_CharacterDamageManagerComponent damage = SCR_CharacterDamageManagerComponent.Cast(target.FindComponent(SCR_CharacterDamageManagerComponent)); + if (!damage) continue; + damage.Kill(Instigator.CreateInstigator(center)); + if (damage.IsDestroyed()) killed++; + } + return killed; + } + static bool Eligible(IEntity target, IEntity center, array protectedBodies) + { + return target && ChimeraCharacter.Cast(target) && target != center && ERR_Actors.Alive(target) && !ERR_Actors.Player(target) && !protectedBodies.Contains(target) && vector.Distance(target.GetOrigin(), center.GetOrigin()) <= 1000; + } + protected static void Add(IEntity target, IEntity center, array protectedBodies, array targets) + { + if (Eligible(target, center, protectedBodies) && !targets.Contains(target)) targets.Insert(target); + } +} diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_DebugIntel.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_DebugIntel.c new file mode 100644 index 0000000..11e2900 --- /dev/null +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_DebugIntel.c @@ -0,0 +1,30 @@ +class ERR_DebugIntel +{ + static bool SpawnSix(ERR_GameMode mode, IEntity actor) + { + if (!Replication.IsServer() || !mode || mode != ERR_GameMode.Get() || !mode.Active() || !ERR_Actors.CanFight(actor) || !mode.Players().CurrentActor(actor)) return false; + ERR_SpawnPlacement placement = new ERR_SpawnPlacement(); + map positions = new map(); + // Survey all six spots first, including solid obstructions and the path from + // the player. This also refuses airborne/seated players and deep water. + for (int i = 0; i < 6; i++) + { + vector position; + if (!placement.Near(actor, positions, position)) return false; + positions.Set(i, position); + } + array spawned = {}; + for (int j = 0; j < 6; j++) + { + IEntity document = ERR_Actors.Spawn(ERR_Resources.IntelFolder(), positions.Get(j)); + if (!document) + { + foreach (IEntity partial : spawned) ERR_Actors.DeleteSpawned(partial); + return false; + } + spawned.Insert(document); + } + foreach (IEntity intel : spawned) mode.Own(intel); + return true; + } +} diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_DiscoveryMap.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_DiscoveryMap.c index 18344bd..f693603 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_DiscoveryMap.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_DiscoveryMap.c @@ -14,6 +14,38 @@ class ERR_DiscoveryMapRules // that boundary so native edit/drag cannot move a discovered objective. class ERR_DiscoveryMarker : SCR_MapMarkerBase { + protected string m_Icon = "supplies"; + static string Icon(ERR_LocationKind kind, string id) + { + if (kind == ERR_LocationKind.EXTRACTION) return "helicopters"; + if (kind == ERR_LocationKind.RADIO) return "radio"; + if (kind == ERR_LocationKind.MORTAR) return "artilleryFireMission"; + if (kind == ERR_LocationKind.OUTPOST) return "building"; + if (id.Contains("medical")) return "medical"; + return "supplies"; + } + void SetLocationIcon(ERR_LocationKind kind, string id, int knowledge = 2) + { + m_Icon = "mark-question"; + if (knowledge >= 2) m_Icon = Icon(kind, id); + ApplyIcon(); + } + protected void ApplyIcon() + { + SCR_MapMarkerWidgetComponent widget = GetMarkerComponent(); + if (!GetRootWidget() || !widget) return; + if (m_Icon == "mark-question") + { + widget.SetImage("{E23427CAC80DA8B7}UI/Textures/Icons/icons_mapMarkersUI.imageset", m_Icon); + widget.SetGlowImage("{67B3A6DC2D712B52}UI/Textures/Icons/icons_mapMarkersUI-glow.imageset", m_Icon); + } + else + { + widget.SetImage("{3262679C50EF4F01}UI/Textures/Icons/icons_wrapperUI.imageset", m_Icon); + widget.SetGlowImage("{00FE3DBDFD15227B}UI/Textures/Icons/icons_wrapperUI-glow.imageset", m_Icon); + } + widget.SetColor(Color.FromSRGBA(35, 45, 50, 255)); + } void ERR_DiscoveryMarker() { SetCanBeRemovedByOwner(false); } void SetDiscoveryPosition(vector position, int knowledge) { @@ -25,6 +57,7 @@ class ERR_DiscoveryMarker : SCR_MapMarkerBase // Text is scenario-authored, never user input. Avoid delayed UGC callbacks // overwriting a newer discovery label after the location becomes identified. super.OnCreateMarker(true); + ApplyIcon(); } override void OnDelete() { @@ -73,17 +106,26 @@ modded class ERR_LocationComponent } protected void ERR_UpdateMarker() { - if (!GetGame().GetPlayerController() || Knowledge() <= 0 || (Knowledge() == m_ERRShown && Label() == m_ERRShownLabel)) return; + if (!GetGame().GetPlayerController()) return; + if (Kind() == ERR_LocationKind.PRISON || Knowledge() < 1) + { + SCR_MapMarkerManagerComponent oldManager = SCR_MapMarkerManagerComponent.GetInstance(); + if (m_ERRMarker && oldManager) oldManager.ERR_RemoveDiscoveryMarker(m_ERRMarker); + else if (m_ERRMarker) m_ERRMarker.OnDelete(); + m_ERRMarker = null; m_ERRShown = 0; m_ERRShownLabel = ""; + return; + } + if (Knowledge() == m_ERRShown && Label() == m_ERRShownLabel) return; SCR_MapMarkerManagerComponent manager = SCR_MapMarkerManagerComponent.GetInstance(); if (!manager || !manager.GetMarkerConfig()) return; - string label = "Search area (500 m square)"; + string label = "Unknown location (500 m area)"; if (Knowledge() == 2) { if (!Label().IsEmpty()) label = Label(); else if (Kind() == ERR_LocationKind.RADIO) label = "Radio station"; else if (Kind() == ERR_LocationKind.EXTRACTION) label = "Initial helicopter pickup site"; else if (Kind() == ERR_LocationKind.DEPOT) label = "Supply cache"; - else if (Kind() == ERR_LocationKind.PRISON) label = "Prison"; + else if (Kind() == ERR_LocationKind.MORTAR) label = "Mortar site"; else label = Id(); } if (!m_ERRMarker) @@ -92,10 +134,12 @@ modded class ERR_LocationComponent m_ERRMarker.SetType(SCR_EMapMarkerType.PLACED_CUSTOM); m_ERRMarker.SetDiscoveryPosition(Position(), Knowledge()); m_ERRMarker.SetMarkerConfigID(0); + m_ERRMarker.SetLocationIcon(Kind(), Id(), Knowledge()); m_ERRMarker.SetCustomText(label); manager.InsertStaticMarker(m_ERRMarker, true); } m_ERRMarker.SetDiscoveryPosition(Position(), Knowledge()); + m_ERRMarker.SetLocationIcon(Kind(), Id(), Knowledge()); m_ERRMarker.SetCustomText(label); // Reactivate a previously culled rough marker if the exact point moves // into the open map's view. Native update performs normal visibility checks. diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_DiscoveryService.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_DiscoveryService.c index 5d26f66..c64c9db 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_DiscoveryService.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_DiscoveryService.c @@ -57,18 +57,24 @@ class ERR_DiscoveryService m_Mode.Locations(locations); array eligible = {}; ERR_DocumentComponent document = ERR_DocumentComponent.Cast(folder.FindComponent(ERR_DocumentComponent)); + string sealedTarget = m_Mode.Evidence().Target(folder); foreach (ERR_LocationComponent location : locations) { if (!location || location.Knowledge() >= 2) continue; + if (!sealedTarget.IsEmpty() && location.Id() != sealedTarget) continue; if (document) { if (location.Id() == document.TargetId()) eligible.Insert(location); } else if (location.Kind() != ERR_LocationKind.PRISON && location.Kind() != ERR_LocationKind.EXTRACTION) eligible.Insert(location); } - if (eligible.IsEmpty()) continue; + if (eligible.IsEmpty()) + { + if (!document && MarkSpent(folder)) m_Mode.ERR_IntelExhausted(!sealedTarget.IsEmpty()); + continue; + } ERR_LocationComponent chosen = eligible.GetRandomElement(); - if (!chosen.Discover(Math.RandomInt(0, 100), m_Mode.Settings().Get("intelRevealChancePercent"))) continue; + if (!chosen.Discover(Math.RandomInt(0, 100), m_Mode.Settings().Runtime("intelRevealChancePercent"))) continue; m_Spent.Insert(folder); PrintFormat("Reintroduced [intel]: player %1 recovered folder; location=%2 knowledge=%3", GetGame().GetPlayerManager().GetPlayerIdFromControlledEntity(player), chosen.Id(), chosen.Knowledge()); } diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_EnvironmentService.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_EnvironmentService.c index 36339d4..a290d37 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_EnvironmentService.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_EnvironmentService.c @@ -66,12 +66,40 @@ class ERR_EnvironmentService if (state && state.GetStateName() == name) return true; return false; } + static int DateFromOrdinal(int year, int ordinal) + { + if (year < 1900 || year > 2050 || ordinal < 0) return -1; + for (int month = 1; month <= 12; month++) + { + int days = 31; + if (month == 4 || month == 6 || month == 9 || month == 11) days = 30; + if (month == 2) + { + days = 28; + if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) days = 29; + } + if (ordinal < days) return (year - 1900) * 10000 + month * 100 + ordinal + 1; + ordinal -= days; + } + return -1; + } + static int RandomDate(int year) + { + int days = 365; + if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) days = 366; + return DateFromOrdinal(year, Math.RandomInt(0, days)); + } bool Start(ERR_GameMode mode) { if (!Replication.IsServer() || !mode || !mode.Settings()) return false; ChimeraWorld world = ChimeraWorld.CastFrom(mode.GetWorld()); if (!world) return false; - return StartOn(world.GetTimeAndWeatherManager(), mode.Settings().Get("startDateCode"), mode.Settings().Get("weatherProfile")); + if (m_Started) return !m_Stopped; + TimeAndWeatherManagerEntity manager = world.GetTimeAndWeatherManager(); + if (!manager) return false; + int dateCode = mode.Settings().Get("startDateCode"); + if (dateCode == -1) dateCode = RandomDate(manager.GetYear()); + return StartOn(manager, dateCode, mode.Settings().Runtime("weatherProfile")); } protected bool StartOn(TimeAndWeatherManagerEntity manager, int dateCode, int profile) { @@ -144,7 +172,7 @@ class ERR_EnvironmentCommands if (parts.Count() == 3 && parts[2] == "show") { if (environment) replies.Insert(environment.Status()); - replies.Insert("Next round: date " + ERR_EnvironmentService.Date(settings.Get("startDateCode")) + ", weather " + ERR_EnvironmentService.ProfileName(settings.Get("weatherProfile")) + "."); + replies.Insert("Next round: date " + ERR_AdminMenuFields.Display("startDateCode", settings.Get("startDateCode").ToString()) + ", weather " + ERR_AdminMenuFields.Display("weatherProfile", settings.Get("weatherProfile").ToString()) + "."); return true; } int value; @@ -153,12 +181,11 @@ class ERR_EnvironmentCommands if (parts[1] == "weather") key = "weatherProfile"; if (parts.Count() == 4 && parts[2] == "set") { - if (key == "startDateCode") valid = ERR_EnvironmentService.ParseDate(parts[3], value); - else valid = ERR_EnvironmentService.ParseProfile(parts[3], value); + valid = ERR_CommandArguments.Selection(key, parts[3], value); } if (valid && settings.Set(key, value)) - replies.Insert("Saved for next round: date " + ERR_EnvironmentService.Date(settings.Get("startDateCode")) + ", weather " + ERR_EnvironmentService.ProfileName(settings.Get("weatherProfile")) + ". Current round unchanged."); - else replies.Insert("Invalid environment or settings could not be saved. Use mission date set YYYY-MM-DD (1900-2050) or authored; mission weather set authored|clear|overcast|rain. Previous setting retained."); + replies.Insert("Saved for next round: date " + ERR_AdminMenuFields.Display("startDateCode", settings.Get("startDateCode").ToString()) + ", weather " + ERR_AdminMenuFields.Display("weatherProfile", settings.Get("weatherProfile").ToString()) + ". Current round unchanged."); + else replies.Insert("Invalid environment or settings could not be saved. Use mission date set YYYY-MM-DD (1900-2050) or authored|random; mission weather set authored|clear|overcast|rain|random. Previous setting retained."); return true; } } diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_FactionMenu.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_FactionMenu.c new file mode 100644 index 0000000..c9b3082 --- /dev/null +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_FactionMenu.c @@ -0,0 +1,96 @@ +// Uses only authenticated server snapshots for eligibility and saved role choices. +modded class ERR_AdminMenu +{ + protected ref array m_FactionIds = {}; + protected ref array m_FactionButtons = {}; + protected ref map m_FactionSaved = new map(); + protected ref map m_FactionActive = new map(); + protected bool m_FactionFieldsInitialized; + override void OnMenuOpen() + { + super.OnMenuOpen(); + array names = {"FactionsApply", "FactionsRandomAll"}; + foreach (string name : names) + { + SCR_ButtonTextComponent button = SCR_ButtonTextComponent.GetButtonText(name, GetRootWidget()); + if (!button) { Close(); return; } + button.m_OnClicked.Insert(OnFactionButton); m_FactionButtons.Insert(button); + } + UpdateActions(); + } + override void OnMenuClose() + { + foreach (SCR_ButtonTextComponent button : m_FactionButtons) if (button) button.m_OnClicked.Remove(OnFactionButton); + m_FactionButtons.Clear(); m_FactionIds.Clear(); m_FactionSaved.Clear(); m_FactionActive.Clear(); m_FactionFieldsInitialized = false; + super.OnMenuClose(); + } + protected override void UpdateActions() + { + super.UpdateActions(); + bool ready = m_Ready && m_FactionSaved.Count() == 3 && m_FactionActive.Count() == 3; + foreach (SCR_ButtonTextComponent button : m_FactionButtons) + if (button) button.SetEnabled(ready); + foreach (string role : ERR_FactionChoices.Roles()) + { + SCR_ComboBoxComponent combo = SCR_ComboBoxComponent.GetComboBoxComponent("FactionSelect_" + role, GetRootWidget()); + if (combo) combo.SetEnabled(ready); + if (ready) SetText("FactionState_" + role, "Current: " + ERR_FactionChoices.Label(m_FactionActive.Get(role)) + " | Saved: " + ERR_FactionChoices.Label(m_FactionSaved.Get(role))); + } + } + override void ReceiveSnapshot(bool authorized, array values, array status) + { + m_FactionSaved.Clear(); m_FactionActive.Clear(); + array available = {"random"}; + if (authorized && values) + foreach (string value : values) + { + array pair = {}; value.Split("=", pair, true); + if (pair.Count() != 2) continue; + if (pair[0] == "factionAvailable" && ERR_FactionChoices.Find(pair[1]) && !available.Contains(pair[1])) available.Insert(pair[1]); + foreach (string role : ERR_FactionChoices.Roles()) + { + if (pair[0] == "factionSaved_" + role) m_FactionSaved.Set(role, pair[1]); + if (pair[0] == "factionActive_" + role) m_FactionActive.Set(role, pair[1]); + } + } + bool changed = available.Count() != m_FactionIds.Count(); + if (!changed) for (int i = 0; i < available.Count(); i++) if (available[i] != m_FactionIds[i]) changed = true; + if (authorized && m_FactionSaved.Count() == 3 && (changed || !m_FactionFieldsInitialized)) + { + foreach (string role : ERR_FactionChoices.Roles()) + { + SCR_ComboBoxComponent combo = SCR_ComboBoxComponent.GetComboBoxComponent("FactionSelect_" + role, GetRootWidget()); + if (!combo) continue; + string draft = m_FactionSaved.Get(role); + int previous = combo.GetCurrentIndex(); + if (m_FactionFieldsInitialized && previous >= 0 && previous < m_FactionIds.Count()) draft = m_FactionIds[previous]; + combo.ClearAll(); + foreach (string id : available) combo.AddItem(ERR_FactionChoices.Label(id)); + combo.SetCurrentItem(Math.Max(0, available.Find(draft)), false, false, false); + } + m_FactionIds.Copy(available); m_FactionFieldsInitialized = true; + } + super.ReceiveSnapshot(authorized, values, status); + } + protected void OnFactionButton(SCR_ButtonBaseComponent button) + { + if (!button) return; + string name = button.GetRootWidget().GetName(); + if (!m_Ready || !IsFocused() || !m_Controller || m_Age > 6 || m_ClickDelay > 0 || !m_FactionFieldsInitialized) return; + if (name == "FactionsRandomAll") + { + foreach (string role : ERR_FactionChoices.Roles()) SCR_ComboBoxComponent.GetComboBoxComponent("FactionSelect_" + role, GetRootWidget()).SetCurrentItem(0); + return; + } + if (name != "FactionsApply") return; + string command = "factions set"; + foreach (string role : ERR_FactionChoices.Roles()) + { + int index = SCR_ComboBoxComponent.GetComboBoxComponent("FactionSelect_" + role, GetRootWidget()).GetCurrentIndex(); + if (index < 0 || index >= m_FactionIds.Count()) return; + command += " " + m_FactionIds[index]; + } + m_ClickDelay = 0.3; SetText("Feedback", "Saving faction selections..."); + m_Controller.ERR_AdminSubmit(command, true); + } +} diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_FactionSelection.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_FactionSelection.c new file mode 100644 index 0000000..b7d8b26 --- /dev/null +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_FactionSelection.c @@ -0,0 +1,268 @@ +// Saved role choices are stable registry IDs, never menu indexes. Random resolves +// once per round on the server, without replacement across the three roles. +class ERR_FactionChoice +{ + string Id; + string Label; + string Key; + ResourceName Group; + void ERR_FactionChoice(string id, string label, string key, ResourceName group) + { Id = id; Label = label; Key = key; Group = group; } +} +class ERR_FactionChoices +{ + static array Roles() { return {"escapists", "enemy", "independent"}; } + static array All() + { + array choices = {}; + choices.Insert(new ERR_FactionChoice("us", "US Army", "US", "{84E5BBAB25EA23E5}Prefabs/Groups/BLUFOR/Group_US_FireTeam.et")); + choices.Insert(new ERR_FactionChoice("ussr", "Soviet Army", "USSR", "{D5A4D0D3AE1A3E26}Prefabs/ERR/Patrol.et")); + choices.Insert(new ERR_FactionChoice("fia", "FIA", "FIA", "{5BEA04939D148B1D}Prefabs/Groups/INDFOR/Group_FIA_FireTeam.et")); + ERR_ContentDefinition definition = ERR_ContentRegistry.Definition(); + if (definition && definition.Valid()) + foreach (ERR_ContentOption option : definition.Options) + { + if (option.NativeFactionKey.IsEmpty()) continue; + bool duplicate; + foreach (ERR_FactionChoice existing : choices) if (existing.Id == option.Id || existing.Key == option.NativeFactionKey) duplicate = true; + if (!duplicate) choices.Insert(new ERR_FactionChoice(option.Id, option.Label, option.NativeFactionKey, option.GuardGroup)); + } + return choices; + } + static ERR_FactionChoice Find(string id) + { + foreach (ERR_FactionChoice choice : All()) if (choice.Id == id) return choice; + return null; + } + static string Label(string id) + { + if (id == "random") return "Random"; + ERR_FactionChoice choice = Find(id); + if (choice) return choice.Label; + return "Unavailable (" + id + ")"; + } + static bool Enabled(string id, ERR_ContentSettings settings) + { + if (id == "us" || id == "ussr" || id == "fia") return true; + ERR_ContentOption option = ERR_ContentRegistry.Definition().Find(id); + return option && settings && settings.Enabled(id) && (option.Parent.IsEmpty() || settings.Enabled(option.Parent)); + } + static bool Resolve(array available, map saved, map resolved) + { + resolved.Clear(); + if (available.Count() < 3 || !Distinct(saved)) return false; + // Reserve every explicit choice first, so Random cannot steal a later role. + foreach (string fixedRole : Roles()) + { + string fixedId = saved.Get(fixedRole); + if (fixedId == "random" || !available.Contains(fixedId)) continue; + resolved.Set(fixedRole, fixedId); available.RemoveItem(fixedId); + } + foreach (string randomRole : Roles()) + { + if (resolved.Contains(randomRole)) continue; + if (available.IsEmpty()) return false; + int index = Math.RandomInt(0, available.Count()); + resolved.Set(randomRole, available[index]); available.Remove(index); + } + return true; + } + static bool Distinct(map selections) + { + array fixed = {}; + foreach (string role : Roles()) + { + if (!selections.Contains(role)) return false; + string id = selections.Get(role); + if (id == "random") continue; + if (!Find(id) || fixed.Contains(id)) return false; + fixed.Insert(id); + } + return true; + } +} +class ERR_FactionSelection +{ + static const string PATH = "$profile:EscapistsFactions.json"; + protected string m_Path; + protected bool m_ReadOnly; + protected bool m_Ready; + protected ref map m_Saved = new map(); + protected ref map m_Resolved = new map(); + void ERR_FactionSelection(string path = PATH) + { + m_Path = path; + m_Saved.Set("escapists", "us"); m_Saved.Set("enemy", "ussr"); m_Saved.Set("independent", "fia"); + if (!Replication.IsServer()) { m_ReadOnly = true; return; } + map loaded; + if (Read(m_Path, loaded) || Read(m_Path + ".bak", loaded)) m_Saved = loaded; + else if (FileIO.FileExists(m_Path) || FileIO.FileExists(m_Path + ".bak")) + { m_ReadOnly = true; Print("Escapists: invalid faction selections; defaults active and files preserved", LogLevel.ERROR); } + } + protected bool Read(string path, out map values) + { + JsonLoadContext json = new JsonLoadContext(); + if (!json.LoadFromFile(path)) return false; + values = new map(); + foreach (string role : ERR_FactionChoices.Roles()) + { + string id; + if (!json.ReadValue(role, id) || (id != "random" && !ERR_FactionChoices.Find(id))) return false; + values.Set(role, id); + } + return ERR_FactionChoices.Distinct(values); + } + protected bool Same(map a, map b) + { + if (!a || !b) return false; + foreach (string role : ERR_FactionChoices.Roles()) if (!a.Contains(role) || !b.Contains(role) || a.Get(role) != b.Get(role)) return false; + return true; + } + string Saved(string role) { return m_Saved.Get(role); } + string Active(string role) { return m_Resolved.Get(role); } + bool Ready() { return m_Ready; } + ERR_FactionChoice Choice(string role) { return ERR_FactionChoices.Find(Active(role)); } + ResourceName Soldier() + { + ERR_FactionChoice enemy = Choice("enemy"); + if (!enemy) return ""; + Resource resource = Resource.Load(enemy.Group); + if (!resource || !resource.IsValid()) return ""; + IEntitySource source = resource.GetResource().ToEntitySource(); + array members = {}; + if (!source || !source.Get("m_aUnitPrefabSlots", members) || members.IsEmpty()) return ""; + return members[0]; + } + bool Save(array ids, ERR_ContentSettings content) + { + if (!Replication.IsServer() || m_ReadOnly || !ids || ids.Count() != 3) return false; + map values = new map(); + array roles = ERR_FactionChoices.Roles(); + for (int i = 0; i < roles.Count(); i++) + { + if (ids[i] != "random" && !ERR_FactionChoices.Enabled(ids[i], content)) return false; + values.Set(roles[i], ids[i]); + } + if (!ERR_FactionChoices.Distinct(values)) return false; + JsonSaveContext json = new JsonSaveContext(); json.EnableTypeDiscriminator(false); + foreach (string role : roles) json.WriteValue(role, values.Get(role)); + map checked; + if (!json.SaveToFile(m_Path + ".tmp") || !Read(m_Path + ".tmp", checked) || !Same(values, checked)) return false; + map previous; + bool hadPrevious = Read(m_Path, previous); + if (hadPrevious && !FileIO.CopyFile(m_Path, m_Path + ".bak")) return false; + if (!FileIO.CopyFile(m_Path + ".tmp", m_Path) || !Read(m_Path, checked) || !Same(values, checked)) + { + if (hadPrevious) FileIO.CopyFile(m_Path + ".bak", m_Path); + else FileIO.DeleteFile(m_Path); + return false; + } + m_Saved = checked; return true; + } + bool Prepare(ERR_GameMode mode) + { + if (m_Ready) return true; + if (!Replication.IsServer() || !mode || !mode.Factions()) return false; + m_Resolved.Clear(); + array available = {}; + foreach (ERR_FactionChoice option : ERR_FactionChoices.All()) + { + if (!ERR_FactionChoices.Enabled(option.Id, mode.ContentSettings())) continue; + if (!GetGame().GetFactionManager().GetFactionByKey(option.Key)) continue; + Resource resource = Resource.Load(option.Group); + if (resource && resource.IsValid()) available.Insert(option.Id); + } + if (available.Count() < 3) return false; + if (!ERR_FactionChoices.Resolve(available, m_Saved, m_Resolved)) return false; + mode.Factions().PlayerFactionKey = Choice("escapists").Key; + mode.Factions().EnemyFactionKey = Choice("enemy").Key; + mode.Factions().GuardGroupPrefab = Choice("enemy").Group; + SCR_FactionManager manager = SCR_FactionManager.Cast(GetGame().GetFactionManager()); + if (!manager) return false; + foreach (string a : ERR_FactionChoices.Roles()) + foreach (string b : ERR_FactionChoices.Roles()) + { + SCR_Faction first = SCR_Faction.Cast(manager.GetFactionByKey(Choice(a).Key)); + SCR_Faction second = SCR_Faction.Cast(manager.GetFactionByKey(Choice(b).Key)); + if (a == b) manager.SetFactionsFriendly(first, second, -1, false); + else manager.SetFactionsHostile(first, second, -1, false); + } + SCR_Faction player = SCR_Faction.Cast(manager.GetFactionByKey(Choice("escapists").Key)); + player.SetIsPlayable(true); + if (!player.IsPlayable()) return false; + m_Ready = true; + mode.PublishFactionRoles(Choice("escapists").Key, Choice("enemy").Key); + PrintFormat("Escapists factions: players=%1 enemy=%2 independent=%3", Choice("escapists").Key, Choice("enemy").Key, Choice("independent").Key); + return true; + } + void Snapshot(ERR_ContentSettings content, array values) + { + foreach (string role : ERR_FactionChoices.Roles()) + { + values.Insert("factionSaved_" + role + "=" + Saved(role)); + values.Insert("factionActive_" + role + "=" + Active(role)); + } + foreach (ERR_FactionChoice option : ERR_FactionChoices.All()) + if (ERR_FactionChoices.Enabled(option.Id, content)) values.Insert("factionAvailable=" + option.Id); + } +} +class ERR_FactionAdminProvider : ERR_AdminProvider +{ + override string Id() { return "factions"; } + override void Capabilities(array values) + { + ERR_GameMode mode = ERR_GameMode.Get(); + if (mode && mode.FactionSelection()) mode.FactionSelection().Snapshot(mode.ContentSettings(), values); + } + override bool Execute(ERR_GameMode mode, string arguments, array replies) + { + array parts = {}; arguments.Split(" ", parts, true); + if (parts.IsEmpty() || parts[0] != "factions") return false; + if (parts.Count() == 5 && parts[1] == "set") + { + array ids = {parts[2], parts[3], parts[4]}; + if (mode.FactionSelection().Save(ids, mode.ContentSettings())) replies.Insert("Faction selections saved for next round. Current factions unchanged."); + else replies.Insert("Could not save factions. Choose three distinct enabled factions, or Random. Previous selections retained."); + return true; + } + foreach (string role : ERR_FactionChoices.Roles()) replies.Insert(role + ": " + ERR_FactionChoices.Label(mode.FactionSelection().Active(role)) + "; next round: " + ERR_FactionChoices.Label(mode.FactionSelection().Saved(role))); + replies.Insert("Use the Factions menu, or /esc factions set ; each accepts a faction ID or random."); + return true; + } +} + +// Only the live mission policy follows role selections. Isolated policy probes +// and registry tooling keep the generic content eligibility behavior. +modded class ERR_ContentPolicy +{ + protected ERR_FactionSelection Roles() + { + ERR_GameMode mode = ERR_GameMode.Get(); + if (mode && mode.Content() == this && mode.FactionSelection() && mode.FactionSelection().Ready()) return mode.FactionSelection(); + return null; + } + override bool Enemy(Faction faction) + { + ERR_FactionSelection roles = Roles(); + if (roles) return faction && faction.GetFactionKey() == roles.Choice("independent").Key; + return super.Enemy(faction); + } + override ResourceName GuardGroup(int index) + { + ERR_FactionSelection roles = Roles(); + if (!roles) return super.GuardGroup(index); + if (index % 2 == 0) return roles.Choice("independent").Group; + return roles.Choice("enemy").Group; + } + override string GuardFaction(ResourceName prefab) + { + ERR_FactionSelection roles = Roles(); + if (roles) + { + if (prefab == roles.Choice("independent").Group) return roles.Choice("independent").Key; + if (prefab == roles.Choice("enemy").Group) return roles.Choice("enemy").Key; + return ""; + } + return super.GuardFaction(prefab); + } +} diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_ForceLedger.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_ForceLedger.c index 617bc72..d2a2023 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_ForceLedger.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_ForceLedger.c @@ -104,9 +104,9 @@ class ERR_ForceLedger if (group && FindGroup(group)) return null; // Retired source IDs also occupy the finite pool: re-registering a removed // formation cannot replace its casualties with a fresh full-strength unit. - if (m_Records.Count() >= 128 || m_Sources.Count() >= 128) + if (m_Records.Count() >= 256 || m_Sources.Count() >= 256) { - if (!m_CapLogged) Print("Reintroduced [ledger]: 128-formation registration cap reached."); + if (!m_CapLogged) Print("Reintroduced [ledger]: 256-formation registration cap reached."); m_CapLogged = true; return null; } diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_GameMode.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_GameMode.c index da97302..b1379bf 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_GameMode.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_GameMode.c @@ -3,6 +3,8 @@ class ERR_GameMode : SCR_BaseGameMode { [RplProp(), Attribute("6090 0 7160", UIWidgets.Coords, "Prison position; configured from authored scenario")] protected vector m_PrisonPosition; + [RplProp()] protected float m_PrisonHeading; + float PrisonHeading() { return m_PrisonHeading; } [Attribute("6090 0 7160", UIWidgets.Coords, "Centre of extraction boundary")] protected vector m_EscapeCenter; [RplProp(), Attribute("9000", UIWidgets.EditBox, "Helicopter must cross this radius to escape")] @@ -14,7 +16,18 @@ class ERR_GameMode : SCR_BaseGameMode [RplProp()] protected string m_PreparationError; protected ref ERR_FactionCatalog m_Factions; + protected ref ERR_FactionSelection m_FactionSelection; + [RplProp()] protected string m_SelectedPlayerFaction; + [RplProp()] protected string m_SelectedEnemyFaction; + ERR_FactionSelection FactionSelection() { return m_FactionSelection; } + void PublishFactionRoles(string player, string enemy) + { + if (!Replication.IsServer()) return; + m_SelectedPlayerFaction = player; m_SelectedEnemyFaction = enemy; Replication.BumpMe(); + } protected ref ERR_Settings m_Settings; + protected ref ERR_ContentPolicy m_Content; + protected ref ERR_ContentSettings m_ContentSettings; protected ref ERR_TimeService m_Time = new ERR_TimeService(); protected ref ERR_EnvironmentService m_Environment = new ERR_EnvironmentService(); protected ref ERR_DiscoveryService m_Discovery; @@ -60,6 +73,12 @@ class ERR_GameMode : SCR_BaseGameMode ERR_PlayerRoster Players() { return m_Roster; } ERR_AdminService Admin() { return m_Admin; } ERR_Settings Settings() { return m_Settings; } + ERR_ContentPolicy Content() { return m_Content; } + ERR_ContentSettings ContentSettings() { return m_ContentSettings; } + bool IsMissionEnemy(Faction faction) + { + return faction && (faction == EnemyFaction() || (m_Content && m_Content.Enemy(faction))); + } ERR_DiscoveryService Discovery() { return m_Discovery; } ERR_TimeService Time() { return m_Time; } ERR_EnvironmentService Environment() { return m_Environment; } @@ -112,11 +131,13 @@ class ERR_GameMode : SCR_BaseGameMode Faction PlayerFaction() { if (!m_Factions) return null; + if (!m_SelectedPlayerFaction.IsEmpty()) return GetGame().GetFactionManager().GetFactionByKey(m_SelectedPlayerFaction); return m_Factions.PlayerFaction(); } Faction EnemyFaction() { if (!m_Factions) return null; + if (!m_SelectedEnemyFaction.IsEmpty()) return GetGame().GetFactionManager().GetFactionByKey(m_SelectedEnemyFaction); return m_Factions.EnemyFaction(); } string PreparationError() { return m_PreparationError; } @@ -164,10 +185,11 @@ class ERR_GameMode : SCR_BaseGameMode bool Active() { return !m_Stopped && !m_NativeEndHandled && m_Phase >= ERR_Phase.PRISON && !ERR_MissionRules.Terminal(m_Phase); } protected ERR_CommandService CreateCommandService() { return null; } - void ConfigureStart(vector position) + void ConfigureStart(vector position, float heading = 0) { if (!Replication.IsServer() || m_Phase != ERR_Phase.PREPARING) return; m_PrisonPosition = position; + m_PrisonHeading = heading; m_EscapeCenter = position; Replication.BumpMe(); } @@ -226,6 +248,13 @@ class ERR_GameMode : SCR_BaseGameMode } } if (m_Command) m_Command.RegisterGroup(group); + ERR_ForceRecord auditRecord = m_Forces.FindGroup(group); + string auditSource = "mission-owned hostile faction"; + if (auditRecord) auditSource = auditRecord.SourceId; + else if (Sites() && Sites().FindGroup(group)) auditSource = Sites().FindGroup(group).Definition.Id; + string auditFaction; + if (group.GetFaction()) auditFaction = group.GetFaction().GetFactionKey(); + PrintFormat("Reintroduced [SPAWN GROUP]: source=%1 faction=%2 group=%3 position=%4 living=%5", auditSource, auditFaction, group, group.GetOrigin(), ForceLiving(group)); m_OnGroup.Invoke(group); } @@ -358,6 +387,11 @@ class ERR_GameMode : SCR_BaseGameMode if (!System.IsConsoleApp()) GetGame().GetCallqueue().CallLater(BindLocalObserver, 250, true); if (!Replication.IsServer()) return; m_Settings = new ERR_Settings(SettingsPath()); + m_ContentSettings = new ERR_ContentSettings(); + m_Content = new ERR_ContentPolicy(m_ContentSettings); + m_FactionSelection = new ERR_FactionSelection(); + m_Admin.Register(new ERR_ContentAdminProvider(m_Content)); + m_Admin.Register(new ERR_FactionAdminProvider()); OnStop().Insert(m_Environment.Stop); m_Recovery = new ERR_RecoveryService(this); m_Recovery.OnChanged().Insert(RecoveryChanged); @@ -405,7 +439,9 @@ class ERR_GameMode : SCR_BaseGameMode protected void StartScenario() { if (m_Stopped || m_NativeEndHandled || m_Phase != ERR_Phase.PREPARING || !m_PreparationError.IsEmpty()) return; + if (!m_FactionSelection || !m_FactionSelection.Prepare(this)) { FailPreparation("Three enabled faction profiles are required for the mission roles."); return; } if (!m_Factions || !m_Factions.WorldReady()) { FailPreparation("The configured player and enemy factions or required assets are missing, invalid or not hostile."); return; } + if (!m_Content || !m_Content.PrepareFactions(this)) { FailPreparation("The content registry or enabled faction profiles are invalid. Check faction keys, guard groups and the mission faction manager."); return; } // Scenario content is created through a separate authoring component. ERR_ScenarioComponent scenario = ERR_ScenarioComponent.Cast(FindComponent(ERR_ScenarioComponent)); ERR_PrepareResult prepared = ERR_PrepareResult.FAILED; diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_GeneratedSites.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_GeneratedSites.c new file mode 100644 index 0000000..8f55425 --- /dev/null +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_GeneratedSites.c @@ -0,0 +1,148 @@ +// Clear-ground sampling adapted from the owner's improvised-prison extension (see migration provenance). +// Searches create no entities and finish before any site starts spawning. +class ERR_CampTerrain +{ + protected ref array m_Airfields = {}; + protected bool Airport(IEntity entity) + { + if (!entity || !entity.GetPrefabData()) return false; + string path = entity.GetPrefabData().GetPrefabName(); path.ToLower(); + return path.Contains("prefabs/structures/") && (path.Contains("/runway") || path.Contains("/lightrunway_") || path.Contains("/aircontroltower") || path.Contains("/airportcontroltower") || path.Contains("/controltower")); + } + protected bool AddAirport(IEntity entity) { m_Airfields.Insert(entity.GetOrigin()); return true; } + void Collect(vector low, vector high) + { + GetGame().GetWorld().QueryEntitiesByAABB(Vector(low[0], -1000, low[2]), Vector(high[0], 5000, high[2]), AddAirport, Airport, EQueryEntitiesFlags.ALL); + } + static vector Rotate(vector offset, float heading) + { + vector rotation[3]; Math3D.AnglesToMatrix(Vector(heading, 0, 0), rotation); + return rotation[0] * offset[0] + rotation[1] * offset[1] + rotation[2] * offset[2]; + } + static vector Local(vector offset, float heading) + { + vector rotation[3]; Math3D.AnglesToMatrix(Vector(heading, 0, 0), rotation); + return Vector(vector.Dot(offset, rotation[0]), offset[1], vector.Dot(offset, rotation[2])); + } + bool Clear(vector center, float heading, float halfSize, float maximumRange, out float lowest) + { + lowest = float.MAX; float highest = -float.MAX; + for (int x = -1; x <= 1; x++) + for (int z = -1; z <= 1; z++) + { + vector corner = center + Rotate(Vector(x * halfSize, 0, z * halfSize), heading); + if (ChimeraWorldUtils.TryGetWaterSurfaceSimple(GetGame().GetWorld(), corner)) return false; + } + // A 2m grid covers the walls, door approach, furniture and all interior slots. + for (float dx = -halfSize; dx <= halfSize; dx += 2) + for (float dz = -halfSize; dz <= halfSize; dz += 2) + { + vector sample = center + Rotate(Vector(dx, 0, dz), heading); + float height = GetGame().GetWorld().GetSurfaceY(sample[0], sample[2]); + lowest = Math.Min(lowest, height); highest = Math.Max(highest, height); + if (lowest < 1 || highest - lowest > maximumRange) return false; + } + for (float cx = -halfSize + 1; cx < halfSize; cx += 2) + for (float cz = -halfSize + 1; cz < halfSize; cz += 2) + { + vector cell = center + Rotate(Vector(cx, 0, cz), heading); + float ground = GetGame().GetWorld().GetSurfaceY(cell[0], cell[2]); + TraceBox trace = new TraceBox(); + trace.Start = Vector(cell[0], ground + 0.12, cell[2]); trace.End = trace.Start + "0 4 0"; + // Bounding the rotated cell conservatively also protects the exit corridor. + trace.Mins = "-1.42 0 -1.42"; trace.Maxs = "1.42 0.1 1.42"; + trace.Flags = TraceFlags.ENTS | TraceFlags.WORLD; + if (GetGame().GetWorld().TraceMove(trace, null) < 1) return false; + } + return true; + } + bool Site(ERR_SiteDefinition site, vector position, float heading, out float baseHeight) + { + bool prison = site.Kind == ERR_LocationKind.PRISON; + if (prison) + { + foreach (vector airport : m_Airfields) if (vector.DistanceXZ(position, airport) < 1500) return false; + } + SCR_AIWorld aiWorld = SCR_AIWorld.Cast(GetGame().GetAIWorld()); + if (!aiWorld || !aiWorld.GetRoadNetworkManager()) return false; + BaseRoad road; float distance; + aiWorld.GetRoadNetworkManager().GetClosestRoad(position, road, distance, skipNavlinks: true); + if (road && distance < 12) return false; + if (!Clear(position, heading, 10, 0.6, baseHeight)) return false; + float guardHeight; + if (site.Guarded && !Clear(position + Rotate(site.GuardOffset, heading), heading, 6, 0.6, guardHeight)) return false; + return true; + } +} +class ERR_GeneratedSites +{ + protected ERR_ScenarioDefinition m_Definition; + protected ref ERR_CampTerrain m_Terrain = new ERR_CampTerrain(); + protected ref array m_Pending = {}; + protected vector m_Low, m_High; + protected int m_Index, m_Attempts, m_Began; + protected bool m_Started; + protected ERR_PrepareResult m_Result = ERR_PrepareResult.PENDING; + protected string m_Error; + string Error() { return m_Error; } + bool Begin(ERR_ScenarioDefinition definition) + { + if (m_Started || !Replication.IsServer() || !definition || !definition.Valid() || !GetGame().GetWorldEntity()) return false; + m_Started = true; m_Definition = definition; + // Prison resolves first, irrespective of authored array order. + foreach (ERR_SiteDefinition prison : definition.Sites) if (prison.RandomClear && prison.Kind == ERR_LocationKind.PRISON) m_Pending.Insert(prison); + foreach (ERR_SiteDefinition radio : definition.Sites) if (radio.RandomClear && radio.Kind == ERR_LocationKind.RADIO) m_Pending.Insert(radio); + foreach (ERR_SiteDefinition mortar : definition.Sites) if (mortar.RandomClear && mortar.Kind == ERR_LocationKind.MORTAR) m_Pending.Insert(mortar); + GetGame().GetWorldEntity().GetWorldBounds(m_Low, m_High); + if (!m_Pending.IsEmpty()) m_Terrain.Collect(m_Low, m_High); + m_Began = System.GetTickCount(); + return true; + } + protected bool Separated(ERR_SiteDefinition candidate, vector position, bool fallback) + { + foreach (ERR_SiteDefinition other : m_Definition.Sites) + { + if (other == candidate) continue; + if (candidate.Kind == ERR_LocationKind.PRISON && other.Kind == ERR_LocationKind.RADIO && other.RandomClear) continue; + float minimum = 300; + if (candidate.Kind == ERR_LocationKind.MORTAR && other.Kind == ERR_LocationKind.MORTAR) minimum = 1000; + if (candidate.Kind == ERR_LocationKind.MORTAR && other.Kind == ERR_LocationKind.PRISON) minimum = 500; + if (candidate.Kind == ERR_LocationKind.RADIO && other.Kind == ERR_LocationKind.PRISON) minimum = 1000; + if (vector.DistanceXZ(position, other.Position) < minimum) return false; + if (candidate.Kind == ERR_LocationKind.PRISON && other.Kind == ERR_LocationKind.EXTRACTION && vector.DistanceXZ(position, other.Position) + 100 >= ERR_GameMode.Get().EscapeRadius()) return false; + } + return true; + } + ERR_PrepareResult Tick() + { + if (m_Result != ERR_PrepareResult.PENDING) return m_Result; + if (!m_Started || !Replication.IsServer()) return ERR_PrepareResult.FAILED; + int tick = System.GetTickCount(); + while (m_Index < m_Pending.Count()) + { + ERR_SiteDefinition site = m_Pending[m_Index]; + bool fallback = m_Attempts >= 12000 || System.GetTickCount() - m_Began >= 30000; + vector position = site.Position; float heading = site.Heading; + if (!fallback) + { + position = Vector(Math.RandomFloat(m_Low[0] + 50, m_High[0] - 50), 0, Math.RandomFloat(m_Low[2] + 50, m_High[2] - 50)); + heading = Math.RandomFloat(0, 360); m_Attempts++; + } + float floor; + if (Separated(site, position, fallback) && m_Terrain.Site(site, position, heading, floor)) + { + position[1] = floor + 0.02; + site.Position = position; site.Heading = heading; site.PlacementResolved = true; + PrintFormat("Escapists [generated site]: id=%1 position=%2 heading=%3 attempts=%4 fallback=%5", site.Id, position, heading, m_Attempts, fallback); + m_Index++; m_Attempts = 0; + } + else if (fallback) + { + m_Error = "No safe terrain or valid authored fallback for " + site.Id; + m_Result = ERR_PrepareResult.FAILED; return m_Result; + } + if (System.GetTickCount() - tick >= 8) return ERR_PrepareResult.PENDING; + } + m_Result = ERR_PrepareResult.READY; return m_Result; + } +} diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_Location.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_Location.c index b26d4f2..ff205a8 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_Location.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_Location.c @@ -1,4 +1,4 @@ -enum ERR_LocationKind { PRISON, RADIO, EXTRACTION, OUTPOST, DEPOT } +enum ERR_LocationKind { PRISON, RADIO, EXTRACTION, OUTPOST, DEPOT, MORTAR } [ComponentEditorProps(category: "Reintroduced", description: "Server-owned location with replicated discovery state")] class ERR_LocationComponentClass : ScriptComponentClass {} diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAdminMenuProbe.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAdminMenuProbe.c index 2eec258..e2545f4 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAdminMenuProbe.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAdminMenuProbe.c @@ -1,9 +1,47 @@ #ifdef WORKBENCH +modded class PauseMenuUI +{ + static bool ERR_ProbeModsEntry() + { + return s_Instance && s_Instance.m_ERRModsButton; + } + static void ERR_ProbeOpenMods() { if (s_Instance) s_Instance.ERR_OpenMods(); } +} // Explicit local fixture: real dialog, widgets and owner RPCs; no mouse/remote claim. modded class ERR_AdminMenu { - bool ERR_ProbeReady() { return m_Ready && m_AvailableFields.Count() == 10; } - void ERR_ProbePage(int page) { ShowPage(page); } + bool ERR_ProbeReady() { return m_Ready && m_AvailableFields.Count() == ERR_AdminMenuFields.Keys().Count(); } + void ERR_ProbePage(int page) + { + OnButton(SCR_ButtonTextComponent.GetButtonText(Navigation()[page], GetRootWidget())); + } + bool ERR_ProbeNavigation(int expected) + { + GetRootWidget().Update(); + if (m_Page != expected) return false; + for (int i = 0; i < Pages().Count(); i++) + { + Widget panel = GetRootWidget().FindAnyWidget(Pages()[i]); + Widget tab = GetRootWidget().FindAnyWidget(Navigation()[i]); + Widget selected = GetRootWidget().FindAnyWidget("Selected_" + Navigation()[i]); + if (!panel || !tab || !selected || panel.IsVisible() != (i == expected) || !tab.IsVisible() || selected.IsVisible() != (i == expected)) return false; + float x, y, width, height, px, py; + tab.GetScreenPos(x, y); tab.GetScreenSize(width, height); panel.GetScreenPos(px, py); + if (width <= 1 || height <= 1 || (i == expected && y + height > py)) + { PrintFormat("ERR ADMIN NAV BOUNDS: page=%1 tab=%2 bounds=%3,%4,%5,%6 panelY=%7", expected, i, x, y, width, height, py); return false; } + } + return true; + } + void ERR_ProbeFieldPage(string key) + { + Widget widget = GetRootWidget().FindAnyWidget(key); + while (widget) + { + int page = Pages().Find(widget.GetName()); + if (page >= 0) { ERR_ProbePage(page); return; } + widget = widget.GetParent(); + } + } string ERR_ProbeDraft() { return SCR_EditBoxComponent.GetEditBoxComponent("radioDefenceSeconds", GetRootWidget()).GetValue(); } void ERR_ProbeEdit(string text) { SCR_EditBoxComponent.GetEditBoxComponent("radioDefenceSeconds", GetRootWidget()).SetValue(text); } void ERR_ProbeApply() @@ -11,8 +49,71 @@ modded class ERR_AdminMenu Widget widget = GetRootWidget().FindAnyWidget("Apply_radioDefenceSeconds"); OnButton(SCR_ButtonBaseComponent.Cast(widget.FindHandler(SCR_ButtonBaseComponent))); } + bool ERR_ProbeRandomChoices() + { + foreach (string key : ERR_AdminMenuFields.Keys()) + { + ERR_ProbeFieldPage(key); + SCR_ButtonTextComponent button = SCR_ButtonTextComponent.GetButtonText("Random_" + key, GetRootWidget()); + SCR_EditBoxComponent edit = SCR_EditBoxComponent.GetEditBoxComponent(key, GetRootWidget()); + bool available = ERR_AdminMenuFields.Available(key, m_HQ, m_Intel); + if (!button || !edit || button.IsEnabled() != available) return false; + if (!available) continue; + string previous = edit.GetValue(); + OnButton(button); + if (edit.GetValue() != "Random") return false; + edit.SetValue(previous); + } + ERR_ProbeFieldPage("startTimeMinutes"); + SCR_EditBoxComponent time = SCR_EditBoxComponent.GetEditBoxComponent("startTimeMinutes", GetRootWidget()); + string previousTime = time.GetValue(); + SCR_ButtonTextComponent day = SCR_ButtonTextComponent.GetButtonText("RandomDay_startTimeMinutes", GetRootWidget()); + if (!day || !day.IsEnabled()) return false; + OnButton(day); + bool selected = time.GetValue() == "Random day"; + time.SetValue(previousTime); + ERR_ProbePage(0); + return selected; + } + bool ERR_ProbeFactionRandomAll() + { + if (!m_FactionFieldsInitialized || m_FactionIds.Count() < 4) return false; + ERR_ProbePage(4); + if (m_Page != 4) return false; + OnFactionButton(SCR_ButtonTextComponent.GetButtonText("FactionsRandomAll", GetRootWidget())); + foreach (string role : ERR_FactionChoices.Roles()) + { + SCR_ComboBoxComponent combo = SCR_ComboBoxComponent.GetComboBoxComponent("FactionSelect_" + role, GetRootWidget()); + if (!combo || !combo.IsEnabled() || combo.GetCurrentIndex() != 0) return false; + } + return true; + } + void ERR_ProbeFactionApply() { OnFactionButton(SCR_ButtonTextComponent.GetButtonText("FactionsApply", GetRootWidget())); } bool ERR_ProbeHQ() { return m_HQ; } bool ERR_ProbeIntel() { return m_Intel; } + bool ERR_ProbeMods() + { + GetRootWidget().Update(); + PrintFormat("ERR MOD MENU: page=%1 rows=%2 saved=%3 active=%4", m_Page, m_ModRows.Count(), m_ModSaved.Count(), m_ModActive.Count()); + if (m_Page != 3 || m_ModRows.Count() != ERR_ContentRegistry.Ids().Count()) return false; + foreach (string pack, Widget row : m_ModRows) + { + TextWidget text = TextWidget.Cast(row.FindAnyWidget("PackState")); + if (text) PrintFormat("ERR MOD ROW: id=%1 state=%2", pack, text.GetText()); + if (!text || !text.GetText().Contains("Saved preference:") || !m_ModSaved.Contains(pack) || !m_ModActive.Contains(pack)) return false; + float width, height; row.GetScreenSize(width, height); + PrintFormat("ERR MOD BOUNDS: id=%1 width=%2 height=%3", pack, width, height); + if (width < 100 || height < 2) return false; + } + return true; + } + void ERR_ProbeMod(bool enabled) + { + Widget row = m_ModRows.Get("rhs"); + string name = "Disable"; + if (enabled) name = "Enable"; + OnModButton(SCR_ButtonTextComponent.GetButtonText(name, row)); + } int ERR_ProbeLogCursor() { return m_LogCursor; } bool ERR_ProbeJournalVisible() { @@ -39,10 +140,14 @@ class ERR_NativeAdminMenuProbe protected DamageManagerComponent m_Damage; protected bool m_PreviousDamage; protected int m_Stage; + protected int m_CapturePage; protected float m_Deadline; protected float m_Wait; protected int m_RadioSeconds; protected bool m_Failed; + protected bool m_RhsSaved; + protected ref array m_FactionSaved = {}; + protected ref array m_FactionActive = {}; void ERR_NativeAdminMenuProbe(ERR_GameMode mode) { m_Mode = mode; } protected int Fail(string reason) { @@ -67,8 +172,12 @@ class ERR_NativeAdminMenuProbe m_Damage = DamageManagerComponent.Cast(m_Controller.GetControlledEntity().FindComponent(DamageManagerComponent)); m_PreviousDamage = m_Damage.IsDamageHandlingEnabled(); m_RadioSeconds = m_Mode.Settings().Get("radioDefenceSeconds"); - m_Deadline = now + 45000; - m_Controller.ERR_AdminSubmit("menu"); + m_Deadline = now + 90000; + m_RhsSaved = m_Mode.ContentSettings().Enabled("rhs"); + GetGame().OpenPauseMenu(false, true); + if (!PauseMenuUI.ERR_ProbeModsEntry()) return Fail("Esc menu missing Escapists Reintroduced entry"); + PauseMenuUI.ERR_ProbeOpenMods(); + Pass("native Esc menu entry opens mission administration"); m_Stage = 1; return 0; } if (m_Stage < 6 && !menu) return Fail("dialog unexpectedly closed"); @@ -78,6 +187,32 @@ class ERR_NativeAdminMenuProbe array capabilities = {}; m_Mode.Admin().Capabilities(capabilities); if (menu.ERR_ProbeHQ() != capabilities.Contains("supports=hq") || menu.ERR_ProbeIntel() != capabilities.Contains("supports=intel")) return Fail("capability snapshot mismatch"); Pass("real owner RPC opens menu and returns current settings/capabilities"); + System.MakeScreenshot("$logs:err-admin-open"); + if (!menu.ERR_ProbeNavigation(0)) return Fail("Esc entry did not open Mission page with shared navigation"); + menu.ERR_ProbePage(3); + if (!menu.ERR_ProbeMods()) return Fail("mod rows missing state or collapsed"); + Print("ERR MOD CAPTURE READY"); + menu.ERR_ProbePage(0); + Print("ERR ADMIN CAPTURE PAGE: 0"); + m_Wait = now + 3000; m_Stage = 30; return 0; + } + if (m_Stage == 30) + { + if (!menu || !menu.ERR_ProbeNavigation(m_CapturePage)) return Fail("page or top navigation bounds invalid"); + System.MakeScreenshot("$logs:err-admin-page-" + m_CapturePage.ToString()); + m_CapturePage++; + if (m_CapturePage < ERR_AdminMenu.Pages().Count()) + { menu.ERR_ProbePage(m_CapturePage); Print("ERR ADMIN CAPTURE PAGE: " + m_CapturePage.ToString()); } + else { Pass("all eight pages reached through shared top navigation with one visible page"); m_Stage = 13; } + m_Wait = now + 3000; + return 0; + } + if (m_Stage == 13) + { + if (!menu) return Fail("mods dialog closed during visibility check"); + menu.ERR_ProbePage(0); + if (!menu.ERR_ProbeRandomChoices()) return Fail("random choice controls missing, incorrectly gated or did not select draft"); + Pass("all Random buttons and Random day select editable drafts"); menu.ERR_ProbeEdit("47"); m_Controller.ERR_AdminRequestSnapshot(); m_Wait = now + 3000; m_Stage = 2; return 0; @@ -103,6 +238,51 @@ class ERR_NativeAdminMenuProbe if (m_Mode.Settings().Get("radioDefenceSeconds") != m_RadioSeconds) return Fail("test setting restoration failed"); Pass("test setting restored without resetting menu drafts"); System.MakeScreenshot("$logs:err-admin-hq"); + menu.ERR_ProbePage(3); + menu.ERR_ProbeMod(!m_RhsSaved); + m_Wait = now + 2000; m_Stage = 11; return 0; + } + if (m_Stage == 11) + { + if (!menu || m_Mode.ContentSettings().Enabled("rhs") == m_RhsSaved || m_Mode.Content().Enabled("rhs") != m_RhsSaved || !menu.ERR_ProbeMods()) return Fail("mod button failed to save independently of active round"); + Pass("native mod toggle persists through authenticated owner RPC without changing active content"); + menu.ERR_ProbeMod(m_RhsSaved); + m_Wait = now + 2000; m_Stage = 12; return 0; + } + if (m_Stage == 12) + { + if (!menu || m_Mode.ContentSettings().Enabled("rhs") != m_RhsSaved) return Fail("mod preference restoration failed"); + Pass("native mod toggle restores saved preference"); + foreach (string role : ERR_FactionChoices.Roles()) + { + m_FactionSaved.Insert(m_Mode.FactionSelection().Saved(role)); + m_FactionActive.Insert(m_Mode.FactionSelection().Active(role)); + } + if (!menu.ERR_ProbeFactionRandomAll()) return Fail("faction selectors or Random all failed"); + Pass("three faction selectors and Random all create distinct-role drafts"); + m_Wait = now + 3000; m_Stage = 20; return 0; + } + if (m_Stage == 20) + { + if (!menu || !menu.ERR_ProbeFactionRandomAll()) return Fail("snapshot lost faction drafts"); + menu.ERR_ProbeFactionApply(); + m_Wait = now + 1500; m_Stage = 21; return 0; + } + if (m_Stage == 21) + { + array roles = ERR_FactionChoices.Roles(); + for (int i = 0; i < roles.Count(); i++) + if (m_Mode.FactionSelection().Saved(roles[i]) != "random" || m_Mode.FactionSelection().Active(roles[i]) != m_FactionActive[i]) return Fail("faction Apply failed or changed current round"); + Pass("faction Apply persists all three through authenticated owner RPC without changing active round"); + m_Controller.ERR_AdminSubmit("factions set " + m_FactionSaved[0] + " " + m_FactionSaved[1] + " " + m_FactionSaved[2], true); + m_Wait = now + 1500; m_Stage = 22; return 0; + } + if (m_Stage == 22) + { + array restoredRoles = ERR_FactionChoices.Roles(); + for (int j = 0; j < restoredRoles.Count(); j++) + if (m_Mode.FactionSelection().Saved(restoredRoles[j]) != m_FactionSaved[j]) return Fail("faction restoration failed"); + Pass("saved faction choices restored"); if (menu.ERR_ProbeHQ()) menu.ERR_ProbePage(2); m_Wait = now + 3000; m_Stage = 5; return 0; } diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAdminSettingsProbe.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAdminSettingsProbe.c index c17a68d..965cbe1 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAdminSettingsProbe.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAdminSettingsProbe.c @@ -52,6 +52,57 @@ class ERR_NativeAdminSettingsProbe adapter.Probe(settings, "mission radio show", replies); return Check(replies.Count() == 1 && replies[0] == "radioDefenceSeconds=" + initial.Get("radioDefenceSeconds").ToString(), "existing radio alias and response remain intact"); } + protected static bool RandomChoices(string path, ERR_GameMode mode) + { + ERR_Settings settings = new ERR_Settings(path); + foreach (string key : ERR_AdminMenuFields.Keys()) + { + int parsed; + if (!Check(ERR_CommandArguments.Selection(key, "random", parsed) && parsed == -1 && settings.Set(key, parsed), "random selection saved: " + key)) return false; + ERR_Settings reload = new ERR_Settings(path); + if (!Check(reload.Get(key) == -1 && ERR_AdminMenuFields.Display(key, "-1") == "Random", "random mode survives reload and displays by name: " + key)) return false; + if (key == "startDateCode") continue; + int rolled = settings.Runtime(key); + if (!Check(ERR_Settings.Valid(key, rolled), "random resolves within concrete bounds: " + key)) return false; + for (int i = 0; i < 100; i++) + if (settings.Runtime(key) != rolled) return Check(false, "repeated reads rerolled " + key); + if (!Check(settings.Set(key, -1) && settings.Runtime(key) == rolled, "saving same mode preserves roll: " + key)) return false; + } + int radio = settings.Runtime("radioDefenceSeconds"); + if (!Check(settings.Set("intelRevealChancePercent", 15) && settings.Runtime("radioDefenceSeconds") == radio, "unrelated save does not reroll another option")) return false; + if (!Check(settings.Set("radioDefenceSeconds", 45) && settings.Runtime("radioDefenceSeconds") == 45 && settings.Set("radioDefenceSeconds", -1) && ERR_Settings.Valid("radioDefenceSeconds", settings.Runtime("radioDefenceSeconds")), "fixed value replaces random and random can be selected again")) return false; + if (!Check(!settings.Set("unknown", -1) && !settings.Set("weatherProfile", -2) && !settings.Set("startTimeMinutes", -3), "unknown keys and invalid modes rejected")) return false; + int day; + if (!Check(ERR_CommandArguments.Selection("startTimeMinutes", "random day", day) && day == -2 && settings.Set("startTimeMinutes", day), "Random day parses and saves")) return false; + ERR_Settings reloadedDay = new ERR_Settings(path); + if (!Check(reloadedDay.Get("startTimeMinutes") == -2 && ERR_AdminMenuFields.Display("startTimeMinutes", "-2") == "Random day" && !ERR_CommandArguments.Selection("weatherProfile", "random day", day), "Random day reloads and is restricted to time")) return false; + ChimeraWorld world = ChimeraWorld.CastFrom(mode.GetWorld()); + TimeAndWeatherManagerEntity manager = world.GetTimeAndWeatherManager(); + float sunrise, sunset; + int first, end; + if (!Check(manager.GetSunriseHour(sunrise) && manager.GetSunsetHour(sunset) && ERR_TimeService.DaylightBounds(sunrise, sunset, first, end), "native island sunrise and sunset define Random day")) return false; + if (mode.Settings().Get("startTimeMinutes") == -2) + { + int started = mode.Time().StartMinutes(); + if (!Check(started / 60.0 > sunrise && started / 60.0 < sunset, "actual round starts within native daylight interval")) return false; + } + if (!Check(ERR_Settings.Valid("timeMultiplier", mode.Time().Multiplier()) && ERR_Settings.Valid("startDateCode", mode.Environment().CurrentDateCode()), "actual startup uses concrete speed and valid date")) return false; + for (int sample = 0; sample < 100; sample++) + { + int minute = Math.RandomInt(first, end); + int dateCode = ERR_EnvironmentService.RandomDate(manager.GetYear()); + if (minute / 60.0 <= sunrise || minute / 60.0 >= sunset || !ERR_Settings.Valid("startTimeMinutes", minute)) return Check(false, "daylight roll outside sun bounds"); + if (!ERR_Settings.Valid("startDateCode", dateCode) || 1900 + dateCode / 10000 != manager.GetYear()) return Check(false, "random date outside authored year"); + } + array replies = {}; + ERR_NativeAdminSettingsAdapter adapter = new ERR_NativeAdminSettingsAdapter(); + adapter.Probe(settings, "intel reveal set random", replies); + if (!Check(settings.Get("intelRevealChancePercent") == -1 && replies[0].Contains("Random"), "numeric random passes real command handler")) return false; + replies.Clear(); + ERR_EnvironmentCommands.Execute(settings, mode.Environment(), {"mission", "weather", "set", "random"}, replies); + if (!Check(settings.Get("weatherProfile") == -1 && replies[0].Contains("Random"), "environment random passes real command handler")) return false; + return Check(true, "100 valid daylight and calendar samples; all random modes retained"); + } static bool Run(ERR_GameMode mode) { if (!Check(Replication.IsServer() && mode && mode.Admin() && mode.Settings(), "native Core command service and settings ready")) return false; @@ -65,9 +116,20 @@ class ERR_NativeAdminSettingsProbe if (!Check(replies.Count() == 1 && replies[0].Contains("0-100") && mode.Settings().Get("intelRevealChancePercent") == original, "actual dispatch rejects out-of-range value with guidance")) return false; mode.Admin().Execute(mode, true, "intel reveal help", replies); if (!Check(replies.Count() == 1 && replies[0].Contains("second document"), "actual Core help describes physical document progression")) return false; + int savedTime = mode.Settings().Get("startTimeMinutes"); + int activeTime = mode.Time().StartMinutes(); + mode.Admin().Execute(mode, true, "mission time set random day", replies); + bool dayAccepted = mode.Settings().Get("startTimeMinutes") == -2 && mode.Time().StartMinutes() == activeTime && replies.Count() == 1 && replies[0].Contains("Random day"); + bool timeRestored = mode.Settings().Set("startTimeMinutes", savedTime); + if (!Check(dayAccepted && timeRestored, "Random day command saves next-round mode without jumping active clock; restored")) return false; + mode.Admin().Execute(mode, true, "mission time set random", replies); + bool randomAccepted = mode.Settings().Get("startTimeMinutes") == -1 && mode.Time().StartMinutes() == activeTime && replies.Count() == 1 && replies[0].Contains("Random"); + timeRestored = mode.Settings().Set("startTimeMinutes", savedTime); + if (!Check(randomAccepted && timeRestored, "Random time command preserves active clock; restored")) return false; string path = "$profile:erri-native-admin-settings-probe.json"; if (!Check(!FileIO.FileExists(path) && !FileIO.FileExists(path + ".bak") && !FileIO.FileExists(path + ".tmp"), "disposable fixture filenames are unused")) return false; bool result = Storage(path); + if (result) result = RandomChoices(path, mode); FileIO.DeleteFile(path); FileIO.DeleteFile(path + ".bak"); FileIO.DeleteFile(path + ".tmp"); if (!result) return false; return Check(mode.Settings().Get("intelRevealChancePercent") == original && !FileIO.FileExists(path) && !FileIO.FileExists(path + ".bak") && !FileIO.FileExists(path + ".tmp"), "fixture removed its files and never changed actual mission settings"); diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAggressionProbe.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAggressionProbe.c new file mode 100644 index 0000000..4d3eaa0 --- /dev/null +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAggressionProbe.c @@ -0,0 +1,121 @@ +#ifdef WORKBENCH +modded class ERR_ObjectiveDefence +{ + bool ERR_ProbeMedical() + { + foreach (ERR_ObjectiveDefenceEntry entry : m_Entries) + { + if (entry.Site.Definition.Id != "everon-medical-1") continue; + if (!entry.Spawned || !entry.Admitted || !entry.Group || !entry.Hold) return false; + return entry.Group.IsExpandComplete() && m_Mode.ForceLiving(entry.Group) == entry.Group.m_aUnitPrefabSlots.Count() + && vector.Distance(entry.Hold.GetOrigin(), entry.Site.Location.Position()) < 0.1 + && m_HQ.ERR_ProbeDedicated(entry.Group); + } + return false; + } +} +modded class ERR_HunterService +{ + ERR_HunterVehicle ERR_ProbeFirst() + { + if (m_Hunters.IsEmpty()) return null; + ERR_HunterVehicle first = m_Hunters[0]; + return first; + } +} +modded class ERR_HQ +{ + void ERR_ProbeBody(int slot, float now) + { + ERR_HQReport report = new ERR_HQReport(); + report.TravelMode = "body"; report.MessageId = 100000 + slot; + report.CasualtySourceId = "fixture-identified"; report.CasualtyStrength = 4; report.CasualtySlot = slot; + report.ObservedAt = now; report.Position = "5000 50 5000"; + // Delivered intake boundary; policy tests independently cover route/replay rules. + Accept(report, now); + } + bool ERR_ProbeDedicated(SCR_AIGroup group) + { + foreach (ERR_HQUnit unit : m_Units) if (unit.Group == group) return unit.ReservedForSupport && !unit.Eligible(m_Mode); + return false; + } + bool ERR_ProbeMedicalDefence() { return m_ObjectiveDefence.ERR_ProbeMedical(); } +} +modded class ERR_GameMode +{ + protected int m_ERRAggressionStage; + protected int m_ERRAggressionDeadline; + protected vector m_ERRHunterStart; + protected bool m_ERRHunterOrder; + protected override void EOnInit(IEntity owner) + { + super.EOnInit(owner); + string outcome; + if (!Replication.IsServer() || SCR_Global.IsEditMode() || !System.GetCLIParam("errSmokeOutcome", outcome) || outcome != "aggression") return; + m_ERRAggressionDeadline = System.GetTickCount() + 270000; + GetGame().GetCallqueue().CallLater(ERR_AggressionTick, 1000, true); + } + protected bool ERR_AggressionCheck(bool ok, string text) + { + if (ok) { Print("ERR SMOKE PASS: aggression " + text); return true; } + Print("ERR SMOKE FAIL: aggression " + text, LogLevel.ERROR); + GetGame().GetCallqueue().Remove(ERR_AggressionTick); return false; + } + protected void ERR_AggressionTick() + { + if (System.GetTickCount() >= m_ERRAggressionDeadline || Phase() == ERR_Phase.DEFEAT) { ERR_AggressionCheck(false, "native startup/movement deadline"); return; } + if (Phase() < ERR_Phase.PRISON || !GetGame().GetPlayerController()) return; + IEntity player = GetGame().GetPlayerController().GetControlledEntity(); if (!player) return; + DamageManagerComponent damage = DamageManagerComponent.Cast(player.FindComponent(DamageManagerComponent)); + if (damage) damage.EnableDamageHandling(false); + ERR_HQ hq = ERR_HQ.Get(); if (!hq) return; + float now = GetWorld().GetWorldTime(); + if (m_ERRAggressionStage == 0) + { + if (!ERR_AggressionCheck(UnlockPrison(player), "native prison release")) return; + player.SetOrigin(ERR_Actors.Ground(Sites().Find("everon-medical-1").Location.Position() + "300 0 0")); + for (int i = 0; i < 3; i++) hq.ERR_ProbeBody(i, now); + hq.ERR_ProbeBody(2, now); + if (!ERR_AggressionCheck(hq.Watch().IdentifiedBodies() == 3 && hq.Watch().Aggression() == 1 && hq.Watch().HunterTarget() == 1, "three distinct delivered bodies unlock one UAZ; duplicate ignored")) return; + if (!ERR_AggressionCheck(ERR_HQWatchRules.Aggression(90) == 30 && ERR_HQWatchRules.Hunters(30) == 15 && ERR_HQWatchRules.Hunters(1000) == 15, "maximum 30 aggression / 15 UAZ allowance")) return; + for (int j = 0; j < Sites().Count(); j++) + { + ERR_SiteRuntime site = Sites().At(j); + if (site.Group && site.Group.GetFaction() == EnemyFaction() && ERR_ObjectiveDefence.Objective(site.Definition.Kind)) + if (!ERR_AggressionCheck(hq.ERR_ProbeDedicated(site.Group), "objective guard permanently excluded from HQ reassignment: " + site.Definition.Id)) return; + } + m_ERRAggressionStage = 1; + } + ERR_HunterVehicle hunter = hq.Hunters().ERR_ProbeFirst(); + if (!hunter || !hunter.Registered) return; + if (m_ERRAggressionStage == 1) + { + if (!ERR_AggressionCheck(hunter.CrewValid(this) && hunter.Members.Count() == 2, "physical UAZ with native seated driver and gunner")) return; + m_ERRHunterStart = hunter.Entity.GetOrigin(); m_ERRAggressionStage = 2; + } + if (m_ERRAggressionStage == 2) + { + foreach (IEntity soldier : hunter.Members) + { + SCR_AICombatComponent combat = SCR_AICombatComponent.Cast(soldier.FindComponent(SCR_AICombatComponent)); + if (!combat || combat.GetAISkill() != EAISkill.CYLON || !combat.ERR_EnhancedEnemy()) return; + } + if (hunter.Waypoint) m_ERRHunterOrder = true; + if (!m_ERRHunterOrder || vector.DistanceXZ(m_ERRHunterStart, hunter.Entity.GetOrigin()) < 30) return; + if (!hq.ERR_ProbeMedicalDefence()) return; + if (!ERR_AggressionCheck(true, "nearby medical stash gained complete dedicated squad and defend waypoint at terrain height")) return; + if (!ERR_AggressionCheck(true, "HQ radio delivered road order; UAZ drove over 30m; maximum scoped crew skill active")) return; + if (!ERR_AggressionCheck(hq.Hunters().Deployed() == 1, "bounded allowance does not spawn duplicate UAZs")) return; + hq.Hunters().Stop(); + if (!ERR_AggressionCheck(hunter.Released && !hunter.Waypoint && hunter.Entity && hunter.Members.Count() == 2, "stop removes orders and preserves physical vehicle/crew")) return; + foreach (IEntity survivor : hunter.Members) + { + SCR_AICombatComponent survivingCombat = SCR_AICombatComponent.Cast(survivor.FindComponent(SCR_AICombatComponent)); + if (!ERR_AggressionCheck(survivingCombat && survivingCombat.ERR_EnhancedEnemy(), "released driving task preserves surviving crew AI profile")) return; + } + GetGame().GetCallqueue().Remove(ERR_AggressionTick); + Print("ERR SMOKE COMPLETE: aggression, physical UAZ, native movement, dedicated objectives and scoped skill"); + } + } +} +#endif diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAirfieldMarkersProbe.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAirfieldMarkersProbe.c new file mode 100644 index 0000000..c419500 --- /dev/null +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAirfieldMarkersProbe.c @@ -0,0 +1,205 @@ +#ifdef WORKBENCH +modded class ERR_DiscoveryMarker +{ + string ERR_ProbeIcon() { return m_Icon; } +} +modded class ERR_LocationComponent +{ + bool ERR_ProbeLocationIcon() + { + ERR_UpdateMarker(); + if (Kind() == ERR_LocationKind.PRISON) return !m_ERRMarker; + if (!m_ERRMarker || m_ERRMarker.GetMarkerOwnerID() != -1) return false; + string expected = ERR_DiscoveryMarker.Icon(Kind(), Id()); + if (Knowledge() == 1) expected = "mark-question"; + int point[2]; m_ERRMarker.GetWorldPos(point); + return m_ERRMarker.ERR_ProbeIcon() == expected && point[0] == ERR_DiscoveryMapRules.Coordinate(Position()[0], Knowledge()) && point[1] == ERR_DiscoveryMapRules.Coordinate(Position()[2], Knowledge()); + } +} +modded class ERR_GameMode +{ + protected bool ERR_RadioRoof(IEntity tent, vector position, IEntity exclude = null) + { + TraceParam roof = new TraceParam(); + roof.Start = position; roof.End = position + "0 5 0"; + roof.Flags = TraceFlags.ENTS; roof.Exclude = exclude; + return GetWorld().TraceMove(roof, null) < 1 && roof.TraceEnt == tent; + } + protected bool ERR_TestRadioCamp() + { + ERR_SiteRuntime radio = Sites().Find("everon-radio-1"); + IEntity tent; + foreach (IEntity prop : radio.Props) + if (prop && prop.GetPrefabData().GetPrefabName().Contains("/TentUSSR_01_base.et")) tent = prop; + if (!ERR_AirfieldCheck(tent && ERR_RadioRoof(tent, radio.Location.Position() + "0 0.2 0", radio.Location.GetOwner()), "radio physically underneath tent roof")) return false; + ERR_SpawnPlacement placement = new ERR_SpawnPlacement(); + bool accessible; + for (int step = 0; step < 32; step++) + { + float angle = step * Math.PI / 16; + vector offset = Vector(Math.Cos(angle) * 1.4, 0, Math.Sin(angle) * 1.4); + vector position = ERR_Actors.Ground(radio.Location.Position() + ERR_CampTerrain.Rotate(offset, radio.Definition.Heading)); + if (!placement.Clear(position, null) || !ERR_RadioRoof(tent, position + "0 1.7 0")) continue; + TraceParam sight = new TraceParam(); + sight.Start = position + "0 1.3 0"; sight.End = radio.Location.Position() + "0 0.3 0"; + sight.Flags = TraceFlags.ENTS | TraceFlags.WORLD; + float fraction = GetWorld().TraceMove(sight, null); + if (fraction < 1 && sight.TraceEnt != radio.Location.GetOwner()) continue; + accessible = true; break; + } + if (!ERR_AirfieldCheck(accessible, "standing room inside tent within radio interaction distance and line of sight")) return false; + array guards = {}; radio.Group.GetAgents(guards); + if (!ERR_AirfieldCheck(guards.Count() == radio.InitialGuardCount && guards.Count() > 0, "radio always has its complete physical guard squad")) return false; + foreach (AIAgent guard : guards) + if (!ERR_AirfieldCheck(guard && ERR_Actors.CanFight(guard.GetControlledEntity()), "radio guard alive and conscious")) return false; + if (!ERR_AirfieldCheck(ERR_HQ.Get().ERR_ProbeRadioReservation(radio.Group), "HQ permanently refuses radio squad reassignment and courier reservation")) return false; + array waypoints = {}; radio.Group.GetWaypoints(waypoints); + bool defending; + foreach (AIWaypoint waypoint : waypoints) + if (SCR_DefendWaypoint.Cast(waypoint) && vector.DistanceXZ(waypoint.GetOrigin(), radio.Location.Position()) < 0.1 && waypoint.GetCompletionRadius() == 20) defending = true; + return ERR_AirfieldCheck(defending, "permanent native defend order centred on radio with 20m radius"); + } + + protected int m_ERRAirfieldStage; + protected bool m_ERRAirfieldOpeningChecked; + protected int m_ERRMortarFolders; + protected IEntity m_ERRMortarFolder; + protected ref ERR_AdminItemCallback m_ERRMortarPickup; + protected bool ERR_MortarIntelReady() + { + array batteries = {}; ERR_MortarSystem.Get().Batteries(batteries); + if (batteries.Count() != 4) { ERR_AirfieldCheck(false, "exactly four authored mortar batteries"); return false; } + foreach (ERR_MortarBattery battery : batteries) + { + if (!battery.SpawnFailure.IsEmpty()) { ERR_AirfieldCheck(false, "mortar preparation: " + battery.SpawnFailure); return false; } + if (!battery.StartupActivated) return false; + } + if (m_ERRMortarFolder) + { + if (!m_ERRMortarPickup.Finished) return false; + if (!m_ERRMortarPickup.Succeeded) { ERR_AirfieldCheck(false, "native intel inventory insertion"); return false; } + if (!Discovery().IsSpent(m_ERRMortarFolder)) return false; + m_ERRMortarFolder = null; + } + int known; + for (int i = 1; i <= 4; i++) + if (Sites().Find("everon-mortar-" + i).Location.Knowledge() == 2) known++; + if (known == 4) return true; + if (m_ERRMortarFolders >= 8) { ERR_AirfieldCheck(false, "all four mortar locations discoverable within eight folders"); return false; } + // Exclude already-known non-mortar destinations, then exercise actual normal + // untargeted folder recovery. No direct mortar Discover call is made here. + array locations = {}; Locations(locations); + foreach (ERR_LocationComponent location : locations) + if (location.Kind() != ERR_LocationKind.MORTAR) location.Discover(0, 100); + IEntity player = GetGame().GetPlayerController().GetControlledEntity(); + m_ERRMortarFolder = ERR_Actors.Spawn(ERR_Resources.IntelFolder(), player.GetOrigin()); Own(m_ERRMortarFolder); + m_ERRMortarPickup = new ERR_AdminItemCallback(); + SCR_InventoryStorageManagerComponent inventory = SCR_InventoryStorageManagerComponent.Cast(player.FindComponent(SCR_InventoryStorageManagerComponent)); + if (!m_ERRMortarFolder || !inventory.TryInsertItem(m_ERRMortarFolder, EStoragePurpose.PURPOSE_DEPOSIT, m_ERRMortarPickup)) + ERR_AirfieldCheck(false, "physical intel pickup accepted"); + m_ERRMortarFolders++; + return false; + } + + protected int m_ERRAirfieldDeadline; + protected float m_ERRAirfieldWait; + protected override void EOnInit(IEntity owner) + { + super.EOnInit(owner); + string outcome; + if (!Replication.IsServer() || SCR_Global.IsEditMode() || !System.GetCLIParam("errSmokeOutcome", outcome) || outcome != "airfield-markers") return; + m_ERRAirfieldDeadline = System.GetTickCount() + 200000; + GetGame().GetCallqueue().CallLater(ERR_AirfieldTick, 500, true); + } + protected bool ERR_AirfieldCheck(bool value, string text) + { + if (value) { Print("ERR SMOKE PASS: airfield " + text); return true; } + Print("ERR SMOKE FAIL: airfield " + text, LogLevel.ERROR); + GetGame().GetCallqueue().Remove(ERR_AirfieldTick); return false; + } + protected void ERR_AirfieldTick() + { + if (System.GetTickCount() >= m_ERRAirfieldDeadline || Phase() == ERR_Phase.DEFEAT) { ERR_AirfieldCheck(false, "preparation or deadline failure"); return; } + if ((Phase() != ERR_Phase.PRISON && Phase() != ERR_Phase.RADIO_SEARCH) || !GetGame().GetPlayerController() || !GetGame().GetPlayerController().GetControlledEntity()) return; + if (GetWorld().GetWorldTime() < m_ERRAirfieldWait) return; + if (m_ERRAirfieldStage == 0) + { + if (!m_ERRAirfieldOpeningChecked) + { + if (!ERR_TestRadioCamp()) return; + if (!ERR_AirfieldCheck(ERR_NativeScoutProbe.Run(), "ten hill scouts: complete finite loadouts, full ammo packs, physical radios and reserved observation posts")) return; + ERR_SiteRuntime prison = Sites().Find("everon-prison-1"); + array guards = {}; prison.Group.GetAgents(guards); + int radios; array guardPositions = {}; + foreach (AIAgent guard : guards) + { + IEntity actor = guard.GetControlledEntity(); + float distance = vector.DistanceXZ(actor.GetOrigin(), prison.Location.Position()); + if (!ERR_AirfieldCheck(distance >= 11.5 && distance <= 24.5 && !guard.IsAIActivated() && ERR_Actors.CanFight(actor), "guard alive, frozen and outside prison at random perimeter position")) return; + foreach (vector previous : guardPositions) + if (!ERR_AirfieldCheck(vector.DistanceXZ(previous, actor.GetOrigin()) > 3, "guards occupy separate perimeter positions")) return; + guardPositions.Insert(actor.GetOrigin()); + if (ERR_HQRadio.Capability(actor) == 2) radios++; + } + if (!ERR_AirfieldCheck(radios > 0, "perimeter patrol retains physical large radio")) return; + for (int mortarId = 1; mortarId <= 4; mortarId++) + { + ERR_LocationComponent hidden = Sites().Find("everon-mortar-" + mortarId).Location; + if (!ERR_AirfieldCheck(hidden.Knowledge() == 0, "mortar initially undiscovered")) return; + } + ERR_LocationComponent partial = Sites().Find("everon-mortar-1").Location; + partial.Discover(99, 0); + if (!ERR_AirfieldCheck(partial.Knowledge() == 1 && partial.ERR_ProbeLocationIcon(), "partial mortar intel displays question mark at coarse location")) return; + IEntity player = GetGame().GetPlayerController().GetControlledEntity(); + if (!ERR_AirfieldCheck(UnlockPrison(player), "normal prison unlock starts HQ and mortar activity")) return; + // Park only the fixture actor beside the unguarded medical stash so nearby + // prison combat does not interrupt the inventory/UI observation sequence. + ERR_SpawnPlacement placement = new ERR_SpawnPlacement(); bool parked; + for (int spot = 0; spot < 8; spot++) + { + vector position = ERR_Actors.Ground(Sites().Find("everon-medical-1").Location.Position() + Vector(5 + spot * 2, 0, 5)); + if (!placement.Clear(position, null, -1, player)) continue; + vector transform[4]; player.GetTransform(transform); transform[3] = position; + ChimeraCharacter.Cast(player).Teleport(transform); parked = true; break; + } + if (!ERR_AirfieldCheck(parked, "fixture actor parked on checked terrain for mortar intel observation")) return; + m_ERRAirfieldOpeningChecked = true; + } + if (!ERR_MortarIntelReady()) return; + if (!ERR_AirfieldCheck(!Sites().Find("everon-supply-2"), "guarded car-and-crate site absent")) return; + ERR_SiteRuntime extraction = Sites().Find("everon-extraction-1"); + if (!ERR_AirfieldCheck(extraction.Definition.RequireAirfield && vector.DistanceXZ(ExtractionVehicle().GetOrigin(), "4800.953 0 11487.412") < 3 && ERR_CasualtyLoadingRules.AircraftReady(ExtractionVehicle()), "production aircraft settled intact on validated Everon airfield pad")) return; + if (!ERR_AirfieldCheck(!ERR_AirfieldPlacement.Clear(ERR_Actors.Ground("7012 0 7500")), "old off-airfield helicopter position rejected")) return; + if (!ERR_AirfieldCheck(!ERR_AirfieldPlacement.Clear(ExtractionVehicle().GetOrigin()), "occupied airfield pad rejected")) return; + if (!ERR_AirfieldCheck(Sites().Find("everon-medical-1").Definition.RevealOnEscape && Sites().Find("everon-supply-1").Definition.RevealOnEscape, "two reachable intel sites retained")) return; + if (!ERR_AirfieldCheck(true, "four stocked operational mortar batteries discovered through physical intel")) return; + array locations = {}; Locations(locations); + foreach (ERR_LocationComponent location : locations) + { + location.Discover(0, 100); + if (!ERR_AirfieldCheck(location.Knowledge() == 2 && location.ERR_ProbeLocationIcon(), "identified " + location.Id() + " has correct map visibility and icon")) return; + } + GetGame().GetMenuManager().OpenMenu(ChimeraMenuPreset.MapMenu); + m_ERRAirfieldStage = 1; m_ERRAirfieldWait = GetWorld().GetWorldTime() + 3000; return; + } + SCR_MapEntity mapEntity = SCR_MapEntity.GetMapInstance(); + if (m_ERRAirfieldStage == 1) + { + if (!ERR_AirfieldCheck(mapEntity && mapEntity.IsOpen(), "native fullscreen map open")) return; + mapEntity.ZoomPanSmooth(0.08, 5800, 9000, 0.1); + m_ERRAirfieldStage = 2; m_ERRAirfieldWait = GetWorld().GetWorldTime() + 3000; return; + } + if (m_ERRAirfieldStage == 2) + { + System.MakeScreenshot("$logs:err-airfield-map-icons"); + Print("ERR AIRFIELD CAPTURE READY"); + m_ERRAirfieldStage = 3; m_ERRAirfieldWait = GetWorld().GetWorldTime() + 15000; return; + } + GetGame().GetMenuManager().CloseMenuByPreset(ChimeraMenuPreset.MapMenu); + GetGame().GetCallqueue().Remove(ERR_AirfieldTick); + // Runner tears down the test world. Avoid mixing native map close with a + // same-frame task-list teardown, which has a vanilla delayed-refresh race. + Print("ERR SMOKE COMPLETE: airfield, four mortar intel sites, hidden prison and random perimeter guards"); + } +} +#endif diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeBaseSmoke.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeBaseSmoke.c index ffb5beb..a242406 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeBaseSmoke.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeBaseSmoke.c @@ -54,7 +54,7 @@ modded class ERR_GameMode string enabled; if (SCR_Global.IsEditMode() || !Replication.IsServer() || !System.GetCLIParam("errBaseSmoke", enabled) || enabled != "1") return; string nativeEndCase; - if (System.GetCLIParam("errSmokeOutcome", nativeEndCase) && (nativeEndCase == "native-end-active" || nativeEndCase == "native-end-preparing")) return; + if (System.GetCLIParam("errSmokeOutcome", nativeEndCase) && (nativeEndCase == "aggression" || nativeEndCase == "native-end-active" || nativeEndCase == "native-end-preparing" || nativeEndCase == "generated-sites" || nativeEndCase == "mortar-station" || nativeEndCase == "opening-tools" || nativeEndCase == "airfield-markers" || nativeEndCase == "air-logistics" || nativeEndCase == "air-assault" || nativeEndCase == "air-recon")) return; ERR_NativeObjectiveProbe.BeginRound(); ERR_NativeProgressionIdentityProbe.BeginRound(); string outcome; @@ -565,6 +565,11 @@ modded class ERR_GameMode if (m_ERRExtractionCase == "prisoner-kit") { + int contentMenu = ERR_ProbeAdminMenu(now); + if (contentMenu < 0) { ERR_BaseCheck(false, "content admin menu"); return; } + if (contentMenu == 0) return; + if (!ERR_NativeAdminSettingsProbe.Run(this)) { ERR_BaseCheck(false, "random settings storage and commands"); return; } + if (!ERR_NativeContentProbe.Run(this)) { ERR_BaseCheck(false, "content registry and backpack"); return; } DamageManagerComponent.Cast(m_ERRBasePlayer.FindComponent(DamageManagerComponent)).EnableDamageHandling(false); m_ERRPrisonerProbe = new ERR_NativePrisonerProbe(this, m_ERRBasePlayer); m_ERRBaseStep = 700; diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeContentProbe.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeContentProbe.c new file mode 100644 index 0000000..0e1d87b --- /dev/null +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeContentProbe.c @@ -0,0 +1,71 @@ +#ifdef WORKBENCH +class ERR_NativeContentProbe +{ + protected static bool Check(bool condition, string detail) + { + if (condition) { Print("ERR SMOKE PASS: content " + detail); return true; } + Print("ERR SMOKE FAIL: content " + detail, LogLevel.ERROR); + return false; + } + static bool Run(ERR_GameMode mode) + { + if (!ERR_NativeFactionSelectionProbe.Run(mode)) return false; + ERR_ContentDefinition definition = ERR_ContentRegistry.Definition(); + if (!Check(definition && definition.Valid() && definition.Options.Count() == 4, "native pack and three faction definitions load")) return false; + ERR_SiteRuntime prison = mode.Sites().Find("everon-prison-1"); + if (!Check(prison && prison.Container && prison.Container.FindComponent(BaseLoadoutClothComponent), "prison supplies use a wearable ground backpack")) return false; + BaseInventoryStorageComponent storage = BaseInventoryStorageComponent.Cast(prison.Container.FindComponent(BaseInventoryStorageComponent)); + array items = {}; + if (storage) storage.GetAll(items); + array unique = {}; + int pistols, magazines, maps; + foreach (IEntity item : items) + { + if (!item || unique.Contains(item)) continue; + unique.Insert(item); + if (!Check(ERR_SpawnSceneInventory.InStorage(item), "bag item has native visible storage ownership")) return false; + ResourceName prefab = item.GetPrefabData().GetPrefabName(); + PrintFormat("ERR CONTENT BAG: item=%1 prefab=%2", item, prefab); + if (prefab.Contains("Handgun_PM.et")) pistols++; + else if (prefab.Contains("Magazine_9x18_PM_8rnd_Ball.et")) magazines++; + else maps++; + } + if (!Check(unique.Count() == 14 && pistols == 5 && magazines == 8 && maps == 1, "backpack physically contains five pistols, eight magazines and map before admission")) return false; + array siteIds = {"everon-supply-1", "everon-radio-1", "everon-supply-2"}; + array factions = {mode.PlayerFaction(), mode.EnemyFaction()}; + int poolIndex; + for (int i = 0; i < siteIds.Count(); i++) + { + ERR_SiteRuntime site = mode.Sites().Find(siteIds[i]); + ResourceName expected; + if (site && site.Definition.AllowFactionPool) expected = mode.Content().GuardGroup(poolIndex++); + if (expected.IsEmpty()) expected = mode.Factions().GuardGroupPrefab; + if (!Check(site && site.Group && site.Group.GetPrefabData().GetPrefabName() == expected && mode.IsMissionEnemy(site.Group.GetFaction()), "selected physical faction group at " + siteIds[i])) return false; + if (!factions.Contains(site.Group.GetFaction())) factions.Insert(site.Group.GetFaction()); + } + foreach (Faction a : factions) + foreach (Faction b : factions) + if (a != b && !Check(a.IsFactionEnemy(b) && b.IsFactionEnemy(a), "mutual hostility " + a.GetFactionKey() + " / " + b.GetFactionKey())) return false; + array replies = {}; + bool original = mode.ContentSettings().Enabled("rhs"); + mode.Admin().Execute(mode, false, "mods rhs disable", replies); + if (!Check(replies.Count() == 1 && replies[0] == "Administrator access required." && mode.ContentSettings().Enabled("rhs") == original, "unauthorized mod command rejected")) return false; + string path = "$profile:erri-content-probe.json"; + if (!Check(!FileIO.FileExists(path), "disposable preference path unused")) return false; + ERR_ContentSettings settings = new ERR_ContentSettings(path); + ERR_ContentPolicy active = new ERR_ContentPolicy(settings); + if (!Check(active.Enabled("rhs") && active.Enabled("rhs_usmc") && !active.Enabled("unknown"), "new options default on; unknown IDs denied")) return false; + if (!Check(settings.Set("rhs", 0) && active.Enabled("rhs_usmc"), "saving pack disable leaves active round unchanged")) return false; + ERR_ContentSettings reloaded = new ERR_ContentSettings(path); + ERR_ContentPolicy disabled = new ERR_ContentPolicy(reloaded); + if (!Check(!disabled.Enabled("rhs") && !disabled.Enabled("rhs_usmc") && !disabled.Enabled("rhs_afrf") && !disabled.Enabled("rhs_ion") && disabled.GuardGroup(0).IsEmpty(), "reload excludes disabled pack and every child faction")) return false; + if (!Check(!disabled.Allows("{A1D5833FF10C6503}Prefabs/Weapons/Attachments/Optics/Optic_PSO1/Optic_PSO1M2.et") && disabled.Allows("{C850A33226B8F9C1}Prefabs/Weapons/Attachments/Optics/Optic_PSO1/Optic_PSO1.et"), "disabled RHS optics keep vanilla alternatives")) return false; + if (!Check(reloaded.Set("rhs", 1) && reloaded.Set("rhs_usmc", 0), "pack and individual faction preferences save independently")) return false; + ERR_ContentPolicy selected = new ERR_ContentPolicy(reloaded); + if (!Check(selected.Enabled("rhs") && !selected.Enabled("rhs_usmc") && selected.Enabled("rhs_afrf") && selected.Enabled("rhs_ion"), "individual faction disable preserves sibling factions")) return false; + if (!Check(!reloaded.Set("unknown", 1) && !reloaded.Set("rhs", 2), "unknown IDs and malformed flags rejected")) return false; + FileIO.DeleteFile(path); FileIO.DeleteFile(path + ".bak"); FileIO.DeleteFile(path + ".tmp"); + return Check(!FileIO.FileExists(path) && mode.ContentSettings().Enabled("rhs") == original, "disposable preferences cleaned; live preferences unchanged"); + } +} +#endif diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeContractsProbe.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeContractsProbe.c index 14e03c1..9ff4deb 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeContractsProbe.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeContractsProbe.c @@ -13,7 +13,9 @@ class ERR_NativeContractsProbe if (!Check(mode.Factions() && mode.Factions().WorldReady() && mode.PreparationError().IsEmpty(), "catalog resolves hostile vanilla factions and successful preparation")) return false; if (!Check(SCR_FactionManager.SGetFaction(player) == mode.PlayerFaction() && player.GetPrefabData().GetPrefabName() == mode.Factions().PrisonerPrefab, "physical prisoner matches injected faction and resource")) return false; ERR_SiteRuntime site = mode.Sites().Find("everon-supply-1"); - if (!Check(site && site.Group && site.Group.GetFaction() == mode.EnemyFaction() && site.Group.GetPrefabData().GetPrefabName() == mode.Factions().GuardGroupPrefab, "physical guard squad comes from injected catalog")) return false; + ResourceName expectedGroup = mode.Content().GuardGroup(0); + if (expectedGroup.IsEmpty()) expectedGroup = mode.Factions().GuardGroupPrefab; + if (!Check(site && site.Group && mode.IsMissionEnemy(site.Group.GetFaction()) && site.Group.GetPrefabData().GetPrefabName() == expectedGroup, "physical guard squad comes from enabled catalog")) return false; ERR_FactionCatalog isolated = ERR_FactionCatalog.Cast(SCR_BaseContainerTools.CreateInstanceFromPrefab("{BE50B97B8E2B36E6}Configs/ERR/VanillaFactions.conf")); if (!isolated) return false; string enemyKey = isolated.EnemyFactionKey; diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeDefinitionProbe.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeDefinitionProbe.c index d795dd9..daea402 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeDefinitionProbe.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeDefinitionProbe.c @@ -9,7 +9,7 @@ class ERR_NativeDefinitionProbe } static bool Run() { - ERR_ScenarioDefinition definition = ERR_ScenarioDefinition.Cast(SCR_BaseContainerTools.CreateInstanceFromPrefab("{BC310DC0CD27F523}Configs/ERR/EveronSites.conf")); + ERR_ScenarioDefinition definition = ERR_ScenarioDefinition.Cast(SCR_BaseContainerTools.CreateInstanceFromPrefab("{ACA98B44E2173605}Configs/ERR/Tests/LegacySites.conf")); if (!Check(definition && definition.Valid(), "authored configuration resolves")) return false; ERR_SiteDefinition cache = definition.Find("everon-supply-1"); if (!cache) return false; diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFactionCatalogProbe.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFactionCatalogProbe.c index 0c9d96c..881e6f6 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFactionCatalogProbe.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFactionCatalogProbe.c @@ -53,7 +53,7 @@ class ERR_NativeFactionCatalogProbe if (!Check(manager != null, "native faction manager exists")) return false; SCR_Faction us = SCR_Faction.Cast(manager.GetFactionByKey("US")); SCR_Faction ussr = SCR_Faction.Cast(manager.GetFactionByKey("USSR")); - if (!Check(us && ussr && mode.PlayerFaction() == us && mode.EnemyFaction() == ussr, "mission retains US and USSR faction identities")) return false; + if (!Check(us && ussr && mode.PlayerFaction().GetFactionKey() == mode.FactionSelection().Choice("escapists").Key && mode.EnemyFaction().GetFactionKey() == mode.FactionSelection().Choice("enemy").Key, "mission uses selected faction identities")) return false; if (!Check(us.IsFactionEnemy(ussr) && ussr.IsFactionEnemy(us) && !us.IsFactionEnemy(us) && !ussr.IsFactionEnemy(ussr), "mutual enemy and same-faction relations preserved")) return false; if (!Check(us.GetFactionRadioEncryptionKey() == "chickenNuggets" && ussr.GetFactionRadioEncryptionKey() == "coldBorscht" && us.GetFactionRadioFrequency() == 48000 && ussr.GetFactionRadioFrequency() == 42000, "native radio encryption and frequencies preserved")) return false; if (!Check(us.GetCallsignInfo() && ussr.GetCallsignInfo(), "native faction callsign configurations resolve")) return false; diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFactionSelectionProbe.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFactionSelectionProbe.c new file mode 100644 index 0000000..03d6ce6 --- /dev/null +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeFactionSelectionProbe.c @@ -0,0 +1,53 @@ +#ifdef WORKBENCH +class ERR_NativeFactionSelectionProbe +{ + protected static bool Check(bool condition, string detail) + { + if (condition) { Print("ERR SMOKE PASS: factions " + detail); return true; } + Print("ERR SMOKE FAIL: factions " + detail, LogLevel.ERROR); return false; + } + static bool Run(ERR_GameMode mode) + { + ERR_FactionSelection live = mode.FactionSelection(); + if (!Check(live && live.Ready() && mode.PlayerFaction() != mode.EnemyFaction(), "server resolves distinct roles before preparation")) return false; + Faction independent = GetGame().GetFactionManager().GetFactionByKey(live.Choice("independent").Key); + if (!Check(independent && independent != mode.PlayerFaction() && independent != mode.EnemyFaction() && mode.IsMissionEnemy(independent) && !mode.IsMissionEnemy(mode.PlayerFaction()), "independent is hostile while player faction is excluded")) return false; + IEntity player = GetGame().GetPlayerController().GetControlledEntity(); + FactionAffiliationComponent affiliation = FactionAffiliationComponent.Cast(player.FindComponent(FactionAffiliationComponent)); + if (!Check(affiliation && affiliation.GetAffiliatedFaction() == mode.PlayerFaction(), "admitted prisoner uses selected player faction")) return false; + map saved = new map(); + map resolved = new map(); + saved.Set("escapists", "random"); saved.Set("enemy", "us"); saved.Set("independent", "fia"); + for (int i = 0; i < 30; i++) + { + array pool = {"us", "ussr", "fia"}; + if (!ERR_FactionChoices.Resolve(pool, saved, resolved) || resolved.Get("escapists") != "ussr" || resolved.Get("enemy") != "us" || resolved.Get("independent") != "fia") return Check(false, "Random stole a later explicit selection"); + } + if (!Check(true, "Random reserves later explicit roles first")) return false; + saved.Set("enemy", "random"); saved.Set("independent", "random"); + for (int j = 0; j < 60; j++) + { + array all = {"us", "ussr", "fia", "rhs_afrf", "rhs_usmc", "rhs_ion"}; + if (!ERR_FactionChoices.Resolve(all, saved, resolved) || !ERR_FactionChoices.Distinct(resolved)) return Check(false, "Random all duplicated a faction"); + } + if (!Check(true, "Random all chooses three different factions")) return false; + saved.Set("enemy", "rhs_afrf"); + array basePool = {"us", "ussr", "fia"}; + if (!Check(ERR_FactionChoices.Resolve(basePool, saved, resolved) && resolved.Get("enemy") != "rhs_afrf", "disabled choice falls back to eligible random faction")) return false; + array replies = {}; + string previous = live.Saved("escapists"); + mode.Admin().Execute(mode, false, "factions set random random random", replies); + if (!Check(replies.Count() == 1 && replies[0] == "Administrator access required." && live.Saved("escapists") == previous, "unauthorized role changes rejected")) return false; + string path = "$profile:erri-faction-probe.json"; + ERR_FactionSelection settings = new ERR_FactionSelection(path); + array valid = {"random", "ussr", "fia"}; + array duplicate = {"us", "us", "fia"}; + array unknown = {"unknown", "ussr", "fia"}; + if (!Check(settings.Save(valid, mode.ContentSettings()) && !settings.Save(duplicate, mode.ContentSettings()) && !settings.Save(unknown, mode.ContentSettings()), "atomic persistence rejects duplicate and unknown selections")) return false; + ERR_FactionSelection reloaded = new ERR_FactionSelection(path); + if (!Check(reloaded.Saved("escapists") == "random" && reloaded.Saved("enemy") == "ussr" && reloaded.Saved("independent") == "fia", "saved roles survive reload and rejected changes")) return false; + FileIO.DeleteFile(path); FileIO.DeleteFile(path + ".bak"); FileIO.DeleteFile(path + ".tmp"); + return true; + } +} +#endif diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeGeneratedSitesProbe.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeGeneratedSitesProbe.c new file mode 100644 index 0000000..821380d --- /dev/null +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeGeneratedSitesProbe.c @@ -0,0 +1,138 @@ +#ifdef WORKBENCH +modded class ERR_LocationComponent +{ + bool ERR_ProbeGeneratedMarker(bool expected) + { + ERR_UpdateMarker(); + if (!expected) return m_ERRMarker == null; + if (!m_ERRMarker) return false; + int point[2]; m_ERRMarker.GetWorldPos(point); + return point[0] == ERR_DiscoveryMapRules.Coordinate(Position()[0], Knowledge()) && point[1] == ERR_DiscoveryMapRules.Coordinate(Position()[2], Knowledge()); + } +} +modded class ERR_GameMode +{ + protected int m_ERRGeneratedStage; + protected float m_ERRGeneratedWait; + protected int m_ERRGeneratedDeadline; + protected IEntity m_ERRGeneratedPlayer, m_ERRGeneratedNear, m_ERRGeneratedFar, m_ERRGeneratedSeated; + protected Vehicle m_ERRGeneratedVehicle; + protected ERR_LocationComponent m_ERRGeneratedRadio; + protected ref array m_ERRGeneratedTeam = {}; + protected ref map m_ERRGeneratedReservations = new map(); + protected bool m_ERRGeneratedTeamChecked; + protected int ERR_GeneratedTeamSlots(IEntity player) + { + if (m_ERRGeneratedTeamChecked) return 1; + ERR_SpawnPlacement placement = new ERR_SpawnPlacement(); + if (m_ERRGeneratedTeam.IsEmpty() && !ERR_GeneratedCheck(!placement.Clear(player.GetOrigin(), null), "physical player blocks occupied slot without a reservation")) return -1; + if (m_ERRGeneratedTeam.IsEmpty() && !ERR_GeneratedCheck(!placement.Clear(ERR_Actors.Ground(PrisonPosition() + ERR_CampTerrain.Rotate("0 0 6", PrisonHeading())), null), "rotated physical wall blocks spawn volume")) return -1; + m_ERRGeneratedReservations.Set(0, player.GetOrigin()); + if (m_ERRGeneratedTeam.Count() < 11) + { + vector position; + if (!ERR_GeneratedCheck(placement.Prison(PrisonPosition(), m_ERRGeneratedReservations, position, PrisonHeading()), "rotated prison clear slot for member " + (m_ERRGeneratedTeam.Count() + 2))) return -1; + IEntity actor = ERR_Actors.Spawn(Factions().PrisonerPrefab, position); + if (!ERR_GeneratedCheck(actor != null, "additional physical prisoner created")) return -1; + Own(actor); m_ERRGeneratedTeam.Insert(actor); m_ERRGeneratedReservations.Set(m_ERRGeneratedTeam.Count(), position); + DamageManagerComponent.Cast(actor.FindComponent(DamageManagerComponent)).EnableDamageHandling(false); + return 0; + } + foreach (IEntity prisoner : m_ERRGeneratedTeam) ERR_Actors.DeleteSpawned(prisoner); + m_ERRGeneratedTeam.Clear(); m_ERRGeneratedReservations.Clear(); m_ERRGeneratedTeamChecked = true; + return 1; + } + protected override void EOnInit(IEntity owner) + { + super.EOnInit(owner); + string outcome; + if (!Replication.IsServer() || SCR_Global.IsEditMode() || !System.GetCLIParam("errSmokeOutcome", outcome) || outcome != "generated-sites") return; + m_ERRGeneratedDeadline = System.GetTickCount() + 120000; + GetGame().GetCallqueue().CallLater(ERR_GeneratedProbeTick, 500, true); + } + protected bool ERR_GeneratedCheck(bool value, string detail) + { + if (value) { Print("ERR SMOKE PASS: generated " + detail); return true; } + Print("ERR SMOKE FAIL: generated " + detail, LogLevel.ERROR); + GetGame().GetCallqueue().Remove(ERR_GeneratedProbeTick); return false; + } + protected void ERR_GeneratedProbeTick() + { + if (System.GetTickCount() > m_ERRGeneratedDeadline || !PreparationError().IsEmpty()) { ERR_GeneratedCheck(false, "deadline or preparation failure: " + PreparationError()); return; } + if (!Active() || GetGame().GetWorld().GetWorldTime() < m_ERRGeneratedWait) return; + SCR_PlayerController controller = SCR_PlayerController.Cast(GetGame().GetPlayerController()); + if (!controller || !controller.GetControlledEntity()) return; + if (m_ERRGeneratedStage == 0) + { + m_ERRGeneratedPlayer = controller.GetControlledEntity(); + if (ERR_GeneratedTeamSlots(m_ERRGeneratedPlayer) != 1) return; + ERR_SiteRuntime prison = Sites().Find("everon-prison-1"); ERR_SiteRuntime radio = Sites().Find("everon-radio-1"); + if (!ERR_GeneratedCheck(prison && radio && prison.Definition.PlacementResolved && radio.Definition.PlacementResolved, "both generated locations committed before admission")) return; + if (!ERR_GeneratedCheck(vector.DistanceXZ(prison.Definition.Position, radio.Definition.Position) >= 1000 && vector.DistanceXZ(prison.Definition.Position, "6090 0 7160") > 1, "fresh island prison and separated radio")) return; + vector local = ERR_CampTerrain.Local(m_ERRGeneratedPlayer.GetOrigin() - PrisonPosition(), PrisonHeading()); + if (!ERR_GeneratedCheck(Math.AbsFloat(local[0]) <= 5.5 && Math.AbsFloat(local[2]) <= 5.5 && PrisonEscape().Registered(), "player inside rotated prison with intact registered gate")) return; + BaseInventoryStorageComponent bag = BaseInventoryStorageComponent.Cast(prison.Container.FindComponent(BaseInventoryStorageComponent)); + array contents = {}; if (bag) bag.GetAll(contents); + if (!ERR_GeneratedCheck(contents.Count() == 14 && radio.Group.GetFaction() == EnemyFaction(), "starter backpack ready and camp guards use enemy faction")) return; + m_ERRGeneratedRadio = radio.Location; + if (!ERR_GeneratedCheck(radio.Props.Count() == 5, "radio composition has five independently owned scenery objects")) return; + if (!ERR_GeneratedCheck(m_ERRGeneratedRadio.ERR_ProbeGeneratedMarker(false), "undiscovered radio location hidden")) return; + m_ERRGeneratedRadio.Discover(99, 0); + if (!ERR_GeneratedCheck(m_ERRGeneratedRadio.Knowledge() == 1 && m_ERRGeneratedRadio.ERR_ProbeGeneratedMarker(true), "partial intel creates approximate question marker")) return; + m_ERRGeneratedRadio.Discover(99, 0); + if (!ERR_GeneratedCheck(m_ERRGeneratedRadio.Knowledge() == 2 && m_ERRGeneratedRadio.ERR_ProbeGeneratedMarker(true), "further intel reveals actual generated coordinates")) return; + m_ERRGeneratedNear = ERR_Actors.Spawn(Factions().PrisonerPrefab, ERR_Actors.Ground(PrisonPosition() + "0 0 15")); Own(m_ERRGeneratedNear); + vector far; + for (int radius = 1200; radius <= 6000 && far == vector.Zero; radius += 300) + for (int i = 0; i < 36; i++) + { + vector candidate = ERR_Actors.Ground(PrisonPosition() + ERR_CampTerrain.Rotate(Vector(radius, 0, 0), i * 10)); + if (candidate[1] > 1 && !ChimeraWorldUtils.TryGetWaterSurfaceSimple(GetWorld(), candidate)) { far = candidate; break; } + } + if (!ERR_GeneratedCheck(far != vector.Zero, "dry outside-radius test location available")) return; + m_ERRGeneratedFar = ERR_Actors.Spawn(Factions().PrisonerPrefab, far); Own(m_ERRGeneratedFar); + m_ERRGeneratedVehicle = Vehicle.Cast(ERR_Actors.Spawn("{259EE7B78C51B624}Prefabs/Vehicles/Wheeled/UAZ469/UAZ469.et", ERR_Actors.Ground(PrisonPosition() + "0 0 20"))); Own(m_ERRGeneratedVehicle); + BaseCompartmentManagerComponent seats = BaseCompartmentManagerComponent.Cast(m_ERRGeneratedVehicle.FindComponent(BaseCompartmentManagerComponent)); + array slots = {}; seats.GetCompartments(slots); + foreach (BaseCompartmentSlot slot : slots) + { + if (slot.GetType() != ECompartmentType.CARGO) continue; + AIGroup group; + m_ERRGeneratedSeated = slot.SpawnCharacterInCompartment(Factions().PrisonerPrefab, group, "{7A968AB297475FA7}Prefabs/ERR/ConvoyCrew.et"); + Own(group); Own(m_ERRGeneratedSeated); break; + } + if (!ERR_GeneratedCheck(m_ERRGeneratedNear && m_ERRGeneratedFar && m_ERRGeneratedVehicle && m_ERRGeneratedSeated, "friendly foot AI, distant AI and seated AI fixtures created")) return; + m_ERRGeneratedWait = GetWorld().GetWorldTime() + 2000; m_ERRGeneratedStage = 1; return; + } + if (m_ERRGeneratedStage == 1) + { + if (!ERR_GeneratedCheck(ERR_Actors.Alive(m_ERRGeneratedNear) && ERR_Actors.Alive(m_ERRGeneratedFar) && ERR_Actors.Alive(m_ERRGeneratedSeated) && CompartmentAccessComponent.GetVehicleIn(m_ERRGeneratedSeated) == m_ERRGeneratedVehicle, "targets alive and passenger physically seated")) return; + array denied = {}; Admin().Execute(this, false, "killais", denied); + if (!ERR_GeneratedCheck(denied.Count() == 1 && denied[0] == "Administrator access required." && ERR_Actors.Alive(m_ERRGeneratedNear), "unauthorized kill request refused")) return; + controller.ERR_AdminSubmit("killais"); + m_ERRGeneratedWait = GetWorld().GetWorldTime() + 2000; m_ERRGeneratedStage = 2; return; + } + if (m_ERRGeneratedStage == 2) + { + if (!ERR_GeneratedCheck(!ERR_Actors.Alive(m_ERRGeneratedNear) && !ERR_Actors.Alive(m_ERRGeneratedSeated) && ERR_Actors.Alive(m_ERRGeneratedFar) && ERR_Actors.Alive(m_ERRGeneratedVehicle) && ERR_Actors.Alive(m_ERRGeneratedPlayer), "authenticated killais kills nearby foot and seated AI, preserves player, vehicle and distant AI")) return; + if (!ERR_GeneratedCheck(UnlockPrison(m_ERRGeneratedPlayer), "generated prison unlock enters normal progression")) return; + vector approach = ERR_Actors.Ground(m_ERRGeneratedRadio.Position() + ERR_CampTerrain.Rotate("0 0 -1.5", Sites().Find("everon-radio-1").Definition.Heading)); + m_ERRGeneratedPlayer.SetOrigin(approach); + m_ERRGeneratedWait = GetWorld().GetWorldTime() + 1000; m_ERRGeneratedStage = 3; return; + } + if (m_ERRGeneratedStage == 3) + { + if (!ERR_GeneratedCheck(TuneRadio(m_ERRGeneratedPlayer, m_ERRGeneratedRadio) && Phase() == ERR_Phase.RADIO_DEFENCE, "generated radio starts existing transmission objective")) return; + CharacterControllerComponent.Cast(m_ERRGeneratedPlayer.FindComponent(CharacterControllerComponent)).SetHeadingAngle(Sites().Find("everon-radio-1").Definition.Heading * Math.DEG2RAD, true); + Print("ERR GENERATED CAPTURE READY"); + m_ERRGeneratedWait = GetWorld().GetWorldTime() + 3000; m_ERRGeneratedStage = 4; return; + } + if (m_ERRGeneratedStage == 4) + { + GetGame().GetCallqueue().Remove(ERR_GeneratedProbeTick); + Transition(ERR_Phase.DEFEAT); + Print("ERR SMOKE COMPLETE: generated sites, actual intel markers, admin killais and radio progression; scripted local fixture"); + } + } +} +#endif diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeOpeningToolsProbe.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeOpeningToolsProbe.c new file mode 100644 index 0000000..162e03c --- /dev/null +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeOpeningToolsProbe.c @@ -0,0 +1,109 @@ +#ifdef WORKBENCH +modded class ERR_GameMode +{ + protected int m_ERROpeningStage; + protected int m_ERROpeningDeadline; + protected ref array m_ERROpeningDocuments = {}; + protected SCR_AIGroup m_ERROpeningFallbackGroup; + protected ref ERR_PrisonPatrol m_ERROpeningFallback; + protected ref ERR_AdminItemCallback m_ERROpeningPickup; + protected IEntity m_ERROpeningPicked; + protected override void EOnInit(IEntity owner) + { + super.EOnInit(owner); + string outcome; + if (!Replication.IsServer() || SCR_Global.IsEditMode() || !System.GetCLIParam("errSmokeOutcome", outcome) || outcome != "opening-tools") return; + m_ERROpeningDeadline = System.GetTickCount() + 150000; + GetGame().GetCallqueue().CallLater(ERR_OpeningTick, 500, true); + } + protected bool ERR_OpeningCheck(bool value, string text) + { + if (value) { Print("ERR SMOKE PASS: opening " + text); return true; } + Print("ERR SMOKE FAIL: opening " + text, LogLevel.ERROR); + GetGame().GetCallqueue().Remove(ERR_OpeningTick); return false; + } + protected bool ERR_OpeningDocument(IEntity entity) + { + if (entity && entity.GetPrefabData() && entity.GetPrefabData().GetPrefabName() == ERR_Resources.IntelFolder()) m_ERROpeningDocuments.Insert(entity); + return true; + } + protected bool ERR_OpeningAircraftAudit(IEntity entity) + { + if (!entity || !entity.GetPrefabData()) return true; + string prefab = entity.GetPrefabData().GetPrefabName(); string name = prefab; name.ToLower(); + if (name.Contains("helicopter") || name.Contains("mi8") || name.Contains("uh1")) + PrintFormat("ERR OPENING AIRFRAME: prefab=%1 position=%2 extraction=%3", prefab, entity.GetOrigin(), entity == ExtractionVehicle()); + return true; + } + protected void ERR_OpeningTick() + { + if (System.GetTickCount() >= m_ERROpeningDeadline || Phase() == ERR_Phase.DEFEAT) { ERR_OpeningCheck(false, "fixture exceeded deadline or mission failed"); return; } + SCR_PlayerController controller = SCR_PlayerController.Cast(GetGame().GetPlayerController()); + IEntity player; if (controller) player = controller.GetControlledEntity(); + if (Phase() != ERR_Phase.PRISON || !player || !Players().CurrentActor(player)) return; + if (m_ERROpeningStage == 0) + { + array roster = {"rifleman", "squadleader", "Character_RTO.et", "Character_RTO_second.et"}; + for (int size = 3; size <= 5; size++) + { + array selected = ERR_PrisonPatrol.Members(roster, size); + int operators; foreach (ResourceName prefab : selected) if (prefab.Contains("RTO")) operators++; + if (!ERR_OpeningCheck(selected.Count() == size && operators == 1, "roster selection retains exactly one RTO at size " + size)) return; + } + vector low, high; GetGame().GetWorldEntity().GetWorldBounds(low, high); + GetWorld().QueryEntitiesByAABB(low, high, ERR_OpeningAircraftAudit, null, EQueryEntitiesFlags.ALL); + ERR_SiteRuntime prison = Sites().Find("everon-prison-1"); + array guards = {}; prison.Group.GetAgents(guards); + if (!ERR_OpeningCheck(guards.Count() >= 3 && guards.Count() <= 5 && guards.Count() == prison.InitialGuardCount, "3-5 physical prison guards")) return; + int radios; + foreach (AIAgent guard : guards) + { + if (!ERR_OpeningCheck(!guard.IsAIActivated() && ERR_Actors.CanFight(guard.GetControlledEntity()), "guard held alive until lockpick")) return; + if (ERR_HQRadio.Capability(guard.GetControlledEntity()) == 2) radios++; + } + if (!ERR_OpeningCheck(radios >= 1, "large manpack radio physically equipped")) return; + if (!ERR_OpeningCheck(ERR_CasualtyLoadingRules.AircraftReady(ExtractionVehicle()), "initial extraction helicopter intact and grounded")) return; + // Test the fallback on a faction roster containing no RTO. + m_ERROpeningFallbackGroup = SCR_AIGroup.Cast(ERR_Actors.Spawn("{EC9F1AA42D0B7863}Prefabs/ERR/PrisonPatrol.et", ERR_Actors.Ground(prison.Group.GetOrigin() + "10 0 10"))); + Own(m_ERROpeningFallbackGroup); + m_ERROpeningFallbackGroup.SetFaction(EnemyFaction()); + m_ERROpeningFallbackGroup.m_aUnitPrefabSlots = {"{5436629450D8387A}Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_SL.et"}; + m_ERROpeningFallbackGroup.RequestSpawn(1); + m_ERROpeningFallback = new ERR_PrisonPatrol(); + array denied = {}; Admin().Execute(this, false, "cheat intel", denied); + if (!ERR_OpeningCheck(denied.Count() == 1 && denied[0] == "Administrator access required.", "unauthorized intel command denied")) return; + controller.ERR_AdminSubmit("cheat intel"); + m_ERROpeningStage = 1; return; + } + if (m_ERROpeningStage == 1) + { + m_ERROpeningDocuments.Clear(); + GetWorld().QueryEntitiesBySphere(player.GetOrigin(), 6, ERR_OpeningDocument, null, EQueryEntitiesFlags.ALL); + if (m_ERROpeningDocuments.IsEmpty()) return; + if (!ERR_OpeningCheck(m_ERROpeningDocuments.Count() == 6, "authenticated command spawned exactly six physical intel documents")) return; + foreach (IEntity document : m_ERROpeningDocuments) + { + InventoryItemComponent item = InventoryItemComponent.Cast(document.FindComponent(InventoryItemComponent)); + if (!ERR_OpeningCheck(item && !item.GetParentSlot() && Math.AbsFloat(document.GetOrigin()[1] - ERR_Actors.Ground(document.GetOrigin())[1]) < 0.4 && !Discovery().IsSpent(document), "fresh document lies on nearby ground outside inventory")) return; + } + m_ERROpeningPicked = m_ERROpeningDocuments[0]; + SCR_InventoryStorageManagerComponent inventory = SCR_InventoryStorageManagerComponent.Cast(player.FindComponent(SCR_InventoryStorageManagerComponent)); + m_ERROpeningPickup = new ERR_AdminItemCallback(); + if (!ERR_OpeningCheck(inventory.TryInsertItem(m_ERROpeningPicked, EStoragePurpose.PURPOSE_DEPOSIT, m_ERROpeningPickup), "ground document pickup accepted")) return; + m_ERROpeningStage = 2; return; + } + if (m_ERROpeningStage == 2) + { + ERR_PrepareResult radio = m_ERROpeningFallback.Radio(this, m_ERROpeningFallbackGroup, GetWorld().GetWorldTime() + 10000); + if (radio == ERR_PrepareResult.FAILED) { ERR_OpeningCheck(false, "fallback radio insertion failed"); return; } + if (radio != ERR_PrepareResult.READY || !m_ERROpeningPickup.Finished || !Discovery().IsSpent(m_ERROpeningPicked)) return; + if (!ERR_OpeningCheck(m_ERROpeningPickup.Succeeded, "picked-up cheat document consumed by normal discovery")) return; + if (!ERR_OpeningCheck(ERR_HQRadio.Capability(m_ERROpeningFallbackGroup.GetLeaderEntity()) == 2, "non-RTO loadout receives actual large radio")) return; + if (!ERR_OpeningCheck(UnlockPrison(player), "normal lockpick progression remains available")) return; + GetGame().GetCallqueue().Remove(ERR_OpeningTick); + Transition(ERR_Phase.DEFEAT); + Print("ERR SMOKE COMPLETE: prison patrol, large radio, ground intel admin command and discovery"); + } + } +} +#endif diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_NativePatrolProbe.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativePatrolProbe.c index ec795e5..d0b5029 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_NativePatrolProbe.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativePatrolProbe.c @@ -38,7 +38,7 @@ class ERR_NativePatrolProbe } protected bool DefinitionChecks() { - ERR_ScenarioDefinition definition = ERR_ScenarioDefinition.Cast(SCR_BaseContainerTools.CreateInstanceFromPrefab("{BC310DC0CD27F523}Configs/ERR/EveronSites.conf")); + ERR_ScenarioDefinition definition = ERR_ScenarioDefinition.Cast(SCR_BaseContainerTools.CreateInstanceFromPrefab("{ACA98B44E2173605}Configs/ERR/Tests/LegacySites.conf")); if (!Check(definition && definition.Valid(), "authored definition resolves")) return false; ERR_SiteDefinition site = definition.Find("everon-outpost-1"); if (!Check(site && site.Patrol && site.Patrol.Count() == 4, "four ordered outpost points authored")) return false; diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeRadioCampProbe.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeRadioCampProbe.c new file mode 100644 index 0000000..95b497d --- /dev/null +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeRadioCampProbe.c @@ -0,0 +1,17 @@ +#ifdef WORKBENCH +modded class ERR_HQ +{ + bool ERR_ProbeRadioReservation(SCR_AIGroup group) + { + foreach (ERR_HQUnit unit : m_Units) + { + if (unit.Group != group) continue; + if (!unit.ReservedForSupport || !unit.HomeGuard || unit.Eligible(m_Mode)) return false; + if (ReserveLogistics(group, 999)) return false; + ReleaseMortarCrew(group); // Only actual destroyed mortar crews may be released. + return unit.ReservedForSupport && !unit.Eligible(m_Mode) && !unit.Waypoint && !unit.PendingOrder && !unit.Assignment; + } + return false; + } +} +#endif diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeTransportProbe.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeTransportProbe.c index 1c413f0..5974a38 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeTransportProbe.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeTransportProbe.c @@ -27,7 +27,7 @@ class ERR_NativeTransportProbe } protected bool DefinitionChecks() { - ERR_ScenarioDefinition definition = ERR_ScenarioDefinition.Cast(SCR_BaseContainerTools.CreateInstanceFromPrefab("{BC310DC0CD27F523}Configs/ERR/EveronSites.conf")); + ERR_ScenarioDefinition definition = ERR_ScenarioDefinition.Cast(SCR_BaseContainerTools.CreateInstanceFromPrefab("{ACA98B44E2173605}Configs/ERR/Tests/LegacySites.conf")); ERR_SiteDefinition site; if (definition) site = definition.Find("everon-supply-2"); if (!Check(site && site.Transport && definition.Valid(), "authored transport definition resolves")) return false; @@ -189,7 +189,7 @@ class ERR_NativeTransportProbe if (m_Step == 5) { if (!Check(!m_Site.Transport && m_Mode.Sites().TransportCount() == 0 && m_Mode.Sites().Prepare() == ERR_PrepareResult.READY, "lost transport remains absent after service ticks and preparation queries")) return -1; - ERR_ScenarioDefinition definition = ERR_ScenarioDefinition.Cast(SCR_BaseContainerTools.CreateInstanceFromPrefab("{BC310DC0CD27F523}Configs/ERR/EveronSites.conf")); + ERR_ScenarioDefinition definition = ERR_ScenarioDefinition.Cast(SCR_BaseContainerTools.CreateInstanceFromPrefab("{ACA98B44E2173605}Configs/ERR/Tests/LegacySites.conf")); if (!Check(!m_Mode.Sites().Begin(definition, ERR_Supplies.Map()) && m_Mode.Sites().TransportCount() == 0, "duplicate initialization cannot replace lost transport")) return -1; m_Mode.Sites().Stop(); if (!Check(m_Mode.Sites().Prepare() == ERR_PrepareResult.FAILED && !m_Mode.Sites().Begin(definition, ERR_Supplies.Map()), "stopped finite owner cannot reinitialize transport")) return -1; diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeTransportSurvey.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeTransportSurvey.c index 475a2b1..844a95e 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeTransportSurvey.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeTransportSurvey.c @@ -15,7 +15,7 @@ class ERR_NativeTransportSurvey { static void Run(ERR_GameMode mode) { - ERR_ScenarioDefinition definition = ERR_ScenarioDefinition.Cast(SCR_BaseContainerTools.CreateInstanceFromPrefab("{BC310DC0CD27F523}Configs/ERR/EveronSites.conf")); + ERR_ScenarioDefinition definition = ERR_ScenarioDefinition.Cast(SCR_BaseContainerTools.CreateInstanceFromPrefab("{ACA98B44E2173605}Configs/ERR/Tests/LegacySites.conf")); ERR_SiteDefinition site = definition.Find("everon-supply-2"); int clear; for (int x = -40; x <= 40; x += 8) diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_ObjectiveText.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_ObjectiveText.c index 8dad2bc..a02bbc8 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_ObjectiveText.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_ObjectiveText.c @@ -54,8 +54,8 @@ class ERR_ObjectiveText } // Scan all sites before acknowledging rough intel: an identified radio wins. if (roughRadio) - return "Intel recovered: a 500 m search square is now marked on the map. Use a carried field map to view it. Take a different intelligence folder into your inventory to pinpoint the radio; a folder already recovered cannot provide another clue. Try the other marked supply cache if needed. A close approach with a clear view can also identify the station."; - return "Choose either marked supply cache. Take its intelligence folders into your own inventory to reveal the station on your map. If only a search area appears, take another folder. Each cache has enough folders; use the other if one is lost. If every folder is lost, a close approach with a clear view can identify the station itself. Nearby medical and guard sites can also be discovered by approaching with a clear view."; + return "Intel recovered: a question mark shows an approximate location, but its type is still unknown. Take a different intelligence folder into your inventory to pinpoint the radio; a folder already recovered cannot provide another clue. Try the other marked supply cache if needed. A close approach with a clear view can also identify the station."; + return "Choose either marked supply cache. Take its intelligence folders into your own inventory to reveal the station on your map. If the location is not yet identified, take another folder. Each cache has enough folders; use the other if one is lost. If every folder is lost, a close approach with a clear view can identify the station itself. Nearby medical and guard sites can also be discovered by approaching with a clear view."; } if (phase == ERR_Phase.RADIO_DEFENCE) { diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonAI.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonAI.c index 05d0322..80d3309 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonAI.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonAI.c @@ -11,7 +11,7 @@ modded class SCR_ChimeraAIAgent ERR_GameMode mode = ERR_GameMode.Get(); IEntity actor = GetControlledEntity(); if (!mode || mode.Phase() > ERR_Phase.PRISON || !actor || ERR_Actors.Player(actor) || IsPlayerPending_S()) return; - if (!mode.EnemyFaction() || SCR_FactionManager.SGetFaction(actor) != mode.EnemyFaction()) return; + if (!mode.IsMissionEnemy(SCR_FactionManager.SGetFaction(actor))) return; DeactivateAI(); if (m_ERRPrisonMode) return; m_ERRPrisonMode = mode; diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonEscapeService.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonEscapeService.c index d108e35..dcf65a6 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonEscapeService.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonEscapeService.c @@ -161,7 +161,7 @@ class ERR_PrisonEscapeService vector position = actor.GetOrigin(); float ground = GetGame().GetWorld().GetSurfaceY(position[0], position[2]); if (!ERR_PrisonEscapeRules.Grounded(position[1] - ground)) continue; - vector offset = position - m_Center; + vector offset = ERR_CampTerrain.Local(position - m_Center, m_Mode.PrisonHeading()); ERR_PrisonEscapeSample sample = m_Samples.Get(life.AccountId); bool armed; if (sample && sample.Actor == actor && sample.Controller == controller) @@ -169,7 +169,7 @@ class ERR_PrisonEscapeService float elapsed = now - sample.ObservedAt; float displacement = vector.Distance(position, sample.Position); bool continuous = ERR_PrisonEscapeRules.Continuous(elapsed, displacement); - vector previousOffset = sample.Position - m_Center; + vector previousOffset = ERR_CampTerrain.Local(sample.Position - m_Center, m_Mode.PrisonHeading()); if (ERR_PrisonEscapeRules.Crossing(sample.Armed, previousOffset[0], previousOffset[2], offset[0], offset[2], elapsed, displacement)) { // An actual qualifying exit is sufficient even if the gate remains intact. diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonPatrol.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonPatrol.c new file mode 100644 index 0000000..ddda0c2 --- /dev/null +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_PrisonPatrol.c @@ -0,0 +1,106 @@ +// One finite opening patrol. Build the selected faction's roster before asking +// the native spawn queue for any members; never spawn a full squad and trim it. +class ERR_PrisonPatrol +{ + protected IEntity m_Radio; + protected bool m_RequestedRadio; + + protected bool m_Placed; + bool Place(SCR_AIGroup group, vector center) + { + if (m_Placed) return true; + if (!Replication.IsServer() || !group) return false; + array agents = {}; group.GetAgents(agents); + if (agents.Count() < 3 || agents.Count() > 5) return false; + map positions = new map(); + ERR_SpawnPlacement placement = new ERR_SpawnPlacement(); + float start = Math.RandomFloat(0, 360); + float sector = 360.0 / agents.Count(); + for (int index = 0; index < agents.Count(); index++) + { + if (!agents[index] || !ChimeraCharacter.Cast(agents[index].GetControlledEntity())) return false; + bool found; + for (int attempt = 0; attempt < 80; attempt++) + { + float angle = (start + sector * index + Math.RandomFloat(-sector * 0.3, sector * 0.3)) * Math.DEG2RAD; + float radius = Math.RandomFloat(12, 24); + vector position = ERR_Actors.Ground(center + Vector(Math.Cos(angle) * radius, 0, Math.Sin(angle) * radius)); + if (ChimeraWorldUtils.TryGetWaterSurfaceSimple(GetGame().GetWorld(), position)) continue; + if (!placement.Clear(position, positions, index, agents[index].GetControlledEntity())) continue; + positions.Insert(index, position); found = true; break; + } + if (!found) return false; + } + for (int member = 0; member < agents.Count(); member++) + { + ChimeraCharacter actor = ChimeraCharacter.Cast(agents[member].GetControlledEntity()); + vector transform[4]; + Math3D.AnglesToMatrix(Vector(Math.RandomFloat(0, 360), 0, 0), transform); + transform[3] = positions.Get(member); + actor.Teleport(transform); + } + m_Placed = true; + return true; + } + + static array Members(array source, int count) + { + array result = {}; + if (!source || source.IsEmpty() || count < 3 || count > 5) return result; + array soldiers = {}; + ResourceName radioman; + foreach (ResourceName prefab : source) + { + string name = prefab; name.ToLower(); + if (name.Contains("_rto") || name.Contains("radioman")) + { if (radioman.IsEmpty()) radioman = prefab; } + else if (!prefab.IsEmpty()) soldiers.Insert(prefab); + } + if (!radioman.IsEmpty()) result.Insert(radioman); + if (soldiers.IsEmpty()) soldiers.Insert(source[0]); + int index; + while (result.Count() < count) { result.Insert(soldiers[index % soldiers.Count()]); index++; } + return result; + } + + static bool Configure(SCR_AIGroup group, ResourceName profile, Faction faction) + { + if (!Replication.IsServer() || !group || !faction || group.GetAgentsCount() != 0) return false; + Resource resource = Resource.Load(profile); + if (!resource || !resource.IsValid()) return false; + IEntitySource source = resource.GetResource().ToEntitySource(); + array roster = {}; + if (!source || !source.Get("m_aUnitPrefabSlots", roster)) return false; + group.m_aUnitPrefabSlots = Members(roster, Math.RandomIntInclusive(3, 5)); + if (group.m_aUnitPrefabSlots.IsEmpty()) return false; + group.SetFaction(faction); + group.SetSpawnImmediately(true); + group.RequestSpawn(group.m_aUnitPrefabSlots.Count()); + return true; + } + + // Existing faction RTO loadouts are preferred. If a mod's fireteam has none, + // equip one soldier with a real large radio, replacing its backpack if needed. + ERR_PrepareResult Radio(ERR_GameMode mode, SCR_AIGroup group, float deadline) + { + array agents = {}; group.GetAgents(agents); + foreach (AIAgent member : agents) + if (member && ERR_HQRadio.Capability(member.GetControlledEntity()) == 2) return ERR_PrepareResult.READY; + if (GetGame().GetWorld().GetWorldTime() >= deadline) return ERR_PrepareResult.FAILED; + if (m_RequestedRadio) return ERR_PrepareResult.PENDING; + if (agents.IsEmpty() || !agents[0]) return ERR_PrepareResult.PENDING; + IEntity actor = agents[0].GetControlledEntity(); + if (!actor) return ERR_PrepareResult.PENDING; + SCR_InventoryStorageManagerComponent inventory = SCR_InventoryStorageManagerComponent.Cast(actor.FindComponent(SCR_InventoryStorageManagerComponent)); + if (!inventory) return ERR_PrepareResult.PENDING; + m_RequestedRadio = true; + ResourceName radio = "{54C68E438DD34265}Prefabs/Items/Equipment/Radios/Radio_R107M.et"; + if (group.GetFaction().GetFactionKey() == "US" || group.GetFaction().GetFactionKey() == "RHS_USAF") + radio = "{9B6B61BB3FE3DFB0}Prefabs/Items/Equipment/Radios/Radio_ANPRC77.et"; + m_Radio = ERR_Actors.Spawn(radio, actor.GetOrigin()); + if (!m_Radio) return ERR_PrepareResult.FAILED; + mode.Own(m_Radio); + inventory.EquipCloth(m_Radio); + return ERR_PrepareResult.PENDING; + } +} diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_RadioDefenceService.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_RadioDefenceService.c index 19fa6f0..a63fba0 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_RadioDefenceService.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_RadioDefenceService.c @@ -56,7 +56,7 @@ class ERR_RadioDefenceService int DurationSeconds() { if (!m_Mode || !m_Mode.Settings()) return 0; - return m_Mode.Settings().Get("radioDefenceSeconds"); + return m_Mode.Settings().Runtime("radioDefenceSeconds"); } int SecondsRemaining(float now) { diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_ScenarioComponent.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_ScenarioComponent.c index 5df7ee6..648cbd3 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_ScenarioComponent.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_ScenarioComponent.c @@ -6,12 +6,17 @@ class ERR_ScenarioComponent : ScriptComponent protected ResourceName m_Definition; protected ref ERR_SiteService m_Sites; protected bool m_Started; + protected ref ERR_ScenarioDefinition m_RuntimeDefinition; + protected ref ERR_GeneratedSites m_Generated; protected bool m_Finished; protected bool m_Failed; ERR_SiteService Sites() { return m_Sites; } string FailureReason() { + ERR_HQ hq = ERR_HQ.Get(); + if (hq && hq.Scouts() && !hq.Scouts().Error().IsEmpty()) return hq.Scouts().Error(); + if (m_Generated && !m_Generated.Error().IsEmpty()) return m_Generated.Error(); if (m_Sites && !m_Sites.FailureReason().IsEmpty()) return m_Sites.FailureReason(); return "Scenario or additional force preparation failed."; } @@ -23,12 +28,35 @@ class ERR_ScenarioComponent : ScriptComponent if (!m_Started) { m_Started = true; - ERR_ScenarioDefinition definition = ERR_ScenarioDefinition.Cast(SCR_BaseContainerTools.CreateInstanceFromPrefab(m_Definition)); + #ifdef WORKBENCH + string historicalFixture; + if (System.GetCLIParam("errSmokeOutcome", historicalFixture) && historicalFixture != "generated-sites" && historicalFixture != "opening-tools" && historicalFixture != "airfield-markers" && historicalFixture != "air-recon" && historicalFixture != "air-logistics" && historicalFixture != "air-assault") + m_Definition = "{ACA98B44E2173605}Configs/ERR/Tests/LegacySites.conf"; + #endif + m_RuntimeDefinition = ERR_ScenarioDefinition.Cast(SCR_BaseContainerTools.CreateInstanceFromPrefab(m_Definition)); + if (!m_RuntimeDefinition || !m_RuntimeDefinition.Valid()) { m_Failed = true; return ERR_PrepareResult.FAILED; } + #ifdef WORKBENCH + // Existing deterministic probes intentionally use authored coordinates. + string fixture; + if (System.GetCLIParam("errSmokeOutcome", fixture) && fixture != "generated-sites" && fixture != "airfield-markers" && fixture != "air-recon" && fixture != "air-logistics" && fixture != "air-assault") + foreach (ERR_SiteDefinition fixedSite : m_RuntimeDefinition.Sites) fixedSite.RandomClear = false; + #endif + m_Generated = new ERR_GeneratedSites(); + if (!m_Generated.Begin(m_RuntimeDefinition)) { m_Failed = true; return ERR_PrepareResult.FAILED; } + } + ERR_PrepareResult placement = m_Generated.Tick(); + if (placement == ERR_PrepareResult.FAILED) m_Failed = true; + if (placement != ERR_PrepareResult.READY) return placement; + if (!m_Sites) + { m_Sites = new ERR_SiteService(mode); - if (!m_Sites.Begin(definition, FieldMap())) { m_Failed = true; return ERR_PrepareResult.FAILED; } + if (!m_Sites.Begin(m_RuntimeDefinition, FieldMap())) { m_Failed = true; return ERR_PrepareResult.FAILED; } } ERR_PrepareResult result = m_Sites.Prepare(); if (result != ERR_PrepareResult.READY) return result; + ERR_PrepareResult population = PrepareAdditionalPopulation(); + if (population == ERR_PrepareResult.FAILED) { m_Failed = true; m_Sites.Rollback(); } + if (population != ERR_PrepareResult.READY) return population; if (!PrepareAdditionalForces()) { m_Failed = true; @@ -47,6 +75,7 @@ class ERR_ScenarioComponent : ScriptComponent ERR_GameMode mode = ERR_GameMode.Get(); if (mode && mode.Active() && m_Sites) m_Sites.Activate(); } + protected ERR_PrepareResult PrepareAdditionalPopulation() { return ERR_PrepareResult.READY; } protected bool PrepareAdditionalForces() { return true; } protected ResourceName FieldMap() { return ERR_Supplies.Map(); } protected override void OnDelete(IEntity owner) diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_Settings.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_Settings.c index 2ee2d56..1fc5b99 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_Settings.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_Settings.c @@ -3,16 +3,19 @@ class ERR_Settings { static const string PATH = "$profile:rereintroduced.json"; protected ref map m_Values = new map(); + protected ref map m_Resolved = new map(); protected bool m_ReadOnly; protected string m_Path; static array Keys() { - return {"reportIntervalSeconds", "supportSquadLimit", "responseRadiusMetres", "aiIntelChancePercent", "intelRevealChancePercent", "radioDefenceSeconds", "startTimeMinutes", "timeMultiplier", "startDateCode", "weatherProfile", "stingerChanceOneIn", "automaticConvoyEnabled"}; + return {"reportIntervalSeconds", "supportSquadLimit", "responseRadiusMetres", "aiIntelChancePercent", "intelRevealChancePercent", "radioDefenceSeconds", "startTimeMinutes", "timeMultiplier", "startDateCode", "weatherProfile", "stingerChanceOneIn", "automaticConvoyEnabled", "convoyCount", "heliTimerMinutes"}; } static bool Valid(string key, int value) { + if (key == "heliTimerMinutes") return value >= 1 && value <= 1440; + if (key == "convoyCount") return value >= 0 && value <= 20; if (key == "automaticConvoyEnabled") return value == 0 || value == 1; if (key == "stingerChanceOneIn") return value >= 0 && value <= 10000; if (key == "reportIntervalSeconds") return value >= 5 && value <= 60; @@ -44,8 +47,57 @@ class ERR_Settings return false; } + // Saved modes are distinct from validated concrete gameplay values. + static bool Randomizable(string key) + { + return key == "heliTimerMinutes" || key == "convoyCount" || key == "reportIntervalSeconds" || key == "supportSquadLimit" || key == "responseRadiusMetres" || key == "aiIntelChancePercent" || key == "intelRevealChancePercent" || key == "radioDefenceSeconds" || key == "startTimeMinutes" || key == "timeMultiplier" || key == "startDateCode" || key == "weatherProfile"; + } + static bool ValidSelection(string key, int value) + { + if (value == -1) return Randomizable(key); + if (value == -2) return key == "startTimeMinutes"; + return Valid(key, value); + } + static string SelectionText(int value) + { + if (value == -1) return "Random"; + if (value == -2) return "Random day"; + return value.ToString(); + } + static bool RandomBounds(string key, out int minimum, out int maximum) + { + minimum = 0; + if (key == "heliTimerMinutes") { minimum = 1; maximum = 1440; } + else if (key == "convoyCount") maximum = 20; + else if (key == "reportIntervalSeconds") { minimum = 5; maximum = 60; } + else if (key == "supportSquadLimit") maximum = 8; + else if (key == "responseRadiusMetres") { minimum = 500; maximum = 5000; } + else if (key == "aiIntelChancePercent" || key == "intelRevealChancePercent") maximum = 100; + else if (key == "radioDefenceSeconds") { minimum = 30; maximum = 1800; } + else if (key == "startTimeMinutes") maximum = 1439; + else if (key == "timeMultiplier") { minimum = 1; maximum = 24; } + else if (key == "weatherProfile") { minimum = 1; maximum = 3; } + else return false; + return true; + } + // Server-only, once per setting per round. Polls and gameplay reads never reroll. + // Date and daylight depend on the world and are resolved by their services. + int Runtime(string key) + { + int value = Get(key); + if (value != -1 || !Replication.IsServer()) return value; + if (m_Resolved.Contains(key)) return m_Resolved.Get(key); + int minimum, maximum; + if (!RandomBounds(key, minimum, maximum)) return value; + value = Math.RandomInt(minimum, maximum + 1); + m_Resolved.Set(key, value); + return value; + } + static int AddedDefault(string key) { + if (key == "heliTimerMinutes") return 15; + if (key == "convoyCount") return 3; if (key == "automaticConvoyEnabled") return 1; if (key == "stingerChanceOneIn") return 15; if (key == "startTimeMinutes") return 840; @@ -69,6 +121,8 @@ class ERR_Settings m_Values.Set("weatherProfile", AddedDefault("weatherProfile")); m_Values.Set("stingerChanceOneIn", AddedDefault("stingerChanceOneIn")); m_Values.Set("automaticConvoyEnabled", AddedDefault("automaticConvoyEnabled")); + m_Values.Set("convoyCount", AddedDefault("convoyCount")); + m_Values.Set("heliTimerMinutes", AddedDefault("heliTimerMinutes")); if (!Replication.IsServer()) { m_ReadOnly = true; return; } map loaded; if (Read(m_Path, loaded) || Read(m_Path + ".bak", loaded)) m_Values = loaded; @@ -97,7 +151,7 @@ class ERR_Settings float number; if (!json.ReadValue(key, number)) return false; int value = Math.Round(number); - if (number != value || !Valid(key, value)) return false; + if (number != value || !ValidSelection(key, value)) return false; values.Set(key, value); } return true; @@ -105,7 +159,7 @@ class ERR_Settings bool Set(string key, int value) { - if (!Replication.IsServer() || m_ReadOnly || !Valid(key, value)) return false; + if (!Replication.IsServer() || m_ReadOnly || !ValidSelection(key, value)) return false; JsonSaveContext json = new JsonSaveContext(); json.EnableTypeDiscriminator(false); foreach (string option : Keys()) @@ -139,6 +193,7 @@ class ERR_Settings return false; } } + if (Get(key) != value) m_Resolved.Remove(key); m_Values = checked; return true; } diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_SiteDefinition.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_SiteDefinition.c index 1298f99..5458c93 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_SiteDefinition.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_SiteDefinition.c @@ -57,8 +57,21 @@ class ERR_SiteDefinition ResourceName Prefab; [Attribute("0 0 0", UIWidgets.Coords)] vector Position; + [Attribute("0", UIWidgets.CheckBox, "Choose dry clear terrain once per round (prison, radio or mortar)")] + bool RandomClear; + [Attribute("0", UIWidgets.EditBox, "Composition heading in degrees")] + float Heading; + [Attribute("0", UIWidgets.EditBox, "Height of composition root above its surveyed ground")] + float RootHeight; + bool PlacementResolved; + [Attribute("12 0 0", UIWidgets.Coords, "Extraction aircraft offset from its site")] + vector AircraftOffset; + [Attribute("0", UIWidgets.CheckBox, "Require a clear pad on airfield grounds before aircraft creation")] + bool RequireAirfield; [Attribute("", UIWidgets.ResourceNamePicker, "Optional physical guard group", "et")] ResourceName Guards; + [Attribute("0", UIWidgets.CheckBox, "Choose a guard group from enabled content factions; retain catalog fallback when none enabled")] + bool AllowFactionPool; [Attribute()] ref array Patrol; [Attribute("0", UIWidgets.CheckBox, "Populate a finite squad from the faction catalog") ] bool Guarded; @@ -81,6 +94,8 @@ class ERR_ScenarioDefinition ref array Sites; [Attribute("2", UIWidgets.EditBox, "Independent accessible caches containing enough radio documents") ] int MinimumRadioSources; + [Attribute("0", UIWidgets.EditBox, "Finite hill scouts per round (0-32); each has a radio, binoculars and a sniper rifle")] + int ScoutCount; ERR_SiteDefinition Find(string id) { @@ -91,6 +106,7 @@ class ERR_ScenarioDefinition bool Valid() { + if (ScoutCount < 0 || ScoutCount > 32) return false; if (!Sites || Sites.IsEmpty() || Sites.Count() > 32) return false; set ids = new set(); int prisons, radios, extractions, groups, items, sources, maps, props, transports; @@ -99,6 +115,9 @@ class ERR_ScenarioDefinition foreach (ERR_SiteDefinition site : Sites) { if (!site || site.Id.IsEmpty() || ids.Contains(site.Id) || site.Prefab.IsEmpty()) return false; + if (site.RequireAirfield && site.Kind != ERR_LocationKind.EXTRACTION) return false; + if (site.Kind == ERR_LocationKind.RADIO && !site.Guarded && site.Guards.IsEmpty()) return false; + if (site.RandomClear && site.Kind != ERR_LocationKind.PRISON && site.Kind != ERR_LocationKind.RADIO && site.Kind != ERR_LocationKind.MORTAR) return false; if (site.Label.IsEmpty() || site.Label.Length() > 64) return false; if (!ERR_SiteDiscoveryRules.ValidRadius(site.Kind, site.DiscoverRadius)) return false; bool optionalSite = site.Kind == ERR_LocationKind.DEPOT || site.Kind == ERR_LocationKind.OUTPOST; @@ -118,7 +137,7 @@ class ERR_ScenarioDefinition foreach (ERR_SiteProp prop : site.Props) if (!prop || prop.Prefab.IsEmpty() || prop.Offset.Length() > 40) return false; } - if (site.Kind < ERR_LocationKind.PRISON || site.Kind > ERR_LocationKind.DEPOT) return false; + if (site.Kind < ERR_LocationKind.PRISON || site.Kind > ERR_LocationKind.MORTAR) return false; ids.Insert(site.Id); if (site.Kind == ERR_LocationKind.PRISON) prisons++; if (site.Kind == ERR_LocationKind.RADIO) radios++; diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_SiteDiscoveryRules.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_SiteDiscoveryRules.c index 8926179..61529c1 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_SiteDiscoveryRules.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_SiteDiscoveryRules.c @@ -7,7 +7,7 @@ class ERR_SiteDiscoveryRules { if (radius < 0 || radius > 60) return false; if (kind == ERR_LocationKind.RADIO) return radius <= RadioRadiusLimit(); - if (kind == ERR_LocationKind.DEPOT || kind == ERR_LocationKind.OUTPOST) return true; + if (kind == ERR_LocationKind.DEPOT || kind == ERR_LocationKind.OUTPOST || kind == ERR_LocationKind.MORTAR) return true; return (kind == ERR_LocationKind.PRISON || kind == ERR_LocationKind.EXTRACTION) && radius == 0; } static bool InRange(float radius, float horizontalDistance, float verticalDistance) diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_SiteService.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_SiteService.c index 46f3a0b..b2c36b8 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_SiteService.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_SiteService.c @@ -13,18 +13,22 @@ class ERR_SiteRuntime ERR_LocationComponent Location; IEntity Container; SCR_AIGroup Group; + string ExpectedGuardFaction; int InitialGuardCount; + ref ERR_PrisonPatrol PrisonPatrol; int LastInitialPhysical = -1; int LastInitialConscious = -1; Vehicle Transport; AIWaypointCycle PatrolCycle; ref array PatrolWaypoints = {}; + ref array Props = {}; } // One owner for finite physical site contents. No population or stock refill tick. class ERR_SiteService { protected ERR_GameMode m_Mode; + protected int m_ContentGuardIndex; protected ref ERR_ExtractionPlacement m_ExtractionPlacement; ERR_ExtractionPlacement ExtractionPlacement() { return m_ExtractionPlacement; } protected ref array m_Sites = {}; @@ -43,6 +47,11 @@ class ERR_SiteService void ERR_SiteService(ERR_GameMode mode) { m_Mode = mode; } int Count() { return m_Sites.Count(); } + ERR_SiteRuntime At(int index) + { + if (index < 0 || index >= m_Sites.Count()) return null; + return m_Sites[index]; + } bool Owns(IEntity entity) { return entity && m_Entities.Contains(entity); } // Snapshot only nearby mission-owned objects. Distant sites must not block // arrival, and vanilla map streaming remains the native preload's job. @@ -100,12 +109,23 @@ class ERR_SiteService PrintFormat("Reintroduced [sites]: cache clearance position=%1 clear=%2", ground, !m_Obstructed); return !m_Obstructed; } + protected bool BackpackClearance(vector position) + { + vector floor = ERR_Actors.Ground(position); + TraceBox trace = new TraceBox(); + trace.Start = floor + "0 0.15 0"; trace.End = floor + "0 1.15 0"; + trace.Mins = "-0.5 0 -0.5"; trace.Maxs = "0.5 0.1 0.5"; + trace.Flags = TraceFlags.ENTS | TraceFlags.WORLD; + return GetGame().GetWorld().TraceMove(trace, null) >= 1; + } protected bool CreateGuardOrders(ERR_SiteRuntime site, vector anchor) { + if (site.Definition.Kind == ERR_LocationKind.RADIO) anchor = ERR_Actors.Ground(site.Location.Position()); if (!site.Definition.Patrol || site.Definition.Patrol.IsEmpty()) { AIWaypoint defend = AIWaypoint.Cast(Spawn(ERR_Resources.DefendWaypoint(), anchor)); if (!defend) return false; + if (site.Definition.Kind == ERR_LocationKind.RADIO) defend.SetCompletionRadius(20); site.Group.AddWaypoint(defend); return true; } @@ -247,25 +267,35 @@ class ERR_SiteService { vector position = ERR_Actors.Ground(spec.Position); if (position[1] < 1) return Fail("site below sea level: " + spec.Id); - IEntity root = Spawn(spec.Prefab, position); + vector rootPosition = position; + if (spec.PlacementResolved && spec.Kind == ERR_LocationKind.PRISON) rootPosition = spec.Position; + rootPosition[1] = rootPosition[1] + spec.RootHeight; + IEntity root = ERR_Actors.Spawn(spec.Prefab, rootPosition, Vector(spec.Heading, 0, 0)); + if (root) m_Entities.Insert(root); if (!root) return Fail("site composition: " + spec.Id); ERR_SiteRuntime site = new ERR_SiteRuntime(); site.Definition = spec; site.Location = ERR_LocationComponent.Cast(root.FindComponent(ERR_LocationComponent)); if (!site.Location || !site.Location.Configure(spec.Id, spec.Kind, spec.Label)) return Fail("location identity: " + spec.Id); m_Sites.Insert(site); - if (spec.Kind == ERR_LocationKind.PRISON) m_Mode.ConfigureStart(position); + if (spec.Kind == ERR_LocationKind.PRISON) m_Mode.ConfigureStart(position, spec.Heading); if (spec.Kind == ERR_LocationKind.EXTRACTION) { - Vehicle helicopter = Vehicle.Cast(Spawn(m_Mode.Factions().ExtractionPrefab, position + "12 0 0")); + vector aircraftPosition = ERR_Actors.Ground(position + ERR_CampTerrain.Rotate(spec.AircraftOffset, spec.Heading)); + if (spec.RequireAirfield && !ERR_AirfieldPlacement.Clear(aircraftPosition)) return Fail("extraction airfield pad is missing or obstructed; no off-airfield fallback"); + Vehicle helicopter = Vehicle.Cast(Spawn(m_Mode.Factions().ExtractionPrefab, aircraftPosition)); if (!helicopter) return Fail("extraction vehicle"); if (!m_Mode.SetExtractionVehicle(helicopter)) return Fail("extraction vehicle registration"); m_ExtractionPlacement = new ERR_ExtractionPlacement(m_Mode, helicopter); } if (!spec.Container.IsEmpty()) { - if (!CacheClearance(position + spec.ContainerOffset)) return Fail("obstructed cache position: " + spec.Id); - site.Container = Spawn(spec.Container, position + spec.ContainerOffset); + vector containerPosition = position + ERR_CampTerrain.Rotate(spec.ContainerOffset, spec.Heading); + bool clearContainer; + if (spec.Kind == ERR_LocationKind.PRISON) clearContainer = BackpackClearance(containerPosition); + else clearContainer = CacheClearance(containerPosition); + if (!clearContainer) return Fail("obstructed cache position: " + spec.Id); + site.Container = Spawn(spec.Container, position + ERR_CampTerrain.Rotate(spec.ContainerOffset, spec.Heading)); if (!site.Container) return Fail("container: " + spec.Id); InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(site.Container.FindComponent(InventoryStorageManagerComponent)); if (!inventory) return Fail("container inventory: " + spec.Id); @@ -301,21 +331,39 @@ class ERR_SiteService { foreach (ERR_SiteProp prop : spec.Props) { - vector propPosition = ERR_Actors.Ground(position + prop.Offset); - if (!CacheClearance(propPosition)) return Fail("obstructed scenery position: " + spec.Id); + vector propPosition = ERR_Actors.Ground(position + ERR_CampTerrain.Rotate(prop.Offset, spec.Heading)); + // Radio furniture intentionally surrounds/supports its own elevated radio. + // Generated camp terrain was checked before any of these objects existed. + if (spec.Kind != ERR_LocationKind.RADIO && !CacheClearance(propPosition)) return Fail("obstructed scenery position: " + spec.Id); propPosition[1] = propPosition[1] + prop.Offset[1]; - IEntity scenery = ERR_Actors.Spawn(prop.Prefab, propPosition, prop.Angles); + IEntity scenery = ERR_Actors.Spawn(prop.Prefab, propPosition, prop.Angles + Vector(spec.Heading, 0, 0)); if (!scenery) return Fail("scenery prefab: " + spec.Id); - m_Entities.Insert(scenery); + m_Entities.Insert(scenery); site.Props.Insert(scenery); } } if (!CreateTransport(site, position)) return false; if (spec.Guarded || !spec.Guards.IsEmpty()) { - vector guardPosition = position + spec.GuardOffset; + vector guardPosition = position + ERR_CampTerrain.Rotate(spec.GuardOffset, spec.Heading); ResourceName groupPrefab = spec.Guards; + site.ExpectedGuardFaction = m_Mode.Factions().EnemyFactionKey; + if (spec.AllowFactionPool && m_Mode.Content()) + { + ResourceName selectedGroup = m_Mode.Content().GuardGroup(m_ContentGuardIndex++); + if (!selectedGroup.IsEmpty()) + { + groupPrefab = selectedGroup; + site.ExpectedGuardFaction = m_Mode.Content().GuardFaction(selectedGroup); + } + } if (groupPrefab.IsEmpty()) groupPrefab = m_Mode.Factions().GuardGroupPrefab; - site.Group = SCR_AIGroup.Cast(Spawn(groupPrefab, guardPosition)); + if (spec.Kind == ERR_LocationKind.PRISON) + { + site.Group = SCR_AIGroup.Cast(Spawn("{EC9F1AA42D0B7863}Prefabs/ERR/PrisonPatrol.et", guardPosition)); + if (!ERR_PrisonPatrol.Configure(site.Group, groupPrefab, m_Mode.EnemyFaction())) return Fail("prison patrol roster: " + spec.Id); + site.PrisonPatrol = new ERR_PrisonPatrol(); + } + else site.Group = SCR_AIGroup.Cast(Spawn(groupPrefab, guardPosition)); if (!site.Group) return Fail("guard group resource: " + spec.Id); if (!site.Group.m_aUnitPrefabSlots || site.Group.m_aUnitPrefabSlots.IsEmpty() || !site.Group.GetSpawnImmediately()) return Fail("guard profile must request an initial physical squad: " + spec.Id); site.InitialGuardCount = site.Group.m_aUnitPrefabSlots.Count(); @@ -337,11 +385,16 @@ class ERR_SiteService Fail("initial guard group disappeared or has no configured members: " + site.Definition.Id); return m_State; } - if (site.Group.GetFaction() != m_Mode.EnemyFaction()) + if (!m_Mode.IsMissionEnemy(site.Group.GetFaction())) { Fail("guard group faction disagrees with catalog: " + site.Definition.Id); return m_State; } + if (site.Group.GetFaction().GetFactionKey() != site.ExpectedGuardFaction) + { + Fail("guard prefab faction disagrees with its content definition: " + site.Definition.Id); + return m_State; + } array agents = {}; array physical = {}; site.Group.GetAgents(agents); @@ -352,7 +405,7 @@ class ERR_SiteService IEntity actor = agent.GetControlledEntity(); if (!actor || physical.Contains(actor)) continue; physical.Insert(actor); - if (SCR_FactionManager.SGetFaction(actor) != m_Mode.EnemyFaction()) + if (SCR_FactionManager.SGetFaction(actor) != site.Group.GetFaction()) { Fail("initial guard actor faction disagrees with catalog: " + site.Definition.Id); return m_State; @@ -381,6 +434,15 @@ class ERR_SiteService PrintFormat("Reintroduced [guards]: timeout detail site=%1 navmesh=%2 tileLoaded=%3 tileRequested=%4 dormantAlive=%5 dormantDead=%6", site.Definition.Id, navmesh != null, tileLoaded, tileRequested, site.Group.GetDormantAliveCount(), site.Group.GetDormantDeadCount()); Fail(string.Format("initial guard population incomplete or invalid: site=%1 requested=%2 physical=%3 conscious=%4 nativeComplete=%5; limit=90s; no replacement requested", site.Definition.Id, site.InitialGuardCount, physical.Count(), conscious, complete)); } + if (result == ERR_PrepareResult.READY && site.PrisonPatrol) + { + if (!site.PrisonPatrol.Place(site.Group, site.Location.Position())) + { + Fail("no clear perimeter positions for prison patrol"); return ERR_PrepareResult.FAILED; + } + result = site.PrisonPatrol.Radio(m_Mode, site.Group, m_GuardDeadline); + if (result == ERR_PrepareResult.FAILED) Fail("prison patrol large radio could not be equipped"); + } return result; } protected void CancelInitialGuardRequests() diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnLogic.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnLogic.c index 50ea2a8..547937d 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnLogic.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnLogic.c @@ -146,7 +146,7 @@ class ERR_SpawnLogic : SCR_SpawnLogic protected bool SpawnPosition(ERR_GameMode mode, out vector position) { - if (mode.Phase() == ERR_Phase.PRISON) return m_Placement.Prison(mode.PrisonPosition(), m_AuthorizedPositions, position); + if (mode.Phase() == ERR_Phase.PRISON) return m_Placement.Prison(mode.PrisonPosition(), m_AuthorizedPositions, position, mode.PrisonHeading()); array survivors = {}; ERR_Actors.Players(survivors, true); foreach (IEntity survivor : survivors) @@ -155,7 +155,7 @@ class ERR_SpawnLogic : SCR_SpawnLogic if (!mode.Players() || !mode.Players().CurrentActor(survivor) || !mode.PlayerFaction() || SCR_FactionManager.SGetFaction(survivor) != mode.PlayerFaction()) continue; if (m_Placement.Near(survivor, m_AuthorizedPositions, position)) return true; } - return m_Placement.Prison(mode.PrisonPosition(), m_AuthorizedPositions, position); + return m_Placement.Prison(mode.PrisonPosition(), m_AuthorizedPositions, position, mode.PrisonHeading()); } ERR_SpawnTicket CreateSpawnTicket(SCR_SpawnRequestComponent request, SCR_SpawnData data) @@ -328,7 +328,7 @@ class ERR_SpawnLogic : SCR_SpawnLogic m_Attempts.Remove(playerId); m_Retries.Remove(playerId); ERR_GameMode mode = ERR_GameMode.Get(); - if (mode) mode.PlayerSpawned(playerId, entity); + if (mode) { ERR_Actors.SetFaction(entity, mode.PlayerFaction()); mode.PlayerSpawned(playerId, entity); } SCR_PlayerController controller = SCR_PlayerController.Cast(GetGame().GetPlayerManager().GetPlayerController(playerId)); if (controller) controller.ERR_SetObserver(ERR_ObserverReason.NONE); PrintFormat("Reintroduced [spawn]: player %1 at %2", playerId, entity.GetOrigin()); diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnPlacement.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnPlacement.c index ec23f54..6d44c59 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnPlacement.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnPlacement.c @@ -2,18 +2,25 @@ class ERR_SpawnPlacement { protected IEntity m_Exclude; + protected vector m_Candidate; protected bool m_Blocked; - protected bool Obstacle(IEntity entity) + protected bool Occupied(IEntity entity) { - if (!entity || (!entity.GetVObject() && !ChimeraCharacter.Cast(entity))) return true; + // Character controller geometry is not included in every native shape trace. + // Narrow the broad-phase result by actual body position, not its query bounds. + if (entity != m_Exclude && ChimeraCharacter.Cast(entity) && vector.DistanceXZ(m_Candidate, entity.GetOrigin()) < 1.2 && Math.AbsFloat(m_Candidate[1] - entity.GetOrigin()[1]) < 2) m_Blocked = true; + return !m_Blocked; + } + protected bool Obstacle(IEntity entity, vector start = "0 0 0", vector direction = "0 0 0") + { + if (!entity) return false; IEntity parent = entity; for (int depth = 0; parent && depth < 32; depth++) { - if (parent == m_Exclude) return true; + if (parent == m_Exclude) return false; parent = parent.GetParent(); } - m_Blocked = true; - return false; + return true; } bool Clear(vector position, map reservations, int ownReservation = -1, IEntity exclude = null) { @@ -30,16 +37,24 @@ class ERR_SpawnPlacement vector sample = ERR_Actors.Ground(position + Vector(x * 0.45, 0, z * 0.45)); if (Math.AbsFloat(sample[1] - ground[1]) > 0.3) return false; } - m_Blocked = false; m_Exclude = exclude; - GetGame().GetWorld().QueryEntitiesByAABB(ground + "-0.45 0.15 -0.45", ground + "0.45 1.9 0.45", Obstacle); + m_Candidate = ground; m_Blocked = false; + GetGame().GetWorld().QueryEntitiesByAABB(ground + "-1.2 -2 -1.2", ground + "1.2 2 1.2", Occupied); + if (m_Blocked) { m_Exclude = null; return false; } + // Broad entity bounds overlap clear slots when the prison is rotated. + // Test the filled standing volume against physical geometry instead. + TraceBox volume = new TraceBox(); + volume.Start = ground + "0 0.15 0"; volume.End = volume.Start + "0 0.01 0"; + volume.Mins = "-0.45 0 -0.45"; volume.Maxs = "0.45 1.75 0.45"; + volume.Flags = TraceFlags.ENTS | TraceFlags.WORLD; + volume.Exclude = exclude; + float fraction = GetGame().GetWorld().TraceMove(volume, Obstacle); m_Exclude = null; - return !m_Blocked; + return ERR_ForceRules.Finite(fraction) && fraction >= 1; } - bool Prison(vector center, map reservations, out vector position) + bool Prison(vector center, map reservations, out vector position, float heading = 0) { - // Native character query bounds are about 4m wide. A 3m lattice leaves - // clearance between that conservative bound and the 0.9m query column. + // A 3m lattice leaves clearance around the 0.9m standing volume. // Search the four inner positions, then eight edge positions, then corners. // All sixteen centers remain at least 1.5m inside the authored +/-6m walls. for (int band = 0; band <= 2; band++) @@ -50,7 +65,7 @@ class ERR_SpawnPlacement if (row == 0 || row == 3) outerAxes++; if (column == 0 || column == 3) outerAxes++; if (outerAxes != band) continue; - vector candidate = ERR_Actors.Ground(center + Vector(-4.5 + column * 3, 0, -4.5 + row * 3)); + vector candidate = ERR_Actors.Ground(center + ERR_CampTerrain.Rotate(Vector(-4.5 + column * 3, 0, -4.5 + row * 3), heading)); if (!Clear(candidate, reservations)) continue; position = candidate; return true; diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_TimeService.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_TimeService.c index 6285b01..20afd2c 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_TimeService.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_TimeService.c @@ -33,6 +33,14 @@ class ERR_TimeService minutes = hours * 60 + remainder; return true; } + // Whole minutes strictly after sunrise and before sunset; exclusive end. + static bool DaylightBounds(float sunrise, float sunset, out int first, out int end) + { + if (sunrise < 0 || sunset > 24 || sunrise >= sunset) return false; + first = Math.Floor(sunrise * 60) + 1; + end = Math.Ceil(sunset * 60); + return first >= 0 && first < end && end <= 1440; + } bool Start(ERR_GameMode mode) { if (!Replication.IsServer() || !mode || !mode.Settings()) return false; @@ -41,8 +49,15 @@ class ERR_TimeService if (!world) return false; m_Manager = world.GetTimeAndWeatherManager(); if (!m_Manager) return false; - int startMinutes = mode.Settings().Get("startTimeMinutes"); - int multiplier = mode.Settings().Get("timeMultiplier"); + int startMinutes = mode.Settings().Runtime("startTimeMinutes"); + if (startMinutes == -2) + { + float sunrise, sunset; + int first, end; + if (!m_Manager.GetSunriseHour(sunrise) || !m_Manager.GetSunsetHour(sunset) || !DaylightBounds(sunrise, sunset, first, end)) return false; + startMinutes = Math.RandomInt(first, end); + } + int multiplier = mode.Settings().Runtime("timeMultiplier"); if (!ERR_Settings.Valid("startTimeMinutes", startMinutes) || !ERR_Settings.Valid("timeMultiplier", multiplier)) return false; float previousDuration = m_Manager.GetDayDuration(); bool previousAdvancement = m_Manager.GetIsDayAutoAdvanced(); diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_AirAmmoMission.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_AirAmmoMission.c new file mode 100644 index 0000000..4cb785c --- /dev/null +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_AirAmmoMission.c @@ -0,0 +1,239 @@ +// A unit's low-ammo radio check-in can request this airport-loaded delivery. +// Each trip creates at most twelve compatible magazines at the airfield; those +// exact identities must physically arrive before any native inventory transfer. +class ERR_AirAmmoMission +{ + protected ERR_HQ m_HQ; + protected ERR_GameMode m_Mode; + protected ERR_ReconFlightComponent m_Flight; + protected ERR_HQUnit m_Unit; + protected ref ERR_HQRoute m_Order, m_RecipientOrder; + protected ref array m_Cargo = {}, m_Spent = {}, m_Members = {}; + protected ref array m_Loads = {}; + protected ref ERR_InfantryAmmoTransfer m_Move; + protected ref array m_Operations = {}; + protected ref array m_PreviouslySubmitted; + protected float m_NextDiagnostic; + bool PendingNative() + { + foreach (ERR_ConvoyCargoCallback loading : m_Loads) if (!loading.Finished) return true; + foreach (ERR_InfantryAmmoTransfer operation : m_Operations) if (operation.Unresolved()) return true; + return false; + } + protected AIWaypoint m_Waypoint; + protected vector m_Point, m_Pad; + protected int m_Message, m_Token, m_State, m_Created, m_Delivered; + protected float m_Deadline, m_NextTick; + protected bool m_Finished; + bool Finished() { return m_Finished; + } + void ERR_AirAmmoMission(ERR_HQ hq, ERR_GameMode mode, ERR_ReconFlightComponent flight, ERR_HQUnit recipient, vector reported, int message, int trip, array submitted) + { + m_PreviouslySubmitted = submitted; + m_HQ = hq; + m_Mode = mode; + m_Flight = flight; + m_Unit = recipient; + m_Point = reported; + m_Message = message; + m_Token = 200000 + trip; + m_Deadline = GetGame().GetWorld().GetWorldTime() + 600000; + if (!m_HQ.ReserveAirAmmo(recipient, m_Token)) { m_Finished = true; + return; + } + array agents = {}; + recipient.Group.GetAgents(agents); + foreach (AIAgent agent : agents) if (agent && ERR_Actors.CanFight(agent.GetControlledEntity())) m_Members.Insert(agent.GetControlledEntity()); + bool clear; + for (int i = 0; i < 12; i++) + { + float angle = i * Math.PI / 6; + if (ERR_ReconAirports.FindClearPad(reported + Vector(Math.Sin(angle), 0, Math.Cos(angle)) * 80, m_Pad) && vector.DistanceXZ(reported, m_Pad) <= 200) { clear = true; + break; + } + } + if (!clear || m_Members.IsEmpty()) { Finish("no safe landing area near delivered request"); + return; + } + m_Order = hq.Downlink(flight.Crew(), "AIR AMMUNITION", "load twelve magazines and fly to reported unit position " + reported.ToString(), message); + m_RecipientOrder = hq.Downlink(recipient.Group, "AMMUNITION RENDEZVOUS", "meet supply helicopter at " + m_Pad.ToString(), message); + if (!m_Order || !m_RecipientOrder) Finish("physical radio downlink unavailable"); + } + protected ResourceName Magazine(IEntity actor) + { + if (!actor) return ""; + BaseWeaponManagerComponent manager = BaseWeaponManagerComponent.Cast(actor.FindComponent(BaseWeaponManagerComponent)); + if (!manager) return ""; + array weapons = {}; + manager.GetWeapons(weapons); + foreach (BaseWeaponComponent weapon : weapons) + { + if (!weapon || (weapon.GetWeaponType() != EWeaponType.WT_RIFLE && weapon.GetWeaponType() != EWeaponType.WT_MACHINEGUN && weapon.GetWeaponType() != EWeaponType.WT_SNIPERRIFLE)) continue; + array muzzles = {}; + weapon.GetMuzzlesList(muzzles); + foreach (BaseMuzzleComponent muzzle : muzzles) + { + BaseMagazineComponent magazine = muzzle.GetMagazine(); + if (magazine && magazine.GetOwner().GetPrefabData()) return magazine.GetOwner().GetPrefabData().GetPrefabName(); + } + } + return ""; + } + protected bool Owned() + { + return m_Unit && m_Unit.Group && m_Unit.Group.GetPlayerCount(true) == 0 && m_Unit.Group.GetFaction() == m_Mode.EnemyFaction() + && m_HQ.LogisticsToken(m_Unit.Group) == m_Token && m_Flight && !m_Flight.Lost() && m_Flight.Phase() != ERR_ReconPhase.RELEASED; + } + protected void Finish(string reason) + { + if (m_Finished) return; + m_Finished = true; + if (m_Move) m_Move.Stop(); + if (m_Waypoint) { if (m_Unit && m_Unit.Group) m_Unit.Group.RemoveWaypoint(m_Waypoint); + ERR_Actors.DeleteSpawned(m_Waypoint); + m_Waypoint = null; + } + if (m_Unit) m_HQ.ReleaseLogistics(m_Unit.Group, m_Token); + if (m_Unit && m_Unit.Group) + { + array releasedAgents = {}; + m_Unit.Group.GetAgents(releasedAgents); + foreach (AIAgent releasedAgent : releasedAgents) if (releasedAgent) releasedAgent.SetPermanentLOD(-1); + } + if (m_Flight) m_Flight.ReturnHome(); + ERR_HQ.Event("AIR AMMUNITION", string.Format("delivered=%1; %2; remaining original cargo retained", m_Delivered, reason)); + } + void Tick(float now) + { + if (m_Finished || now < m_NextTick) return; + m_NextTick = now + 1000; + if (!m_Mode.Active() || !Owned() || now >= m_Deadline) { Finish("mission expired or ownership lost"); + return; + } + if (m_HQ.AirAssault().MortarsBusy(m_Pad, now)) { Finish("mortar fire conflicts with landing corridor"); + return; + } + if (m_State == 0) + { + int aircraft = 1, recipient = 1; + if (m_Order) aircraft = m_Order.Advance(now, m_HQ.Journal()); + if (m_RecipientOrder) recipient = m_RecipientOrder.Advance(now, m_HQ.Journal()); + if (aircraft == 1) m_Order = null; + if (recipient == 1) m_RecipientOrder = null; + if (aircraft < 0 || recipient < 0) { Finish("radio order interrupted"); + return; + } + if (aircraft == 0 || recipient == 0) return; + m_Unit.ReleaseAssignment(); + m_State = 1; + } + InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(m_Flight.Aircraft().FindComponent(InventoryStorageManagerComponent)); + if (!inventory) { Finish("aircraft cargo storage unavailable"); + return; + } + if (m_State == 1) + { + if (!m_Flight.AtAirport()) { Finish("loading requires airport"); + return; + } + if (m_Created < 12) + { + ResourceName prefab = Magazine(m_Members[m_Created % m_Members.Count()]); + m_Created++; + if (prefab.IsEmpty()) return; + ERR_ConvoyCargoCallback callback = new ERR_ConvoyCargoCallback(); + m_Loads.Insert(callback); + if (!inventory.TrySpawnPrefabToStorage(prefab, null, -1, EStoragePurpose.PURPOSE_DEPOSIT, callback)) callback.Finished = true; + return; + } + foreach (ERR_ConvoyCargoCallback operation : m_Loads) if (!operation.Finished) return; + array items = {}; + ERR_Inventory.Items(inventory, items); + foreach (IEntity item : items) if (item && item.FindComponent(BaseMagazineComponent) && !m_Cargo.Contains(item) && !m_PreviouslySubmitted.Contains(item)) m_Cargo.Insert(item); + if (m_Cargo.IsEmpty()) { Finish("no physical cargo loaded"); + return; + } + m_Flight.LaunchDelivery(m_Pad); + m_State = 2; + ERR_HQ.Event("AIR AMMUNITION DEPARTURE", "native cargo aboard; destination from delivered unit request"); + return; + } + if (m_State == 2) + { + if (m_Flight.Phase() != ERR_ReconPhase.PARKED || vector.DistanceXZ(m_Flight.Aircraft().GetOrigin(), m_Pad) > 10) return; + array anchors = {}; + if (!ERR_InfantryAmmoAccess.Points(m_Flight.Aircraft(), anchors)) { Finish("no authored aircraft cargo access"); + return; + } + vector accessPoint = anchors[0]; + vector outward = accessPoint - m_Flight.Aircraft().GetOrigin(); + outward[1] = 0; + if (outward.Length() < 0.1) outward = "1 0 0"; + accessPoint = ERR_Actors.Ground(accessPoint + outward.Normalized() * 2); + m_Waypoint = AIWaypoint.Cast(ERR_Actors.Spawn(ERR_Resources.MoveWaypoint(), accessPoint)); + if (!m_Waypoint) { Finish("rendezvous waypoint unavailable"); + return; + } + m_Waypoint.SetCompletionRadius(0.5); + m_Unit.Group.AddWaypointAt(m_Waypoint, 0); + m_State = 3; + } + if (m_State == 3) + { + if (now >= m_NextDiagnostic) + { + m_NextDiagnostic = now + 15000; + float closest = 1e20; + foreach (IEntity approaching : m_Members) + if (ERR_Actors.CanFight(approaching)) closest = Math.Min(closest, vector.Distance(approaching.GetOrigin(), m_Flight.Aircraft().GetOrigin())); + ERR_HQ.Event("AIR AMMUNITION RENDEZVOUS", string.Format("nearest original recipient=%1m; confirmed magazines=%2", closest, m_Delivered)); + } + SCR_AIGroupUtilityComponent utility = m_Unit.Group.GetGroupUtilityComponent(); + if (utility && utility.m_Perception && !utility.m_Perception.m_aTargets.IsEmpty()) { Finish("recipient engaged in combat; delivery aborted"); return; } + m_Unit.Group.ActivateAI(); + array receivingAgents = {}; + m_Unit.Group.GetAgents(receivingAgents); + foreach (AIAgent receivingAgent : receivingAgents) + { + receivingAgent.SetPermanentLOD(0); + receivingAgent.ActivateAI(); + } + } + if (m_Move) + { + int result = m_Move.Tick(now); + if (result == 0) return; + if (result > 0) m_Delivered++; + m_Move = null; + if (m_Delivered >= 12) { Finish("delivery complete"); + return; + } + } + foreach (IEntity member : m_Members) + { + if (!ERR_Actors.CanFight(member) || ERR_Actors.Player(member) || ERR_Actors.Group(member) != m_Unit.Group || vector.Distance(member.GetOrigin(), m_Flight.Aircraft().GetOrigin()) > 15) continue; + foreach (IEntity magazine : m_Cargo) + { + if (!magazine || m_Spent.Contains(magazine) || !ERR_InfantryAmmoTransfer.Compatible(member, magazine)) continue; + m_Move = new ERR_InfantryAmmoTransfer(m_Mode, m_Flight.Aircraft(), m_Flight.Crew(), member, m_Unit.Group, magazine); + m_Move.Tick(now); + if (m_Move.Submitted()) { m_Spent.Insert(magazine); + m_PreviouslySubmitted.Insert(magazine); + m_Operations.Insert(m_Move); + return; + } + if (now >= m_NextDiagnostic) + { + m_NextDiagnostic = now + 15000; + ERR_HQ.Event("AIR AMMUNITION WAIT", m_Move.Reason()); + } + m_Move = null; + } + } + if (m_Spent.Count() >= m_Cargo.Count()) Finish("all original cargo operations completed"); + } + bool BlocksMortar(vector point) { return !m_Finished && vector.DistanceXZ(point, m_Pad) < 400; + } + void Stop() { Finish("mission stopped"); + } +} diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_AirAssaultLoad.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_AirAssaultLoad.c new file mode 100644 index 0000000..1f9f364 --- /dev/null +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_AirAssaultLoad.c @@ -0,0 +1,350 @@ +class ERR_AirPassenger +{ + IEntity Actor; + BaseCompartmentSlot Seat; + bool Locked = true; + bool Jumped; + ERR_AssaultParachute Chute; +} +class ERR_AirAssaultTeam +{ + SCR_AIGroup Group; + ref array Members = {}; + ref ERR_AirDropOrder Order; + bool Released; + void Landed() {} // Canopy completion is observed by the owning load for the entire original team. + void Update() + { + if (Released || !Group || !Order || Group.GetPlayerCount(true) > 0) return; + bool survivor; + foreach (ERR_AirPassenger member : Members) + { + if (!ERR_Actors.Alive(member.Actor)) continue; + if (!member.Jumped || CompartmentAccessComponent.GetVehicleIn(member.Actor) || member.Actor.GetOrigin()[1] - SCR_TerrainHelper.GetTerrainY(member.Actor.GetOrigin()) > 3) return; + survivor = survivor || ERR_Actors.CanFight(member.Actor); + } + if (!survivor) return; + Released = true; + Group.ActivateAI(); + Group.SetPermanentLOD(-1); + ERR_HQ.Get().LandAirTeam(Group, Order); + } +} +class ERR_AirDropGeometry +{ + static float Along(vector position, vector center, vector direction) + { vector offset = position - center; + offset[1] = 0; + return vector.Dot(offset, direction); + } + static bool Corridor(vector position, vector center, vector direction, vector velocity) + { + float along = Along(position, center, direction); + vector lateral = position - center - direction * along; + lateral[1] = 0; + velocity[1] = 0; + return along >= -175 && along <= 250 && lateral.Length() <= 45 && velocity.Length() >= 15 && vector.Dot(velocity.Normalized(), direction) >= 0.8; + } + static bool LandingLine(vector center, vector direction) + { + for (int step = -4; step <= 5; step++) + { + vector point = ERR_Actors.Ground(center + direction * (step * 50)); + if (point[1] < 2 || ChimeraWorldUtils.TryGetWaterSurfaceSimple(GetGame().GetWorld(), point) || !ERR_HQRoadIntercept.Standable(point)) return false; + TraceBox trace = new TraceBox(); + trace.Start = point + "0 3 0"; + trace.End = point + "0 190 0"; + trace.Mins = "-4 -1 -4"; + trace.Maxs = "4 1 4"; + trace.Flags = TraceFlags.ENTS | TraceFlags.WORLD; + if (GetGame().GetWorld().TraceMove(trace, null) < 1) return false; + } + return true; + } +} +// Eight original passengers, two original teams, one consumed load per aircraft. +class ERR_AirAssaultLoad +{ + static const ResourceName PARACHUTE = "{C31F210ABE0781A0}Prefabs/ERR/AssaultParachute.et"; + protected ERR_GameMode m_Mode; + protected ERR_ReconFlightComponent m_Flight; + protected Vehicle m_Aircraft; + protected int m_Serial, m_NextPassenger; + protected ref array m_Seats = {}; + protected ref array m_Passengers = {}; + protected ref array m_Teams = {}; + protected ref ERR_AirDropOrder m_Order; + protected float m_CoverUntil; + bool Cover(float now, out vector center) { if (!m_Order || !m_Used || m_Approaching || now >= m_CoverUntil) return false; + center = m_Order.Target; + return true; + } + bool NeedsService(float now) { return m_Used && !m_Approaching && now >= m_CoverUntil; + } + protected float m_LoadDeadline, m_NextBoard, m_NextJump, m_AirspaceUntil; + protected bool m_Ready, m_Failed, m_Stopped, m_Used, m_Approaching, m_RunCommitted; + protected vector m_Center, m_Direction, m_RunStart, m_RunEnd; + static void SetLock(IEntity actor, bool locked) + { + ERR_HQ hq = ERR_HQ.Get(); + if (hq && hq.AirAssault()) hq.AirAssault().Lock(actor, locked); + } + void ReuseRemaining() + { + m_Used = false; + m_Order = null; + m_CoverUntil = 0; + foreach (ERR_AirPassenger member : m_Passengers) + if (member.Actor && CompartmentAccessComponent.GetVehicleIn(member.Actor) == m_Aircraft) { member.Jumped = false; + member.Locked = true; + } + } + int Count() { return m_Passengers.Count(); + } + ERR_AirPassenger At(int index) { return m_Passengers[index]; + } + bool Used() { return m_Used; + } + bool Preparing() { return !m_Ready && !m_Failed && !m_Stopped; + } + bool Ready() + { + return m_Ready && !m_Failed && !m_Stopped && !m_Used && m_Flight && !m_Flight.Lost() + && (m_Flight.Phase() == ERR_ReconPhase.SEARCH || m_Flight.Phase() == ERR_ReconPhase.SHADOW) && Aboard() > 0; + } + void ERR_AirAssaultLoad(ERR_GameMode mode, ERR_ReconFlightComponent flight, int serial) + { m_Mode = mode; + m_Flight = flight; + m_Aircraft = flight.Aircraft(); + m_Serial = serial; + } + protected void Seats(IEntity entity) + { + BaseCompartmentManagerComponent manager = BaseCompartmentManagerComponent.Cast(entity.FindComponent(BaseCompartmentManagerComponent)); + if (manager) + { + array seats = {}; + manager.GetCompartments(seats); + foreach (BaseCompartmentSlot seat : seats) + if (seat && seat.GetType() == ECompartmentType.CARGO && seat.IsCompartmentAccessible() && !seat.IsOccupied() && !m_Seats.Contains(seat)) m_Seats.Insert(seat); + } + IEntity child = entity.GetChildren(); + while (child) { Seats(child); + child = child.GetSibling(); + } + } + protected void Failure(string reason) + { + m_Failed = true; + m_Approaching = false; + foreach (ERR_AirPassenger member : m_Passengers) member.Locked = false; + ERR_HQ.Event("AIR LOAD UNAVAILABLE", reason + "; original partial entities retained, reconnaissance remains available"); + } + void Load(vector pad) + { + m_LoadDeadline = GetGame().GetWorld().GetWorldTime() + 30000; + Seats(m_Aircraft); + ResourceName soldier = m_Mode.FactionSelection().Soldier(); + Resource chute = Resource.Load(PARACHUTE); + if (m_Seats.Count() < 8 || soldier.IsEmpty() || !chute || !chute.IsValid()) { Failure("eight usable cargo seats, soldier or canopy unavailable"); + return; + } + for (int t = 0; t < 2; t++) + { + ERR_AirAssaultTeam team = new ERR_AirAssaultTeam(); + team.Group = SCR_AIGroup.Cast(ERR_Actors.Spawn("{C31F210ABE078195}Prefabs/ERR/ReconCrew.et", pad)); + m_Teams.Insert(team); + if (!team.Group) { Failure("passenger group spawn failed"); + return; + } + m_Mode.Own(team.Group); + team.Group.SetFaction(m_Mode.EnemyFaction()); + team.Group.SetPermanentLOD(0); + } + for (int i = 0; i < 8; i++) + { + ERR_AirPassenger member = new ERR_AirPassenger(); + member.Seat = m_Seats[i]; + AIGroup group = m_Teams[i % 2].Group; + member.Actor = member.Seat.SpawnCharacterInCompartment(soldier, group, "{C31F210ABE078195}Prefabs/ERR/ReconCrew.et"); + m_Passengers.Insert(member); + m_Teams[i % 2].Members.Insert(member); + if (!member.Actor || group != m_Teams[i % 2].Group) { Failure("native passenger creation or group identity failed"); + return; + } + } + } + protected void Boarding(float now) + { + foreach (ERR_AirAssaultTeam loadingTeam : m_Teams) + { + if (!loadingTeam.Group) continue; + loadingTeam.Group.ActivateAI(); + array loadingAgents = {}; + loadingTeam.Group.GetAgents(loadingAgents); + foreach (AIAgent loadingAgent : loadingAgents) { loadingAgent.SetPermanentLOD(0); + loadingAgent.ActivateAI(); + } + } + if (now >= m_LoadDeadline) { Failure(string.Format("native passenger boarding timed out; seated=%1/%2", Aboard(), Count())); + return; + } + bool all = m_Passengers.Count() == 8; + foreach (ERR_AirPassenger member : m_Passengers) + { + if (!ERR_Actors.CanFight(member.Actor)) { all = false; + continue; + } + if (CompartmentAccessComponent.GetVehicleIn(member.Actor) == m_Aircraft && member.Seat.GetOccupant() == member.Actor) continue; + all = false; + if (now < m_NextBoard || CompartmentAccessComponent.GetVehicleIn(member.Actor) || member.Seat.IsOccupied()) continue; + SCR_CompartmentAccessComponent access = SCR_CompartmentAccessComponent.Cast(member.Actor.FindComponent(SCR_CompartmentAccessComponent)); + if (access) access.MoveInVehicle(m_Aircraft, ECompartmentType.CARGO, false, member.Seat); + } + if (now >= m_NextBoard) m_NextBoard = now + 1000; + if (!all) return; + for (int t = 0; t < m_Teams.Count(); t++) + { + ERR_AirAssaultTeam team = m_Teams[t]; + foreach (ERR_AirPassenger original : team.Members) + if (ERR_Actors.Group(original.Actor) != team.Group || !ERR_Actors.SetFaction(original.Actor, m_Mode.EnemyFaction())) { Failure("original passenger faction/group changed"); + return; + } + ERR_ForceRecord record = m_Mode.Forces().Register(string.Format("airborne-%1-team-%2", m_Serial, t), ERR_ForceKind.PATROL, m_Aircraft.GetOrigin(), 4, null, team.Group, now); + if (!record) { Failure("finite passenger ledger refused registration"); + return; + } + record.Pinned = true; + m_Mode.RegisterGroup(team.Group); + ERR_HQ.Get().ReserveGroup(team.Group); + team.Group.ActivateAI(); + array agents = {}; + team.Group.GetAgents(agents); + foreach (AIAgent agent : agents) { agent.SetPermanentLOD(0); + agent.ActivateAI(); + } + } + m_Ready = true; + ERR_HQ.Event("AIR LOAD READY", "eight original passengers seated in two four-person teams"); + } + int Aboard() + { + if (!m_Aircraft) return 0; + int count; + foreach (ERR_AirPassenger member : m_Passengers) + if (ERR_Actors.CanFight(member.Actor) && !ERR_Actors.Player(member.Actor) && CompartmentAccessComponent.GetVehicleIn(member.Actor) == m_Aircraft) count++; + return count; + } + bool HoldsSeat(IEntity actor) + { + if (m_Stopped || m_Failed || !ERR_Actors.CanFight(actor) || ERR_Actors.Player(actor)) return false; + foreach (ERR_AirAssaultTeam team : m_Teams) + foreach (ERR_AirPassenger member : team.Members) + if (member.Actor == actor && member.Locked && ERR_Actors.Group(actor) == team.Group) + return (m_Flight && m_Flight.Phase() < ERR_ReconPhase.PARKED && CompartmentAccessComponent.GetVehicleIn(actor) == m_Aircraft) || (member.Chute && CompartmentAccessComponent.GetVehicleIn(actor) == member.Chute); + return false; + } + void Lock(IEntity actor, bool locked) + { foreach (ERR_AirPassenger member : m_Passengers) if (member.Actor == actor) member.Locked = locked; + } + bool Begin(ERR_AirDropOrder order, float now) + { + if (!Ready() || !order || now >= order.ExpiresAt) return false; + vector radial = m_Aircraft.GetOrigin() - order.Target; + radial[1] = 0; + float heading = Math.Atan2(radial[0], radial[2]); + bool found; + for (int attempt = 0; attempt < 12; attempt++) + { + float angle = heading + attempt * Math.PI / 6; + radial = Vector(Math.Sin(angle), 0, Math.Cos(angle)); + m_Center = ERR_Actors.Ground(order.Target + radial * 450); + m_Direction = Vector(-radial[2], 0, radial[0]); + if (ERR_AirDropGeometry.LandingLine(m_Center, m_Direction)) { found = true; + break; + } + } + if (!found) return false; + m_RunStart = m_Center - m_Direction * 350; + m_RunEnd = m_Center + m_Direction * 450; + m_CoverUntil = now + 300000; + m_Order = order; + m_Used = true; + m_Approaching = true; + m_RunCommitted = false; + m_NextPassenger = 0; + m_NextJump = now; + foreach (ERR_AirAssaultTeam team : m_Teams) team.Order = order; + m_AirspaceUntil = order.ExpiresAt + 150000; + return true; + } + bool Approach(out vector point) + { + point = m_RunStart; + if (m_RunCommitted) point = m_RunEnd; + return m_Approaching && !m_Stopped; + } + void Abort() + { if (m_Approaching && m_Order) m_CoverUntil = GetGame().GetWorld().GetWorldTime() + 300000; + m_Approaching = false; + m_RunCommitted = false; + } + bool BlocksMortar(vector impact, float now) + { + if (!m_Order || vector.DistanceXZ(impact, m_Order.Target) >= 1200) return false; + foreach (ERR_AirPassenger member : m_Passengers) + if (member.Chute && member.Actor && CompartmentAccessComponent.GetVehicleIn(member.Actor) == member.Chute) return true; + return now < m_AirspaceUntil; + } + void Update(float now) + { + if (m_Stopped || !Replication.IsServer() || !m_Mode.Active()) return; + foreach (ERR_AirAssaultTeam team : m_Teams) team.Update(); + if (Preparing()) { Boarding(now); + return; + } + if (!m_Approaching) return; + if (!m_Flight || m_Flight.Lost() || m_Flight.Phase() >= ERR_ReconPhase.RETURNING || !ERR_Actors.Alive(m_Aircraft) || now >= m_Order.ExpiresAt) + { Abort(); + ERR_HQ.Event("AIR DROP ABORTED", "authorization expired or aircraft unavailable; no new passengers created"); + return; + } + foreach (ERR_AirAssaultTeam originalTeam : m_Teams) + if (!originalTeam.Group || originalTeam.Group.GetPlayerCount(true) > 0 || originalTeam.Group.GetFaction() != m_Mode.EnemyFaction()) { Abort(); + return; + } + vector position = m_Aircraft.GetOrigin(); + if (!m_RunCommitted && vector.DistanceXZ(position, m_RunStart) <= 80) m_RunCommitted = true; + if (m_RunCommitted && ERR_AirDropGeometry.Along(position, m_Center, m_Direction) > 300) { Abort(); + return; + } + float height = position[1] - SCR_TerrainHelper.GetTerrainY(position); + if (!m_RunCommitted || now < m_NextJump || height < 90 || height > 180 || !m_Aircraft.GetPhysics() + || !ERR_AirDropGeometry.Corridor(position, m_Center, m_Direction, m_Aircraft.GetPhysics().GetVelocity())) return; + while (m_NextPassenger < m_Passengers.Count()) + { + int index = m_NextPassenger++; + ERR_AirPassenger passenger = m_Passengers[index]; + if (passenger.Jumped || !ERR_Actors.CanFight(passenger.Actor) || ERR_Actors.Player(passenger.Actor) || CompartmentAccessComponent.GetVehicleIn(passenger.Actor) != m_Aircraft) continue; + vector exit = m_Aircraft.CoordToParent("12 -4 0"); + ERR_AssaultParachute chute = ERR_AssaultParachute.Cast(ERR_Actors.Spawn(PARACHUTE, exit)); + m_NextJump = now + 2000; + if (!chute) { ERR_HQ.Event("AIR DROP FAILED", "canopy creation refused; original passenger retained"); + continue; + } + m_Mode.Own(chute); + passenger.Chute = chute; + vector landing = m_Center + m_Direction * ERR_AirDropGeometry.Along(position, m_Center, m_Direction); + passenger.Jumped = chute.BeginJump(passenger.Actor, m_Teams[index % 2], landing); + ERR_HQ.Event("AIR DROP JUMP", string.Format("original passenger=%1 transfer requested=%2", index, passenger.Jumped)); + break; + } + if (m_NextPassenger >= m_Passengers.Count()) Abort(); + } + void Stop() + { + m_Stopped = true; + Abort(); + foreach (ERR_AirPassenger passenger : m_Passengers) passenger.Locked = false; + } +} diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_AirAssaultSystem.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_AirAssaultSystem.c new file mode 100644 index 0000000..541dae6 --- /dev/null +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_AirAssaultSystem.c @@ -0,0 +1,223 @@ +class ERR_AirAssaultSystem +{ + protected ERR_HQ m_HQ; + protected ERR_GameMode m_Mode; + protected ref array m_Loads = {}; + protected ref ERR_AirSupportPolicy m_Policy = new ERR_AirSupportPolicy(); + protected ref ERR_HQRoute m_Route; + protected ref ERR_AirDropOrder m_Order; + protected ERR_AirAssaultLoad m_OrderedLoad; + protected float m_NextDecision; + protected bool m_Stopped; + protected string m_LoggedReason; + void ERR_AirAssaultSystem(ERR_HQ hq, ERR_GameMode mode) { m_HQ = hq; + m_Mode = mode; + } + string Status() { return "Airborne support: " + m_Policy.Reason + string.Format("; finite loads %1/4", m_Loads.Count()); + } + ERR_AirAssaultLoad Load(ERR_ReconFlightComponent flight, vector pad, int serial) + { + if (!Replication.IsServer() || m_Stopped || !m_Mode.Active() || m_Loads.Count() >= 4 || m_Mode.Forces().Count() > 253) return null; + ERR_AirAssaultLoad load = new ERR_AirAssaultLoad(m_Mode, flight, m_Loads.Count() + 1); + m_Loads.Insert(load); + // Consume the finite load before any native spawn; never refund partial failures. + load.Load(pad); + return load; + } + bool HoldsSeat(IEntity actor) + { + if (m_Stopped || !m_Mode.Active()) return false; + foreach (ERR_AirAssaultLoad load : m_Loads) if (load.HoldsSeat(actor)) return true; + return false; + } + void Lock(IEntity actor, bool locked) + { + foreach (ERR_AirAssaultLoad load : m_Loads) load.Lock(actor, locked); + } + bool MortarsBusy(vector point, float now) + { + array batteries = {}; + m_HQ.Mortars().Batteries(batteries); + foreach (ERR_MortarBattery battery : batteries) + { + if (now < battery.AirspaceUntil && vector.DistanceXZ(point, battery.AirspaceImpact) < battery.AirspaceRadius + 900) return true; + ERR_HQReport report = battery.Report; + if (battery.PendingRadioReport) report = battery.PendingRadioReport; + if ((battery.Activity || battery.RadioOrder || battery.CommandOpen || battery.Released) && report && vector.DistanceXZ(point, report.Position) < 1200) return true; + } + return false; + } + bool BlocksMortar(vector impact, float now) + { + if (m_Stopped) return false; + if (m_Order && vector.DistanceXZ(impact, m_Order.Target) < 1200) return true; + foreach (ERR_AirAssaultLoad load : m_Loads) if (load.BlocksMortar(impact, now)) return true; + return false; + } + void Maintain(float now) + { + if (!Replication.IsServer() || m_Stopped || !m_Mode.Active()) return; + foreach (ERR_AirAssaultLoad load : m_Loads) load.Update(now); + } + protected void CancelOrder(float now, string reason) + { + m_Route = null; + m_Order = null; + m_OrderedLoad = null; + m_Policy.Retry(now); + m_Policy.Reason = reason; + ERR_HQ.Event("AIR DROP WITHHELD", reason); + } + void Tick(float now) + { + if (!Replication.IsServer() || m_Stopped || !m_Mode.Active() || m_Mode.Phase() < ERR_Phase.RADIO_SEARCH) return; + if (m_Route) + { + if (!m_OrderedLoad || !m_OrderedLoad.Ready() || now >= m_Order.ExpiresAt) { CancelOrder(now, "order expired or original passenger load unavailable"); + return; + } + int delivery = m_Route.Advance(now, m_HQ.Journal()); + if (delivery < 0) { CancelOrder(now, "helicopter downlink interrupted; troops retained"); + return; + } + if (delivery == 0) return; + ERR_HQBelief belief = m_HQ.Memory().GetById(m_Order.BeliefId); + ERR_AirSupportSituation situation; + if (belief) situation = m_HQ.AirSituation(belief, m_OrderedLoad, now); + if (!belief || !ERR_AirSupportPolicy.Refusal(situation).IsEmpty() || vector.DistanceXZ(belief.PredictedPosition, m_Order.Target) > 150) + { CancelOrder(now, "memory, ground response or airspace changed during radio delivery"); + return; + } + if (!m_OrderedLoad.Begin(m_Order, now)) { CancelOrder(now, "no clear drop corridor; continue reconnaissance"); + return; + } + m_Policy.Committed(now); + m_Policy.Reason = "HQ-authorized drop underway"; + ERR_HQ.Event("AIR DROP AUTHORIZED", string.Format("belief=%1 report=M%2 target=%3; immutable delivered order", m_Order.BeliefId, m_Order.MessageId, m_Order.Target)); + m_Route = null; + m_Order = null; + m_OrderedLoad = null; + return; + } + if (now < m_NextDecision) return; + m_NextDecision = now + 5000; + ERR_ReconFlightComponent flight = m_HQ.Recon().Current(); + ERR_AirAssaultLoad load; + if (flight) load = flight.Assault(); + ERR_HQBelief best; + ERR_AirSupportSituation bestSituation; + float score = -1; + for (int index = 0; index < m_HQ.Memory().Count(); index++) + { + ERR_HQBelief candidate = m_HQ.Memory().At(index); + if (!candidate || candidate.Kind != ERR_HQMemoryKind.SIGHTING) continue; + ERR_AirSupportSituation candidateSituation = m_HQ.AirSituation(candidate, load, now); + float value = candidate.Confidence / (1 + candidate.Radius / 500); + if (!ERR_AirSupportPolicy.Refusal(candidateSituation).IsEmpty()) value -= 10; + if (value <= score && best) continue; + score = value; + best = candidate; + bestSituation = candidateSituation; + } + bool approve = m_Policy.Consider(bestSituation, now); + if (m_Mode.Settings().Runtime("supportSquadLimit") <= 0) { approve = false; + m_Policy.Reason = "HQ support disabled"; + } + if (m_LoggedReason != m_Policy.Reason) { m_LoggedReason = m_Policy.Reason; + ERR_HQ.Event("AIR DROP DECISION", Status()); + } + if (!approve || !best || !load) return; + ERR_HQRoute route = m_HQ.Downlink(flight.Crew(), "AIR DROP", m_Policy.Reason, best.MessageId); + if (!route) { m_Policy.Reason = "no physical radio downlink to helicopter"; + return; + } + m_Route = route; + m_OrderedLoad = load; + m_Order = new ERR_AirDropOrder(); + m_Order.BeliefId = best.BeliefId; + m_Order.BeliefRevision = best.BeliefRevision; + m_Order.MessageId = best.MessageId; + m_Order.Target = best.PredictedPosition; + m_Order.ExpiresAt = now + 120000; + m_Order.Report = best.Report.Snapshot(); + } + void Stop() + { + m_Stopped = true; + m_Route = null; + m_Order = null; + foreach (ERR_AirAssaultLoad load : m_Loads) load.Stop(); + } +} + +modded class ERR_HQ +{ + ERR_AirSupportSituation AirSituation(ERR_HQBelief belief, ERR_AirAssaultLoad load, float now) + { + ERR_AirSupportSituation result = new ERR_AirSupportSituation(); + result.AircraftReady = load && load.Ready(); + if (!belief) return result; + result.BeliefId = belief.BeliefId; + result.Samples = belief.SampleCount; + result.Age = (now - belief.ObservedAt) / 1000; + result.Confidence = belief.Confidence; + result.Radius = belief.Radius; + result.MotionKnown = belief.HasVelocity; + result.Speed = belief.Speed; + result.Infantry = belief.TravelMode == "on foot"; + if (belief.Report) result.Spotted = belief.Report.SeenEscapists; + result.ArtilleryBusy = m_AirAssault.MortarsBusy(belief.PredictedPosition, now); + foreach (ERR_HQUnit unit : m_Units) + { + // HQ knows friendly positions/strength from delivered check-ins, never live locations. + ERR_HQWatchEntry status = m_Watch.Find(unit.ForceSourceId); + if (!status || status.ObservedAt < 0 || now < status.ObservedAt || now - status.ObservedAt > 180000) continue; + if (vector.DistanceXZ(status.Position, belief.PredictedPosition) < 1000) result.ConfirmedLosses += status.ConfirmedLosses; + if (status.Closed || status.Fit <= 0 || unit.ReservedForSupport || unit.HomeGuard || unit.LogisticsReservation > 0 || m_Watch.ArmedSearchBlocked(unit.ForceSourceId, now)) continue; + ERR_HQTask task = unit.PlannedTask(); + float distance = vector.DistanceXZ(status.Position, belief.PredictedPosition); + if (task) + { + if (task.BeliefId == belief.BeliefId && now < task.ExpiresAt && distance <= 900) result.CommittedFit += status.Fit; + } + else if (distance <= 600) result.GroundFit += status.Fit; + } + return result; + } + void LandAirTeam(SCR_AIGroup group, ERR_AirDropOrder order) + { + foreach (ERR_HQUnit unit : m_Units) + { + if (unit.Group != group) continue; + unit.ReservedForSupport = false; + if (!order || !unit.Eligible(m_Mode)) return; + AIWaypoint waypoint = AIWaypoint.Cast(ERR_Actors.Spawn(ERR_Resources.SearchWaypoint(), ERR_Actors.Ground(order.Target))); + if (!waypoint) return; + unit.Release(); + unit.Waypoint = waypoint; + unit.Assignment = order.Report.Snapshot(); + unit.Task = new ERR_HQTask(); + unit.Task.BeliefId = order.BeliefId; + unit.Task.BeliefRevision = order.BeliefRevision; + unit.Task.Role = ERR_HQPursuitRole.SEARCH; + unit.Task.Destination = order.Target; + unit.Task.QueuedAt = GetGame().GetWorld().GetWorldTime(); + unit.Task.ExpiresAt = unit.Task.QueuedAt + 120000; + group.AddWaypointAt(waypoint, 0); + ERR_HQ.Event("AIR TEAM LANDED", "original team searching carried HQ order at " + order.Target.ToString()); + return; + } + } +} + +modded class ERR_MortarSystem +{ + override bool Safe(ERR_MortarBattery battery, vector impact, float flight) + { + if (m_HQ.AirAssault().BlocksMortar(impact, GetGame().GetWorld().GetWorldTime()) || m_HQ.Airfield().BlocksMortar(impact)) + { SafetyReason = "HQ airborne drop corridor or descending troops"; + return false; + } + return super.Safe(battery, impact, flight); + } +} diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_AirReconSystem.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_AirReconSystem.c new file mode 100644 index 0000000..c4e95a2 --- /dev/null +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_AirReconSystem.c @@ -0,0 +1,109 @@ +// Owner's original search-helicopter launch/loss cadence, connected to this mission's HQ owner. +class ERR_ReconSchedule +{ + float Deadline = -1; + int Minutes = 15; + bool Started; + bool Stopped; + void Begin(float now) { if (!Started && !Stopped) { Started = true; Deadline = now + Minutes * 60000.0; } } + bool Due(float now, bool active) { return Started && !Stopped && !active && Deadline >= 0 && now >= Deadline; } + void Launched() { Deadline = -1; } + void Lost(float now) { if (!Stopped) Deadline = now + Minutes * 60000.0; } + void Change(int minutes, float now, bool active) { Minutes = minutes; if (Started && !Stopped && !active) Deadline = now + Minutes * 60000.0; } + void Stop() { Stopped = true; Deadline = -1; } +} +class ERR_AirReconSystem +{ + protected ERR_GameMode m_Mode; + protected ref ERR_ReconAirports m_Airports = new ERR_ReconAirports(); + protected ref ERR_ReconSchedule m_Schedule = new ERR_ReconSchedule(); + protected ref array m_Flights = {}; + protected ERR_ReconFlightComponent m_Current; + protected int m_Serial, m_PadAttempts; + protected float m_NextPad; + protected string m_Reason = "countdown starts after prison escape"; + void ERR_AirReconSystem(ERR_GameMode mode) { m_Mode = mode; m_Schedule.Minutes = mode.Settings().Runtime("heliTimerMinutes"); } + bool SupportPad(out vector point) + { + foreach (vector airport : m_Airports.m_Positions) + if (ERR_ReconAirports.FindClearPad(airport, point)) return true; + return false; + } + ERR_ReconFlightComponent Current() { return m_Current; } + bool Owns(SCR_AIGroup group) + { + foreach (ERR_ReconFlightComponent flight : m_Flights) if (flight && flight.Crew() == group) return true; + return false; + } + bool SetDelay(int minutes) + { + if (!Replication.IsServer() || m_Schedule.Stopped || !m_Mode.Settings().Set("heliTimerMinutes", minutes)) return false; + m_Schedule.Change(minutes, GetGame().GetWorld().GetWorldTime(), m_Current != null); + if (!m_Current) m_PadAttempts = 0; + ERR_HQ.Event("HELICOPTER TIMER", Status()); + return true; + } + void Return() { if (Replication.IsServer() && m_Current) m_Current.ReturnHome(); } + string Status() + { + string state = m_Reason; + if (m_Current) state = m_Current.Status(); + else if (m_Schedule.Started && !m_Schedule.Stopped) + { + float due = m_Schedule.Deadline; if (m_PadAttempts > 0) due = m_NextPad; + state += string.Format("; next attempt in %1 seconds", Math.Ceil(Math.Max(0, due - GetGame().GetWorld().GetWorldTime()) / 1000)); + } + return string.Format("Search helicopter: delay %1 minutes; %2", m_Schedule.Minutes, state); + } + void Tick(float now) + { + if (!Replication.IsServer() || m_Schedule.Stopped || !m_Mode || m_Mode != ERR_GameMode.Get() || !m_Mode.Active()) return; + m_Airports.Update(); + if (m_Current) + { + m_Current.Update(now); + if (!m_Current.Lost()) return; + m_Reason = m_Current.Status(); m_Current.Release(false); + m_Current = null; m_Schedule.Lost(now); m_PadAttempts = 0; + ERR_HQ.Event("HELICOPTER LOST", Status()); + return; + } + if (m_Mode.Phase() < ERR_Phase.RADIO_SEARCH) return; + if (!m_Schedule.Started) { m_Schedule.Begin(now); ERR_HQ.Event("HELICOPTER TIMER", Status()); } + if (m_Schedule.Due(now, false) && m_PadAttempts == 0) + { m_PadAttempts = 3; m_NextPad = now; m_Schedule.Lost(now); } + if (m_PadAttempts == 0 || now < m_NextPad) return; + m_PadAttempts--; m_NextPad = now + 30000; + // All waves share the normal finite ledger cap. Never create an untracked crew. + if (m_Serial >= 64 || m_Mode.Forces().Count() >= 256) { m_Reason = "round aircraft/force bookkeeping capacity reached"; m_Schedule.Stop(); return; } + vector pad; bool found; + if (!m_Airports.m_Positions.IsEmpty()) + { + int first = Math.RandomInt(0, m_Airports.m_Positions.Count()); + for (int attempt = 0; attempt < m_Airports.m_Positions.Count(); attempt++) + if (ERR_ReconAirports.FindClearPad(m_Airports.m_Positions[(first + attempt) % m_Airports.m_Positions.Count()], pad)) { found = true; break; } + } + if (!found) { m_Reason = "no clear airfield departure pad; bounded retry pending"; ERR_HQ.Event("HELICOPTER PAD", Status()); return; } + m_PadAttempts = 0; m_Serial++; + Vehicle aircraft = Vehicle.Cast(ERR_Actors.Spawn("{C31F210ABE078192}Prefabs/ERR/ReconHelicopter.et", pad, Vector(Math.RandomFloat(0, 360), 0, 0))); + if (!aircraft) { m_Reason = "aircraft creation failed; next attempt after full delay"; return; } + m_Mode.Own(aircraft); + ERR_ReconFlightComponent flight = ERR_ReconFlightComponent.Cast(aircraft.FindComponent(ERR_ReconFlightComponent)); + if (!flight) { m_Reason = "flight component missing; partial aircraft retained"; return; } + m_Current = flight; m_Flights.Insert(flight); m_Schedule.Launched(); + flight.Initialize(m_Mode, pad, m_Serial); + ERR_HQ.Event("HELICOPTER LAUNCH", string.Format("wave=%1 airfield pad=%2", m_Serial, pad)); + } + void Removed(ERR_ReconFlightComponent flight) + { + if (!Replication.IsServer() || m_Schedule.Stopped || !flight || m_Current != flight || !m_Mode || !m_Mode.Active()) return; + m_Current = null; m_PadAttempts = 0; m_Reason = "aircraft removed; replacement delayed"; + m_Schedule.Lost(GetGame().GetWorld().GetWorldTime()); + ERR_HQ.Event("HELICOPTER LOST", Status()); + } + void Stop() + { + m_Schedule.Stop(); m_Reason = "mission stopped"; + foreach (ERR_ReconFlightComponent flight : m_Flights) if (flight) flight.Release(false); + } +} diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_AirSupportPolicy.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_AirSupportPolicy.c new file mode 100644 index 0000000..d003992 --- /dev/null +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_AirSupportPolicy.c @@ -0,0 +1,79 @@ +// Decisions consume detached HQ memory and delivered friendly check-ins only. +class ERR_AirSupportSituation +{ + int BeliefId; + int Samples; + int Spotted; + int GroundFit; + int CommittedFit; + int ConfirmedLosses; + float Age; + float Confidence; + float Radius; + float Speed; + bool MotionKnown; + bool Infantry; + bool AircraftReady; + bool ArtilleryBusy; +} +class ERR_AirSupportPolicy +{ + int Candidate; + float ConsideringSince = -1; + float NextDrop; + string Reason = "waiting for delivered intelligence"; + static string Refusal(ERR_AirSupportSituation s) + { + if (!s || !s.AircraftReady) return "no ready helicopter passenger load"; + if (!ERR_HQMemoryRules.Finite(s.Age) || !ERR_HQMemoryRules.Finite(s.Confidence) || !ERR_HQMemoryRules.Finite(s.Radius) || !ERR_HQMemoryRules.Finite(s.Speed)) return "invalid memory sample"; + if (s.BeliefId <= 0 || s.Samples < 2 || s.Age < 0 || s.Age > 90 || s.Confidence < 0.7 || s.Confidence > 1 || s.Radius < 0 || s.Radius > 160) return "memory is too uncertain; continue reconnaissance"; + if (!s.Infantry || !s.MotionKnown || s.Speed < 0 || s.Speed > 6) return "target movement does not justify an infantry drop"; + int needed = Math.Clamp(s.Spotted * 2, 4, 12); + if (s.CommittedFit >= needed) return "ground forces already committed in sufficient strength"; + if (s.GroundFit + s.CommittedFit >= needed && s.ConfirmedLosses < 2) return "nearby ground forces can handle this contact"; + if (s.ArtilleryBusy) return "mortar order or shells occupy the approach area"; + return ""; + } + bool Consider(ERR_AirSupportSituation s, float now) + { + if (!ERR_HQMemoryRules.Finite(now) || now < 0) return false; + string refusal = Refusal(s); + if (!refusal.IsEmpty()) { Candidate = 0; + ConsideringSince = -1; + Reason = refusal; + return false; + } + if (now < NextDrop) { Reason = "reinforcement cooldown; retain remaining troops"; + return false; + } + if (Candidate != s.BeliefId || ConsideringSince < 0) { Candidate = s.BeliefId; + ConsideringSince = now; + } + float delay = 45000; + if (s.ConfirmedLosses >= 2) delay = 20000; + if (now - ConsideringSince < delay) { Reason = "confirming persistent contact and ground-force shortfall"; + return false; + } + Reason = "persistent infantry contact exceeds available ground response"; + return true; + } + void Committed(float now) { NextDrop = now + 480000; + Candidate = 0; + ConsideringSince = -1; + } + void Retry(float now) { NextDrop = Math.Max(NextDrop, now + 15000); + Candidate = 0; + ConsideringSince = -1; + } +} + +// One immutable authorization; receiver revalidates memory and physical safety. +class ERR_AirDropOrder +{ + int BeliefId; + int BeliefRevision; + int MessageId; + vector Target; + float ExpiresAt; + ref ERR_HQReport Report; +} diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftAmmo.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftAmmo.c new file mode 100644 index 0000000..c314111 --- /dev/null +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftAmmo.c @@ -0,0 +1,90 @@ +// Aircraft weapons are physical magazines. Only the landed airport service +// calls Service; the covering orbit consumes normal native weapon ammunition. +class ERR_AircraftAmmo +{ + static void Magazines(IEntity entity, array magazines, bool gunsOnly = false) + { + if (!entity || ChimeraCharacter.Cast(entity)) + return; + BaseWeaponManagerComponent manager = BaseWeaponManagerComponent.Cast(entity.FindComponent(BaseWeaponManagerComponent)); + array weapons = {}; + if (manager) + manager.GetWeapons(weapons); + BaseWeaponComponent mounted = BaseWeaponComponent.Cast(entity.FindComponent(BaseWeaponComponent)); + if (mounted && !weapons.Contains(mounted)) + weapons.Insert(mounted); + foreach (BaseWeaponComponent weapon : weapons) + { + if (!weapon || (gunsOnly && weapon.GetWeaponType() != EWeaponType.WT_MACHINEGUN && weapon.GetWeaponType() != EWeaponType.WT_AUTOCANNON)) + continue; + array muzzles = {}; + weapon.GetMuzzlesList(muzzles); + foreach (BaseMuzzleComponent muzzle : muzzles) + { + BaseMagazineComponent magazine = muzzle.GetMagazine(); + if (magazine && !magazines.Contains(magazine)) + magazines.Insert(magazine); + } + } + IEntity child = entity.GetChildren(); + while (child) + { + Magazines(child, magazines, gunsOnly); + child = child.GetSibling(); + } + } + + static bool HasUsableGun(IEntity aircraft) + { + array magazines = {}; + Magazines(aircraft, magazines, true); + foreach (BaseMagazineComponent magazine : magazines) + { + if (magazine.GetAmmoCount() > magazine.GetMaxAmmoCount() * 0.25) + return true; + } + return false; + } + + // Native rocket pods hold projectile entities rather than magazines. + static int ServicePods(IEntity entity, int available) + { + if (!Replication.IsServer() || !entity || available <= 0 || ChimeraCharacter.Cast(entity)) return 0; + int consumed; + SCR_RocketEjectorMuzzleComponent pod = SCR_RocketEjectorMuzzleComponent.Cast(entity.FindComponent(SCR_RocketEjectorMuzzleComponent)); + if (pod && !pod.GetDefaultRocketPrefab().IsEmpty()) + { + for (int barrel = 0; barrel < pod.GetBarrelsCount() && consumed < available; barrel++) + { + if (!pod.CanReloadBarrel(barrel)) continue; + consumed++; + IEntity rocket = ERR_Actors.Spawn(pod.GetDefaultRocketPrefab(), entity.GetOrigin()); + if (!rocket) continue; + pod.ReloadBarrel(barrel, rocket); + if (pod.GetBarrelProjectile(barrel) != rocket && !rocket.GetParent()) ERR_Actors.DeleteSpawned(rocket); + } + } + IEntity child = entity.GetChildren(); + while (child && consumed < available) + { + consumed += ServicePods(child, available - consumed); + child = child.GetSibling(); + } + return consumed; + } + + static int Service(IEntity aircraft, int available) + { + if (!Replication.IsServer() || available <= 0) return 0; + array magazines = {}; + Magazines(aircraft, magazines); + int used; + foreach (BaseMagazineComponent magazine : magazines) + { + int moved = Math.Min(available - used, Math.Max(0, magazine.GetMaxAmmoCount() - magazine.GetAmmoCount())); + magazine.SetAmmoCount(magazine.GetAmmoCount() + moved); + used += moved; + } + return used; + } +} diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_AirfieldSupport.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_AirfieldSupport.c new file mode 100644 index 0000000..d5f2269 --- /dev/null +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_AirfieldSupport.c @@ -0,0 +1,196 @@ +// One physical airport depot and a separate logistics airframe per round. +class ERR_AirfieldSupport +{ + protected ERR_HQ m_HQ; + protected ERR_GameMode m_Mode; + protected IEntity m_Store, m_FuelTruck; + protected ERR_ReconFlightComponent m_Cargo; + protected ref ERR_HQRoute m_ReturnOrder; + protected ERR_ReconFlightComponent m_ReturnFlight; + protected ref ERR_AirAmmoMission m_Mission; + protected ref array m_RetiredMissions = {}; + protected ref array m_SubmittedCargo = {}; + protected float m_ServiceAt = -1, m_NextTick, m_NextAttempt, m_NextDepot; + protected bool m_Started, m_Stopped, m_Serviced; + protected int m_Rounds = 24000, m_Rockets = 512, m_Services, m_Trips; + protected float m_Fuel = 12000; + protected float m_CargoServiceAt = -1, m_NextCargo; + protected int m_CargoAttempts; + protected vector m_Airport; + protected bool m_CargoSpawned, m_CargoServiced; + protected ref map m_Requests = new map(); + bool BlocksMortar(vector point) { return m_Mission && m_Mission.BlocksMortar(point); + } + ERR_ReconFlightComponent Cargo() { return m_Cargo; + } + IEntity Store() { return m_Store; + } + string Status() { return string.Format("Airport: %1 services; gun rounds=%2 fuel=%3; ammo trips=%4 rockets=%5", m_Services, m_Rounds, Math.Round(m_Fuel), m_Trips, m_Rockets); + } + void ERR_AirfieldSupport(ERR_HQ hq, ERR_GameMode mode) { m_HQ = hq; + m_Mode = mode; + } + protected IEntity Spawn(ResourceName prefab, vector point) + { IEntity entity = ERR_Actors.Spawn(prefab, ERR_Actors.Ground(point)); + if (entity) m_Mode.Own(entity); + return entity; + } + protected void Start(vector airport) + { + m_Started = true; + m_Airport = airport; + m_Store = Spawn("{EBBC859CCD94D96D}Prefabs/Props/EmptyStorages/USSR_AmmoBox_empty.et", airport + "35 0 0"); + m_FuelTruck = Spawn("{16C1F16C9B053801}Prefabs/Vehicles/Wheeled/Ural4320/Ural4320_transport.et", airport + "40 0 12"); + if (m_FuelTruck) ERR_Actors.SetFaction(m_FuelTruck, m_Mode.EnemyFaction()); + Spawn("{BE5D5CFA90224646}Prefabs/Structures/Military/Camps/TentUSSR_01/TentUSSR_01_base.et", airport + "35 0 8"); + } + protected void SpawnCargo(float now) + { + if (m_CargoSpawned || m_CargoAttempts >= 3 || now < m_NextCargo || !DepotAvailable()) return; + m_CargoAttempts++; m_NextCargo = now + 30000; + vector pad; + if (!ERR_ReconAirports.FindClearPad(m_Airport, pad) || vector.DistanceXZ(pad, m_Airport) < 30 || m_Mode.Forces().Count() >= 254) return; + m_CargoSpawned = true; + Vehicle aircraft = Vehicle.Cast(Spawn("{C31F210ABE078192}Prefabs/ERR/ReconHelicopter.et", pad)); + if (!aircraft) return; + m_Cargo = ERR_ReconFlightComponent.Cast(aircraft.FindComponent(ERR_ReconFlightComponent)); + if (m_Cargo) m_Cargo.Initialize(m_Mode, pad, 10001, true); + ERR_HQ.Event("AIRFIELD SUPPORT", "physical service depot and separate ammunition helicopter initialized"); + } + bool DepotAvailable() + { return m_Store && m_FuelTruck && ERR_Actors.Alive(m_FuelTruck) && SCR_FactionManager.SGetFaction(m_FuelTruck) == m_Mode.EnemyFaction(); + } + protected void Service(ERR_ReconFlightComponent flight, float now) + { + if (!flight.AtAirport()) { m_ServiceAt = -1; + m_Serviced = false; + return; + } + if (m_Serviced || !DepotAvailable() || flight.Lost() || vector.DistanceXZ(flight.Aircraft().GetOrigin(), m_Airport) > 500) return; + if (m_ServiceAt < 0) { m_ServiceAt = now; + return; + } + if (now - m_ServiceAt < 60000) return; + m_Serviced = true; + m_Services++; + Replenish(flight); + flight.ReloadPassengers(); + ERR_HQ.Event("AIRFIELD SERVICE", Status() + "; original airframe and crew retained"); + } + protected void Replenish(ERR_ReconFlightComponent flight) + { + m_Rounds -= ERR_AircraftAmmo.Service(flight.Aircraft(), m_Rounds); + m_Rockets -= ERR_AircraftAmmo.ServicePods(flight.Aircraft(), m_Rockets); + FuelManagerComponent fuel = FuelManagerComponent.Cast(flight.Aircraft().FindComponent(FuelManagerComponent)); + if (fuel) + { + array nodes = {}; + fuel.GetFuelNodesList(nodes); + foreach (BaseFuelNode node : nodes) + { float amount = Math.Min(m_Fuel, node.GetMaxFuel() - node.GetFuel()); + if (amount > 0) { node.SetFuel(node.GetFuel() + amount); + m_Fuel -= amount; + } } + } + } + protected bool CargoServiced(float now) + { + if (!m_Cargo || !m_Cargo.AtAirport()) { m_CargoServiceAt = -1; m_CargoServiced = false; return false; } + if (m_Trips == 0 || m_CargoServiced) return true; + if (!DepotAvailable()) return false; + if (m_CargoServiceAt < 0) m_CargoServiceAt = now; + if (now - m_CargoServiceAt < 60000) return false; + Replenish(m_Cargo); m_CargoServiced = true; + return true; + } + void Maintain(float now) + { + if (m_Stopped || !Replication.IsServer() || !m_Mode.Active()) return; + if (m_Cargo) m_Cargo.Update(now); + if (m_Mission) m_Mission.Tick(now); + } + void Tick(float now) + { + if (m_Stopped || !Replication.IsServer() || !m_Mode.Active() || now < m_NextTick) return; + m_NextTick = now + 1000; + ERR_ReconFlightComponent recon = m_HQ.Recon().Current(); + if (!m_Started && now >= m_NextDepot) + { + m_NextDepot = now + 30000; + vector airport; + if (m_HQ.Recon().SupportPad(airport)) Start(airport); + } + if (m_Started) SpawnCargo(now); + bool cargoReady = CargoServiced(now); + if (recon) + { + Service(recon, now); + if (m_Serviced && recon.AtAirport() && (!recon.Assault() || !recon.Assault().Preparing())) recon.RestartFlight(); + if (m_ReturnOrder) + { + int delivered = m_ReturnOrder.Advance(now, m_HQ.Journal()); + if (delivered != 0) { if (delivered == 1 && m_ReturnFlight == recon) recon.ReturnHome(); + m_ReturnOrder = null; + m_ReturnFlight = null; + } + } + else if (recon.Assault() && recon.Assault().NeedsService(now) && (recon.Phase() == ERR_ReconPhase.SEARCH || recon.Phase() == ERR_ReconPhase.SHADOW)) + { m_ReturnOrder = m_HQ.Downlink(recon.Crew(), "AIRCRAFT RELOAD", "cover complete; return to airport for another squad and ammunition", 0); + m_ReturnFlight = recon; + } + } + if (!cargoReady || !m_Cargo || m_Cargo.Lost() || !m_Cargo.AtAirport() || !DepotAvailable() || now < m_NextAttempt || m_Trips >= 12) return; + if (m_Mission && (!m_Mission.Finished() || m_Mission.PendingNative())) return; + m_NextAttempt = now + 10000; + ERR_HQUnit recipient = m_HQ.AirAmmoRecipient(now, m_Requests); + if (!recipient) return; + ERR_HQWatchEntry demand = m_HQ.Watch().Find(recipient.ForceSourceId); + if (!demand) return; + m_Trips++; + m_Requests.Set(demand.SourceId, demand.MessageId); + if (m_Mission) m_RetiredMissions.Insert(m_Mission); + m_Mission = new ERR_AirAmmoMission(m_HQ, m_Mode, m_Cargo, recipient, demand.Position, demand.MessageId, m_Trips, m_SubmittedCargo); + } + void Stop() + { + m_Stopped = true; + m_ReturnOrder = null; + if (m_Mission) m_Mission.Stop(); + if (m_Cargo) m_Cargo.Release(false); + } +} +modded class ERR_HQ +{ + bool ReserveAirAmmo(ERR_HQUnit unit, int token) + { + if (!Replication.IsServer() || !MissionActive() || !unit || token <= 0 || !unit.Eligible(m_Mode) || unit.HomeGuard || !unit.Radio || unit.PendingOrder || unit.Downlink || Fighting(unit)) return false; + // Keep its delivered search task until the replacement order actually arrives. + unit.LogisticsReservation = token; + return true; + } + ERR_HQUnit AirAmmoRecipient(float now, map served) + { + foreach (ERR_HQUnit unit : m_Units) + { + ERR_HQWatchEntry request = m_Watch.Find(unit.ForceSourceId); + if (!unit.Eligible(m_Mode) || unit.ReservedForSupport || unit.HomeGuard || unit.LogisticsReservation > 0 || unit.PendingOrder || unit.Downlink || Fighting(unit)) continue; + if (!ERR_InfantryResupplyRules.Need(request, now) || request.MessageId <= served.Get(request.SourceId)) continue; + return unit; + } + return null; + } + ERR_HQRoute SupportUplink(SCR_AIGroup group, string detail) + { + foreach (ERR_HQUnit unit : m_Units) + { + if (unit.Group != group || !unit.Radio || unit.Uplink || OriginOccupied(unit.Radio, unit)) continue; + ERR_HQRoute route = m_Network.Route(unit.Radio); + if (!route) return null; + route.MessageId = m_Journal.Message(); + route.Payload = detail; + m_Journal.Write("SUPPORT REPORT QUEUED", detail, route.MessageId); + return route; + } + return null; + } +} diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_AssaultParachute.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_AssaultParachute.c new file mode 100644 index 0000000..fa6ace1 --- /dev/null +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_AssaultParachute.c @@ -0,0 +1,321 @@ +class ERR_AssaultParachuteClass : ParachuteDeployedEntityClass +{ +} + +// Reuse the framework's canopy, cargo compartment and movement replication. +// AI owns no PlayerController: flight, transfer and landing run on the server. +class ERR_AssaultParachute : ParachuteDeployedEntity +{ + protected ref ERR_AirAssaultTeam m_ERR_Team; + protected IEntity m_ERR_Soldier; + protected IEntity m_ERR_DepartureVehicle; + protected BaseCompartmentSlot m_ERR_DepartureSeat; + protected vector m_vERR_Landing; + protected float m_fERR_TransferDeadline; + protected float m_fERR_NextTransfer; + protected float m_fERR_NextExit; + protected float m_fERR_FlightDeadline; + protected float m_fERR_NextFlightLog; + protected vector m_vERR_LastProgress; + protected float m_fERR_ProgressAt; + protected float m_fERR_EscapeUntil; + protected int m_iERR_EscapeAttempts; + protected vector m_vERR_Escape; + protected bool m_bERR_Started; + protected bool m_bERR_VerticalDescent; + protected bool m_bERR_Transferring; + protected bool m_bERR_DidBoard; + protected bool m_bERR_Finished; + protected bool m_bERR_Broken; + protected bool m_bERR_Cleanup; + + override void EOnInit(IEntity owner) + { + super.EOnInit(owner); + if (SCR_Global.IsEditMode()) + return; + SetFlags(EntityFlags.ACTIVE); + // The framework's generic destruction path deletes its vehicle after + // 100ms. AI must first confirm the native compartment is empty. + if (m_DamageManager) + { + m_DamageManager.GetOnDamage().Remove(OnParachuteDamaged); + m_DamageManager.GetOnDamage().Insert(ERR_OnDamage); + } + } + + bool BeginJump(IEntity soldier, ERR_AirAssaultTeam team, vector landing) + { + if (!Replication.IsServer()) + return false; + m_bERR_Started = true; + m_vERR_LastProgress = GetOrigin(); + m_fERR_ProgressAt = GetGame().GetWorld().GetWorldTime(); + m_ERR_Soldier = soldier; + m_ERR_Team = team; + m_vERR_Landing = landing; + CompartmentAccessComponent access; + if (soldier) + access = CompartmentAccessComponent.Cast(soldier.FindComponent(CompartmentAccessComponent)); + // Physics handles are local-only; reacquire them instead of retaining + // the framework's cached pointer across engine callbacks. + Physics physics = GetPhysics(); + if (!access || !m_Compartment || m_Compartment.IsOccupied() || !physics || !physics.IsDynamic()) + { + m_bERR_Finished = true; + Print("Reintroduced [air assault]: invalid canopy seat/physics; passenger retained", LogLevel.WARNING); + return false; + } + physics.ChangeSimulationState(SimulationState.SIMULATION); + physics.SetActive(ActiveState.ALWAYS_ACTIVE); + m_ERR_DepartureVehicle = CompartmentAccessComponent.GetVehicleIn(soldier); + m_ERR_DepartureSeat = access.GetCompartment(); + m_fERR_TransferDeadline = GetGame().GetWorld().GetWorldTime() + 2000; + m_fERR_FlightDeadline = m_fERR_TransferDeadline + 120000; + m_bERR_Transferring = true; + ERR_AirAssaultLoad.SetLock(soldier, false); + vector exitTransform[4]; + GetWorldTransform(exitTransform); + if (!access.GetOutVehicle_NoDoor(exitTransform, false, true, true)) + { + m_bERR_Transferring = false; + m_bERR_Finished = true; + ERR_AirAssaultLoad.SetLock(soldier, true); + Print("Reintroduced [air assault]: helicopter exit rejected; passenger retained", LogLevel.WARNING); + return false; + } + return true; + } + + protected void ERR_OnDamage(BaseDamageContext damageContext) + { + if (Replication.IsServer() && m_DamageManager && m_DamageManager.IsDestroyed()) + DestroyParachute(); + } + + override void DestroyParachute() + { + if (!Replication.IsServer()) + return; + m_bERR_Broken = true; + // Leave the damaged canopy/occupant to physics until native ejection + // succeeds. Never delete an occupied replicated hierarchy. + AskServerExit(); + } + + protected void ERR_Transfer(float now) + { + CompartmentAccessComponent access = CompartmentAccessComponent.Cast(m_ERR_Soldier.FindComponent(CompartmentAccessComponent)); + if (m_Compartment.GetOccupant() == m_ERR_Soldier) + { + m_bERR_Transferring = false; + m_bERR_DidBoard = true; + m_ERR_DepartureVehicle = null; + m_ERR_DepartureSeat = null; + ERR_AirAssaultLoad.SetLock(m_ERR_Soldier, true); + ERR_HQ.Event("PARACHUTE BOARDED", string.Format("canopy=%1 soldier=%2 position=%3", this, m_ERR_Soldier, GetOrigin())); + return; + } + if (now >= m_fERR_TransferDeadline || !access || !ERR_Actors.CanFight(m_ERR_Soldier)) + { + // If the native transfer fails, try to return the same soldier to + // their original seat. Do not spawn a replacement or delete them. + if (access && !access.IsInCompartment() && m_ERR_DepartureVehicle && m_ERR_DepartureSeat && !m_ERR_DepartureSeat.IsOccupied()) + access.GetInVehicle(m_ERR_DepartureVehicle, m_ERR_DepartureSeat, true, 0, ECloseDoorAfterActions.INVALID, true); + m_bERR_Transferring = false; + m_bERR_Finished = true; + Print("Reintroduced [air assault]: canopy transfer failed; attempted return to original seat", LogLevel.WARNING); + return; + } + if (now >= m_fERR_NextTransfer && !access.IsInCompartment()) + { + m_fERR_NextTransfer = now + 100; + access.GetInVehicle(this, m_Compartment, true, 0, ECloseDoorAfterActions.INVALID, true); + } + } + + override void AskServerExit() + { + if (!Replication.IsServer() || m_bERR_Transferring || !m_Compartment || !m_Compartment.IsOccupied()) + return; + float now = GetGame().GetWorld().GetWorldTime(); + if (now < m_fERR_NextExit) + return; + vector position = GetOrigin(); + float ground = SCR_TerrainHelper.GetTerrainY(position); + if (!m_bERR_Broken && position[1] - ground > 2) + return; + m_fERR_NextExit = now + 1000; + IEntity occupant = m_Compartment.GetOccupant(); + // A GM/player takeover must never be controlled by this AI controller. + if (occupant != m_ERR_Soldier || ERR_Actors.Player(occupant)) + return; + CompartmentAccessComponent access = CompartmentAccessComponent.Cast(occupant.FindComponent(CompartmentAccessComponent)); + if (!access) + return; + vector exitTransform[4]; + GetWorldTransform(exitTransform); + if (!m_bERR_Broken) + exitTransform[3] = Vector(position[0], ground + 0.2, position[2]); + ERR_AirAssaultLoad.SetLock(occupant, false); + access.GetOutVehicle_NoDoor(exitTransform, m_bERR_Broken, true, true); + } + + protected void ERR_Finish() + { + if (m_Compartment && m_Compartment.IsOccupied()) + return; + if (m_bERR_Cleanup) + return; + m_bERR_Finished = true; + ERR_HQ.Event("PARACHUTE FINISHED", string.Format("canopy=%1 soldier=%2 position=%3 boarded=%4 damaged=%5", this, m_ERR_Soldier, GetOrigin(), m_bERR_DidBoard, m_bERR_Broken)); + if (m_ERR_Soldier && CompartmentAccessComponent.GetVehicleIn(m_ERR_Soldier) == null) + { + ERR_AirAssaultLoad.SetLock(m_ERR_Soldier, false); + AIControlComponent control = AIControlComponent.Cast(m_ERR_Soldier.FindComponent(AIControlComponent)); + AIAgent agent; if (control) agent = control.GetControlAIAgent(); + if (agent) + { + agent.SetPermanentLOD(-1); + agent.ActivateAI(); + } + vector position = GetOrigin(); + if (m_bERR_DidBoard && !m_bERR_Broken && position[1] - SCR_TerrainHelper.GetTerrainY(position) < 3 && m_ERR_Team && ERR_Actors.CanFight(m_ERR_Soldier)) + m_ERR_Team.Landed(); + } + SCR_GarbageSystem garbage = SCR_GarbageSystem.GetByEntityWorld(this); + if (garbage) + m_bERR_Cleanup = garbage.Insert(this); + if (m_bERR_Cleanup) + { + Physics physics = GetPhysics(); + if (physics) + physics.SetActive(ActiveState.ACTIVE); + m_ERR_Soldier = null; + m_ERR_Team = null; + ClearEventMask(EntityEvent.FRAME | EntityEvent.SIMULATE); + } + } + + // Transfer, landing and replication must run even if physics was asleep. + // Do not call the parent's frame handler: it installs human input controls. + override void EOnFrame(IEntity owner, float timeSlice) + { + if (!Replication.IsServer() || !m_bERR_Started || !m_Compartment) + return; + float now = GetGame().GetWorld().GetWorldTime(); + if (m_bERR_Transferring && !m_ERR_Soldier) + { + m_bERR_Transferring = false; + m_bERR_Finished = true; + } + if (m_bERR_Transferring && m_ERR_Soldier) + ERR_Transfer(now); + // A native get-in completion can arrive after the timeout tick. + // Resume descent for any late occupant instead of freezing them aloft. + if (m_bERR_Finished && m_Compartment.IsOccupied()) + { + m_bERR_Finished = false; + m_bERR_DidBoard = true; + } + if (m_bERR_Finished || (!m_bERR_Transferring && !m_Compartment.IsOccupied())) + { + ERR_Finish(); + return; + } + if (m_Compartment.IsOccupied() && (m_Compartment.GetOccupant() != m_ERR_Soldier || ERR_Actors.Player(m_Compartment.GetOccupant()))) + return; + Physics physics = GetPhysics(); + if (!physics) + return; + if (physics.GetSimulationState() != SimulationState.SIMULATION) + physics.ChangeSimulationState(SimulationState.SIMULATION); + physics.SetActive(ActiveState.ALWAYS_ACTIVE); + if (m_fERR_FlightDeadline > 0 && now >= m_fERR_FlightDeadline) + { + // A guidance timeout is not canopy damage. Keep the soldier seated + // and descend vertically instead of cutting them loose at altitude. + m_fERR_FlightDeadline = 0; + m_bERR_VerticalDescent = true; + Print("Reintroduced [air assault]: canopy guidance expired; continuing vertical descent", LogLevel.WARNING); + } + vector progressPosition = GetOrigin(); + if (m_bERR_Transferring || vector.Distance(progressPosition, m_vERR_LastProgress) > 2) + { + m_vERR_LastProgress = progressPosition; + m_fERR_ProgressAt = now; + } + else if (!m_bERR_Broken && now - m_fERR_ProgressAt > 5000 && progressPosition[1] - SCR_TerrainHelper.GetTerrainY(progressPosition) > 2) + { + // A roof/tree collision must not eject a soldier at terrain altitude. + // Try a short lateral escape using collision-aware physics, retaining + // the occupied canopy. No teleport, forced damage, or deletion. + int escapeSide = m_iERR_EscapeAttempts++ % 4; + float angle = escapeSide * Math.PI / 2; + m_vERR_Escape = Vector(Math.Cos(angle) * 3, 0, Math.Sin(angle) * 3); + m_fERR_EscapeUntil = now + 5000; + m_fERR_ProgressAt = now; + ERR_HQ.Event("PARACHUTE OBSTRUCTED", string.Format("canopy=%1 soldier=%2 position=%3 lateral attempt=%4", this, m_ERR_Soldier, progressPosition, m_iERR_EscapeAttempts)); + } + AskServerExit(); + if (now >= m_fERR_NextFlightLog) + { + m_fERR_NextFlightLog = now + 10000; + vector position = GetOrigin(); + ERR_HQ.Event("PARACHUTE STATUS", string.Format("canopy=%1 soldier=%2 position=%3 height=%4 velocity=%5 occupied=%6 transferring=%7 damaged=%8", this, m_ERR_Soldier, position, Math.Round(position[1] - SCR_TerrainHelper.GetTerrainY(position)), physics.GetVelocity(), m_Compartment.IsOccupied(), m_bERR_Transferring, m_bERR_Broken)); + } + // Preserve the framework's proxy movement protocol, at five updates + // per second for at most eight canopies per aircraft. + m_NetAccTime += timeSlice; + if (m_NetAccTime >= 0.2) + { + m_NetAccTime = 0; + vector transform[4]; + GetWorldTransform(transform); + Rpc(RpcDo_SyncMovement, transform, physics.GetVelocity(), physics.GetAngularVelocity(), 0.0, 0.0); + } + } + + override void EOnSimulate(IEntity owner, float timeSlice) + { + if (!Replication.IsServer() || !m_bERR_Started || m_bERR_Finished || m_bERR_Broken || !m_Compartment) + return; + if (m_Compartment.IsOccupied() && (m_Compartment.GetOccupant() != m_ERR_Soldier || ERR_Actors.Player(m_Compartment.GetOccupant()))) + return; + if (!m_bERR_Transferring && !m_Compartment.IsOccupied()) + return; + Physics physics = GetPhysics(); + if (!physics) + return; + vector position = GetOrigin(); + vector toward = m_vERR_Landing - position; + toward[1] = 0; + float height = position[1] - SCR_TerrainHelper.GetTerrainY(position); + vector velocity; + if (!m_bERR_VerticalDescent && toward.LengthSq() > 0.01) + velocity = toward.Normalized() * Math.Min(7, toward.Length() * 0.4); + if (GetGame().GetWorld().GetWorldTime() < m_fERR_EscapeUntil) velocity = m_vERR_Escape; + velocity[1] = -5; + if (height < 10) + velocity[1] = -2; + if (m_bERR_Transferring) + velocity = vector.Zero; + // Let physics move the entire occupied hierarchy without resetting its + // transform between fixed steps. + physics.SetAngularVelocity(vector.Zero); + physics.SetVelocity(velocity); + } + + void ~ERR_AssaultParachute() + { + if (m_DamageManager) + m_DamageManager.GetOnDamage().Remove(ERR_OnDamage); + } + + override void EOnDeactivate(IEntity owner) + { + if (m_DamageManager) + m_DamageManager.GetOnDamage().Remove(ERR_OnDamage); + super.EOnDeactivate(owner); + } +} diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_BodyRecovery.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_BodyRecovery.c new file mode 100644 index 0000000..612b0f0 --- /dev/null +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_BodyRecovery.c @@ -0,0 +1,300 @@ +class ERR_BodyRecoveryJob +{ + IEntity Body; + vector Position; + SCR_AIGroup Team; + AIWaypoint Waypoint; + ref ERR_PrisonPatrol Radio = new ERR_PrisonPatrol(); + ref array Missing = {}; + ref ERR_HQRoute Order, Report; + float Started, SearchAt = -1, RetryAt; + int State; + bool Delivered; + float NextDiagnostic; + // 0 native team, 1 radio order, 2 walk/search, 3 evidence uplink, 4 done +} +class ERR_BodyRecovery +{ + protected ERR_HQ m_HQ; + protected ERR_GameMode m_Mode; + protected ref array m_Jobs = {}; + protected ref set m_ReportedBodies = new set(); + protected int m_Waves; + protected float m_NextTick; + protected bool m_Stopped; + void ERR_BodyRecovery(ERR_HQ hq, ERR_GameMode mode) { m_HQ = hq; + m_Mode = mode; + } + string Status() { return string.Format("Recovery: %1/%2 reports searched; teams dispatched=%3/8", Completed(), m_Jobs.Count(), m_Waves); + } + protected int Completed() + { + int count; + foreach (ERR_BodyRecoveryJob job : m_Jobs) { if (job.Delivered) count++; + } + return count; + } + void ReportBody(ERR_HQReport report) + { + if (m_Stopped || !report || !report.Target || m_ReportedBodies.Contains(report.Target) || m_Jobs.Count() >= 128 || !m_Mode.Evidence().Find(report.Target)) return; + ERR_BodyRecoveryJob job = new ERR_BodyRecoveryJob(); + job.Body = report.Target; + job.Position = report.Position; + m_ReportedBodies.Insert(report.Target); + m_Jobs.Insert(job); + ERR_HQ.Event("BODY RECOVERY REQUEST", "delivered body sighting; search ordered at reported position " + job.Position.ToString()); + } + protected bool SpawnTeam(ERR_BodyRecoveryJob job, float now) + { + foreach (ERR_BodyRecoveryJob previous : m_Jobs) + { + if (previous == job || previous.State != 4 || !previous.Team || previous.Team.GetPlayerCount(true) > 0 || previous.Team.GetFaction() != m_Mode.EnemyFaction() || m_Mode.ForceLiving(previous.Team) == 0) continue; + job.Team = previous.Team; + previous.Team = null; + job.State = 1; + job.Started = now; + m_HQ.ReserveGroup(job.Team); + return true; + } + if (m_Waves >= 8 || m_Mode.Forces().Count() >= 254) return false; + array locations = {}; + m_Mode.Locations(locations); + ERR_LocationComponent base; + float best = 1e20; + foreach (ERR_LocationComponent location : locations) + { + if (!location || (location.Kind() != ERR_LocationKind.RADIO && location.Kind() != ERR_LocationKind.DEPOT)) continue; + float distance = vector.DistanceXZ(location.Position(), job.Position); + if (distance < best) { base = location; + best = distance; + } + } + if (!base) return false; + vector point = ERR_Actors.Ground(base.Position() + "20 0 20"); + if (!ERR_HQRoadIntercept.Standable(point)) return false; + // Only reject visible pop-in; these live player positions never choose a search destination. + array players = {}; + ERR_Actors.Players(players); + foreach (IEntity player : players) if (vector.DistanceXZ(player.GetOrigin(), point) < 300) return false; + m_Waves++; + job.Team = SCR_AIGroup.Cast(ERR_Actors.Spawn("{EC9F1AA42D0B7863}Prefabs/ERR/PrisonPatrol.et", point)); + job.Started = now; + if (!job.Team) { job.State = 4; + return false; + } + m_Mode.Own(job.Team); + if (!ERR_PrisonPatrol.Configure(job.Team, m_Mode.FactionSelection().Choice("enemy").Group, m_Mode.EnemyFaction())) { job.State = 4; + return false; + } + ERR_HQ.Event("BODY RECOVERY TEAM", "special search team departing friendly site; bodies remain retained"); + return true; + } + protected void RemoveWaypoint(ERR_BodyRecoveryJob job) + { + if (job.Waypoint) { if (job.Team) job.Team.RemoveWaypoint(job.Waypoint); + ERR_Actors.DeleteSpawned(job.Waypoint); + job.Waypoint = null; + } + } + protected void Finish(ERR_BodyRecoveryJob job, bool delivered) + { + RemoveWaypoint(job); + job.State = 4; + job.Delivered = delivered; + job.Order = null; + job.Report = null; + if (delivered) { m_HQ.CompromisedSites(job.Missing, job.Position); + m_Mode.Evidence().Delivered(job.Body); + } + if (!delivered) m_HQ.ReleaseRecovery(job.Team); + } + void Tick(float now) + { + if (m_Stopped || !Replication.IsServer() || !m_Mode.Active() || now < m_NextTick) return; + m_NextTick = now + 1000; + m_HQ.SecureKnownSites(now); + int active; + foreach (ERR_BodyRecoveryJob existing : m_Jobs) if (existing.Team && existing.State < 4) active++; + foreach (ERR_BodyRecoveryJob job : m_Jobs) + { + if (job.State == 4 || now < job.RetryAt) continue; + if (!job.Body) { Finish(job, false); + continue; + } + if (!job.Team) + { + if (active >= 2) continue; + job.RetryAt = now + 30000; + if (SpawnTeam(job, now)) active++; + continue; + } + if (job.Team.GetPlayerCount(true) > 0 || job.Team.GetFaction() != m_Mode.EnemyFaction() || now - job.Started > 1800000) { Finish(job, false); + continue; + } + job.Team.ActivateAI(); + array activeAgents = {}; + job.Team.GetAgents(activeAgents); + foreach (AIAgent activeAgent : activeAgents) + { + if (!activeAgent) continue; + activeAgent.SetPermanentLOD(0); + activeAgent.ActivateAI(); + } + if (job.State > 0 && m_Mode.ForceLiving(job.Team) == 0) { Finish(job, false); continue; } + if (job.State == 0) + { + if (now - job.Started > 60000) { Finish(job, false); + continue; + } + if (!job.Team.IsExpandComplete() || job.Team.GetAgentsCount() == 0) continue; + ERR_PrepareResult radio = job.Radio.Radio(m_Mode, job.Team, job.Started + 60000); + if (radio != ERR_PrepareResult.READY) continue; + m_Mode.RegisterGroup(job.Team); + ERR_ForceRecord recoveryRecord = m_Mode.Forces().FindGroup(job.Team); + if (recoveryRecord) ERR_HQ.Event("SPAWN PURPOSE", "force=" + recoveryRecord.SourceId + "; purpose=body inspection; position=" + job.Team.GetOrigin().ToString() + "; reported body=" + job.Position.ToString()); + m_HQ.ReserveGroup(job.Team); + job.Team.ActivateAI(); + job.State = 1; + } + if (job.State == 1) + { + if (!job.Order) { job.Order = m_HQ.Downlink(job.Team, "BODY SEARCH", "inspect reported military body " + job.Position.ToString(), 0); + if (!job.Order) continue; + } + int order = job.Order.Advance(now, m_HQ.Journal()); + if (order < 0) { job.Order = null; + job.RetryAt = now + 15000; + continue; + } + if (order == 0) continue; + job.Order = null; + job.Waypoint = AIWaypoint.Cast(ERR_Actors.Spawn(ERR_Resources.MoveWaypoint(), job.Position)); + if (!job.Waypoint) { Finish(job, false); + continue; + } + job.Waypoint.SetCompletionRadius(1.5); + job.Team.AddWaypointAt(job.Waypoint, 0); + job.State = 2; + } + if (job.State == 2) + { + SCR_AIGroupUtilityComponent utility = job.Team.GetGroupUtilityComponent(); + if (utility && utility.m_Perception && !utility.m_Perception.m_aTargets.IsEmpty()) { job.SearchAt = -1; + continue; + } + array agents = {}; + job.Team.GetAgents(agents); + IEntity searcher; + foreach (AIAgent agent : agents) + if (agent && ERR_Actors.CanFight(agent.GetControlledEntity()) && !ERR_Actors.Player(agent.GetControlledEntity()) && vector.Distance(agent.GetControlledEntity().GetOrigin(), job.Body.GetOrigin()) <= 3) searcher = agent.GetControlledEntity(); + if (now >= job.NextDiagnostic) + { + job.NextDiagnostic = now + 30000; + float nearest = 1e20; + foreach (AIAgent nearbyAgent : agents) + if (nearbyAgent && nearbyAgent.GetControlledEntity()) nearest = Math.Min(nearest, vector.Distance(nearbyAgent.GetControlledEntity().GetOrigin(), job.Body.GetOrigin())); + ERR_HQ.Event("BODY SEARCH PROGRESS", "nearest searcher=" + nearest.ToString() + "m; physical inspection required"); + } + if (!searcher) { job.SearchAt = -1; + continue; + } + if (job.SearchAt < 0) job.SearchAt = now; + if (now - job.SearchAt < 10000) continue; + if (!m_Mode.Evidence().Inspect(job.Body, searcher, job.Missing)) continue; + RemoveWaypoint(job); + job.State = 3; + ERR_HQ.Event("BODY SEARCH COMPLETE", "local inspection complete; missing document report awaits radio"); + } + if (job.State == 3) + { + if (!job.Report) { job.Report = m_HQ.SupportUplink(job.Team, "searched body; missing documents=" + job.Missing.Count().ToString()); + if (!job.Report) continue; + } + int receipt = job.Report.Advance(now, m_HQ.Journal()); + if (receipt < 0) { job.Report = null; + job.RetryAt = now + 15000; + } + else if (receipt > 0) Finish(job, true); + } + } + } + void Stop() { m_Stopped = true; + foreach (ERR_BodyRecoveryJob job : m_Jobs) { RemoveWaypoint(job); + job.Order = null; + job.Report = null; + } } +} +modded class ERR_HQ +{ + protected ref map m_Compromised = new map(); + protected float m_NextSecurity; + void SecureKnownSites(float now) + { + if (now < m_NextSecurity) return; + m_NextSecurity = now + 30000; + array sites = {}; + foreach (string id, float until : m_Compromised) if (now < until) sites.Insert(id); + TrySecureSites(sites); + } + void CompromisedSites(array sites, vector bodyPosition) + { + foreach (string id : sites) + { + if (m_Compromised.Count() >= 64 && !m_Compromised.Contains(id)) continue; + m_Compromised.Set(id, GetGame().GetWorld().GetWorldTime() + 1800000); + } + m_NextSecurity = 0; + SecureKnownSites(GetGame().GetWorld().GetWorldTime()); + } + void ReleaseRecovery(SCR_AIGroup group) + { foreach (ERR_HQUnit unit : m_Units) if (unit.Group == group) unit.ReservedForSupport = false; + } + protected void TrySecureSites(array sites) + { + // A missing issued document means the site MAY be compromised. Never read + // player discoveries and never turn this hypothesis into an artillery target. + foreach (string id : sites) + { + array locations = {}; + m_Mode.Locations(locations); + ERR_LocationComponent target; + foreach (ERR_LocationComponent location : locations) if (location.Id() == id) target = location; + if (!target) continue; + bool secured; + foreach (ERR_HQUnit assigned : m_Units) + { + ERR_HQTask assignedTask = assigned.PlannedTask(); + if (assignedTask && assignedTask.SecuritySite == id && GetGame().GetWorld().GetWorldTime() < assignedTask.ExpiresAt) secured = true; + } + if (secured) continue; + ERR_HQ.Event("INTEL COMPROMISE", "missing issued document concerns " + id + "; defensive reinforcement requested"); + ERR_HQUnit best; + float distance = 1e20; + foreach (ERR_HQUnit unit : m_Units) + { + ERR_HQWatchEntry status = m_Watch.Find(unit.ForceSourceId); + if (!unit.Eligible(m_Mode) || unit.HomeGuard || unit.Assignment || unit.PendingOrder || unit.Downlink || Fighting(unit) || !ERR_InfantryResupplyRules.Fresh(status, GetGame().GetWorld().GetWorldTime())) continue; + float candidate = vector.DistanceXZ(status.Position, target.Position()); + if (candidate < distance && candidate < 2500) { best = unit; + distance = candidate; + } + } + if (!best) continue; + ERR_HQRoute route = Downlink(best.Group, "SITE SECURITY", "secure potentially compromised site " + id, 0); + if (!route) continue; + ERR_HQTask task = new ERR_HQTask(); + task.SecuritySite = id; + task.Role = ERR_HQPursuitRole.SEARCH; + task.Destination = target.Position(); + task.QueuedAt = GetGame().GetWorld().GetWorldTime(); + task.ExpiresAt = task.QueuedAt + 600000; + ERR_HQReport lineage = new ERR_HQReport(); + lineage.Position = target.Position(); + lineage.ObservedAt = task.QueuedAt; + lineage.Distress = true; + best.PendingTask = task; + best.PendingOrder = lineage; + best.Downlink = route; + } + } +} diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyBudget.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyBudget.c index 4d35484..327c946 100644 --- a/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyBudget.c +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyBudget.c @@ -13,10 +13,14 @@ class ERR_ConvoyPool { protected ERR_GameMode m_Mode; protected int m_Limit; + protected bool m_Supply; + protected int m_BodyLimit = 60; + protected int m_GroupLimit = 128; protected ref array m_Receipts = {}; - void ERR_ConvoyPool(ERR_GameMode mode, int maxConvoys) + void ERR_ConvoyPool(ERR_GameMode mode, int maxConvoys, bool supply = false) { - m_Mode = mode; m_Limit = Math.Clamp(maxConvoys, 0, 8); + m_Mode = mode; m_Supply = supply; m_Limit = Math.Clamp(maxConvoys, 0, 20); + if (supply) { m_BodyLimit = 60 + 25 * m_Limit; m_GroupLimit = 256; } } static int CrewCount(int vehicle) { @@ -26,6 +30,22 @@ class ERR_ConvoyPool if (vehicle == 0 || vehicle == 3 || vehicle == 5) return 2; return 0; } + int PlannedCount(int index) + { + if (m_Supply && index == 2) return 1; + if (m_Supply && (index == 6 || index == 7)) return 7; + return CrewCount(index); + } + int PlannedBodies() + { + if (m_Supply) return 25; + return 19; + } + int PlannedGroups() + { + if (m_Supply) return 8; + return 6; + } protected bool Current() { return Replication.IsServer() && m_Mode && m_Mode == ERR_GameMode.Get() && m_Mode.Active() && m_Mode.Forces(); @@ -57,25 +77,26 @@ class ERR_ConvoyPool { if (!Current() || sourceId.IsEmpty() || sourceId.Length() > 64) return null; foreach (ERR_ConvoyReceipt known : m_Receipts) if (known.SourceId == sourceId) return known; - if (m_Receipts.Count() >= m_Limit || CommittedBodies() + 19 > 60 || CommittedGroups() + 6 > 128) return null; + if (m_Receipts.Count() >= m_Limit || CommittedBodies() + PlannedBodies() > m_BodyLimit || CommittedGroups() + PlannedGroups() > m_GroupLimit) return null; ERR_ConvoyReceipt receipt = new ERR_ConvoyReceipt(); receipt.Id = m_Receipts.Count() + 1; receipt.SourceId = sourceId; + if (m_Supply) { receipt.OutstandingBodies = 25; receipt.OutstandingGroups = 8; receipt.Records.Insert(-1); receipt.Records.Insert(-1); } m_Receipts.Insert(receipt); return receipt; } bool Consume(ERR_ConvoyReceipt receipt) { - if (!Current() || !Owns(receipt) || receipt.Consumed || CommittedBodies() > 60 || CommittedGroups() > 128) return false; + if (!Current() || !Owns(receipt) || receipt.Consumed || CommittedBodies() > m_BodyLimit || CommittedGroups() > m_GroupLimit) return false; receipt.Consumed = true; return true; } bool BindRecord(ERR_ConvoyReceipt receipt, int vehicle, ERR_ForceRecord record) { - if (!Current() || !Owns(receipt) || !receipt.Consumed || vehicle < 0 || vehicle >= 6 || !record) return false; + if (!Current() || !Owns(receipt) || !receipt.Consumed || vehicle < 0 || vehicle >= PlannedGroups() || !record) return false; if (receipt.Records[vehicle] >= 0) return receipt.Records[vehicle] == record.Id; if (m_Mode.Forces().Find(record.Id) != record || record.Kind != ERR_ForceKind.CONVOY || !record.Group || !record.Physical || record.Eliminated) return false; - if (record.SourceId != receipt.SourceId + "-vehicle-" + vehicle.ToString() || record.InitialStrength != CrewCount(vehicle) || record.Strength != record.InitialStrength) return false; + if (record.SourceId != receipt.SourceId + "-vehicle-" + vehicle.ToString() || record.InitialStrength != PlannedCount(vehicle) || record.Strength != record.InitialStrength) return false; receipt.Records[vehicle] = record.Id; - receipt.OutstandingBodies -= CrewCount(vehicle); receipt.OutstandingGroups--; + receipt.OutstandingBodies -= PlannedCount(vehicle); receipt.OutstandingGroups--; return true; } // There is intentionally no refund/reset method. A consumed startup attempt diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyCombat.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyCombat.c index d1456c6..e92333e 100644 --- a/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyCombat.c +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyCombat.c @@ -8,6 +8,7 @@ class ERR_ConvoyCombatOrder string SourceId; SCR_AIGroup Group; bool Hold; + vector Position; float ObservedAt = -1; float IssuedAt = -1; float ExpiresAt = -1; diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyService.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyService.c index fecbcbf..24a623a 100644 --- a/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyService.c +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_ConvoyService.c @@ -11,7 +11,11 @@ class ERR_ConvoyResources return ""; } static ResourceName GroupPrefab() { return "{7A968AB297475FA7}Prefabs/ERR/ConvoyCrew.et"; } - static ResourceName Soldier() { return "{DCB41B3746FDD1BE}Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_Rifleman.et"; } + static ResourceName Soldier() + { + ERR_GameMode mode = ERR_GameMode.Get(); + if (mode && mode.FactionSelection() && mode.FactionSelection().Ready() && mode.FactionSelection().Active("enemy") != "ussr") return mode.FactionSelection().Soldier(); + return "{DCB41B3746FDD1BE}Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_Rifleman.et"; } static ResourceName Rifle() { return "{FA5C25BF66A53DCF}Prefabs/Weapons/Rifles/AK74/Rifle_AK74.et"; } static ResourceName Magazine() { return "{BBB50A815A2F916B}Prefabs/Weapons/Magazines/Magazine_545x39_AK_30rnd_Ball.et"; } static bool Available() @@ -225,6 +229,18 @@ class ERR_ConvoyService { return !m_Stopped && Replication.IsServer() && m_Mode && m_Mode == ERR_GameMode.Get() && m_Mode.Active() && m_Pool; } + protected ERR_ConvoyTask NewTask() { return new ERR_ConvoyTask(); } + protected ERR_ConvoyVehicle NewVehicle() { return new ERR_ConvoyVehicle(); } + ERR_ConvoyTask At(int index) + { + if (index < 0 || index >= m_Tasks.Count()) return null; + return m_Tasks[index]; + } + ERR_ConvoyTask Find(string source) + { + foreach (ERR_ConvoyTask task : m_Tasks) if (task.Receipt && task.Receipt.SourceId == source) return task; + return null; + } protected bool FillCrew(ERR_ConvoyVehicle unit) { array all = {}; @@ -259,14 +275,13 @@ class ERR_ConvoyService ERR_ConvoyTask Dispatch(ERR_ConvoyReceipt receipt, array positions, array angles, ERR_ForceRoute route, float now) { if (!Current() || !ERR_ForceRules.Finite(now) || now < 0 || !ERR_ConvoyRules.Plan(positions, angles, route) || !ERR_ConvoyResources.Available() || !ERR_ConvoyRules.GroundClear(positions, angles)) return null; - // The selected stock crew and group are USSR. Other factions require a new - // reviewed catalog; never silently rewrite affiliations on incompatible kit. - if (!m_Mode.EnemyFaction() || m_Mode.EnemyFaction().GetFactionKey() != "USSR" || !m_Pool.Consume(receipt)) return null; - ERR_ConvoyTask task = new ERR_ConvoyTask(); task.Receipt = receipt; task.Route = route; task.Deadline = now + 30000; + // The server role selection owns the memberless group affiliation. + if (!m_Mode.EnemyFaction() || !m_Pool.Consume(receipt)) return null; + ERR_ConvoyTask task = NewTask(); task.Receipt = receipt; task.Route = route; task.Deadline = now + 30000; m_Tasks.Insert(task); for (int index = 0; index < 6; index++) { - ERR_ConvoyVehicle unit = new ERR_ConvoyVehicle(); unit.Index = index; task.Vehicles.Insert(unit); + ERR_ConvoyVehicle unit = NewVehicle(); unit.Index = index; task.Vehicles.Insert(unit); unit.Group = SCR_AIGroup.Cast(ERR_Actors.Spawn(ERR_ConvoyResources.GroupPrefab(), positions[index])); if (unit.Group) m_Mode.Own(unit.Group); unit.Entity = Vehicle.Cast(ERR_Actors.Spawn(ERR_ConvoyResources.VehiclePrefab(index), positions[index], angles[index])); @@ -278,7 +293,7 @@ class ERR_ConvoyService AICarMovementComponent movement = AICarMovementComponent.Cast(unit.Entity.FindComponent(AICarMovementComponent)); if (movement) movement.SetCruiseSpeed(35); } - ERR_HQ.Event("CONVOY CREATED", "six physical vehicles and 19 finite crew; native readiness and ledger admission pending"); + ERR_HQ.Event("CONVOY CREATED", "six physical vehicles; finite crew created; native readiness and ledger admission pending"); return task; } protected string ReadinessReason(ERR_ConvoyVehicle unit) diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyEquipment.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyEquipment.c index f8d99e4..0575d5f 100644 --- a/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyEquipment.c +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyEquipment.c @@ -7,12 +7,11 @@ class ERR_EnemyEquipmentRules if (!Replication.IsServer() || SCR_Global.IsEditMode() || !mode || mode != ERR_GameMode.Get() || !mode.Active()) return false; if (!group || !actor || !ERR_Actors.CanFight(actor) || ERR_Actors.Player(actor) || ERR_Actors.Group(actor) != group) return false; SCR_AIGroupUtilityComponent utility = group.GetGroupUtilityComponent(); - return utility && utility.IsMilitary() && group.GetPlayerCount(true) == 0 && group.GetFaction() == mode.EnemyFaction() && !ERR_EnemyGunnerSkill.CapturedGroup(mode, group); + return utility && utility.IsMilitary() && group.GetPlayerCount(true) == 0 && mode.IsMissionEnemy(group.GetFaction()) && !ERR_EnemyGunnerSkill.CapturedGroup(mode, group); } static EAISkill Floor(EAISkill skill) { - if (skill < EAISkill.EXPERT) return EAISkill.EXPERT; - return skill; + return EAISkill.CYLON; } } @@ -158,7 +157,7 @@ class ERR_EnemyEquipment void ERR_EnemyEquipment(ERR_GameMode mode) { m_Mode = mode; } void RegisterGroup(SCR_AIGroup group, int radioId = 0, bool fitRadios = true) { - if (m_Stopped || !Replication.IsServer() || !group || m_Groups.Count() >= 128) return; + if (m_Stopped || !Replication.IsServer() || !group || m_Groups.Count() >= 256) return; foreach (ERR_EnemyEquipmentGroup existing : m_Groups) if (existing.Group == group) return; ERR_EnemyEquipmentGroup state = new ERR_EnemyEquipmentGroup(); state.Group = group; state.ReadyAt = GetGame().GetWorld().GetWorldTime() + 2000; diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyGunnerSkill.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyGunnerSkill.c index c0dfa9c..239b6a8 100644 --- a/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyGunnerSkill.c +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyGunnerSkill.c @@ -2,12 +2,24 @@ // Owned extension and inspected vanilla API provenance: docs/ai-equipment-migration.md. class ERR_EnemyGunnerSkill { + static ERR_ConvoyTask TaskForGroup(ERR_HQ hq, SCR_AIGroup group) + { + if (!hq || !group || !hq.Convoys()) return null; + for (int i = 0; i < hq.Convoys().Count(); i++) + { + ERR_ConvoyTask task = hq.Convoys().At(i); + if (!task || task.Vehicles.Count() > 6) continue; + foreach (ERR_ConvoyVehicle vehicle : task.Vehicles) + if (vehicle && vehicle.Group == group) return task; + } + return null; + } static bool CapturedGroup(ERR_GameMode mode, SCR_AIGroup group) { if (!mode || !group) return false; ERR_HQ hq = ERR_HQ.Cast(mode.Command()); if (!hq) return false; - ERR_ConvoyTask task = hq.ConvoyTask(); + ERR_ConvoyTask task = TaskForGroup(hq, group); if (!task || task.Vehicles.Count() > 6) return false; foreach (ERR_ConvoyVehicle unit : task.Vehicles) if (unit && unit.Group == group && ERR_ConvoyRules.Captured(unit.Entity, group)) return true; @@ -18,7 +30,7 @@ class ERR_EnemyGunnerSkill if (!ERR_EnemyEquipmentRules.Eligible(mode, group, actor)) return false; ERR_HQ hq = ERR_HQ.Cast(mode.Command()); if (!hq) return false; - ERR_ConvoyTask task = hq.ConvoyTask(); + ERR_ConvoyTask task = TaskForGroup(hq, group); if (!task || !task.Ready || task.Stopped || !task.Receipt || !task.Receipt.Consumed || task.Vehicles.Count() > 6 || !mode.Forces()) return false; foreach (ERR_ConvoyVehicle unit : task.Vehicles) { diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyOptics.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyOptics.c index 776d2d7..13ae588 100644 --- a/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyOptics.c +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemyOptics.c @@ -114,6 +114,7 @@ class ERR_EnemyOptics int draw = Math.RandomInt(0, remaining.Count()); int index = remaining[draw]; remaining.Remove(draw); ResourceName prefab = candidates[index]; + if (!mode.Content() || !mode.Content().Allows(prefab)) continue; for (int slotIndex = 0; slotIndex < storage.GetSlotsCount(); slotIndex++) { InventoryStorageSlot slot = storage.GetSlot(slotIndex); diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemySkillAwareness.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemySkillAwareness.c new file mode 100644 index 0000000..457f052 --- /dev/null +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_EnemySkillAwareness.c @@ -0,0 +1,38 @@ +// Mission-owned military AI use maximum decision skill, independently of aim error. +modded class SCR_AICombatComponent +{ + bool ERR_EnhancedEnemy() + { + return m_ERRSkillMode && ERR_EnemyEquipmentRules.Eligible(m_ERRSkillMode, m_ERRSkillGroup, GetOwner()); + } + override void ERR_RefreshEnemySkill() + { + super.ERR_RefreshEnemySkill(); + if (ERR_EnhancedEnemy() && m_Perception && m_Utility && m_Utility.m_ThreatSystem) + UpdatePerceptionFactor(m_Perception, m_Utility.m_ThreatSystem); + } + override void UpdatePerceptionFactor(PerceptionComponent perceptionComp, SCR_AIThreatSystem threatSystem) + { + if (!ERR_EnhancedEnemy()) { super.UpdatePerceptionFactor(perceptionComp, threatSystem); return; } + // Use native alert recognition even while safe/suppressed. Native visibility, + // vegetation, darkness, viewing direction and binocular equipment still apply. + if (perceptionComp) perceptionComp.SetPerceptionFactor(PERCEPTION_FACTOR_ALERTED * m_fEquipmentPerceptionFactor * m_fPerceptionFactor); + } + override void ERR_ReleaseEnemySkill(ERR_GameMode mode) + { + super.ERR_ReleaseEnemySkill(mode); + if (m_Perception && m_Utility && m_Utility.m_ThreatSystem) + UpdatePerceptionFactor(m_Perception, m_Utility.m_ThreatSystem); + } +} + +modded class SCR_AIGetAimErrorOffset +{ + override float GetRandomFactor(EAISkill skill, float mu) + { + // CYLON normally eliminates aim error. Keep the ordinary REGULAR distribution + // for these soldiers while leaving skill-dependent decisions at maximum. + if (m_CombatComponent && m_CombatComponent.ERR_EnhancedEnemy()) skill = EAISkill.REGULAR; + return super.GetRandomFactor(skill, mu); + } +} diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_HQ.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_HQ.c index f1e43fc..c801b82 100644 --- a/addons/core/Scripts/Game/ERR/10_AI/ERR_HQ.c +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_HQ.c @@ -3,6 +3,8 @@ class ERR_HQUnit int Id; SCR_AIGroup Group; SCR_AIGroupUtilityComponent Utility; + SCR_AIGroupPerception Detection; + float NextDetectionLog; IEntity Radio; float NextReport; ref ERR_HQRoute Uplink; @@ -88,6 +90,20 @@ class ERR_HQ : ERR_CommandService protected ERR_GameMode m_Mode; protected ref ERR_MortarSystem m_Mortars; protected ref ERR_EnemyEquipment m_Equipment; + protected ref ERR_HunterService m_Hunters; + protected ref ERR_ObjectiveDefence m_ObjectiveDefence; + protected ref array m_SpecialSkills = {}; + ERR_HunterService Hunters() { return m_Hunters; } + protected ref ERR_ScoutSystem m_Scouts; + protected ref ERR_AirfieldSupport m_Airfield; + ERR_AirfieldSupport Airfield() { return m_Airfield; } + protected ref ERR_BodyRecovery m_Recovery; + ERR_BodyRecovery Recovery() { return m_Recovery; } + protected ref ERR_AirAssaultSystem m_AirAssault; + ERR_AirAssaultSystem AirAssault() { return m_AirAssault; } + protected ref ERR_AirReconSystem m_Recon; + ERR_AirReconSystem Recon() { return m_Recon; } + ERR_ScoutSystem Scouts() { return m_Scouts; } protected ref ERR_ConvoyPool m_ConvoyPool; protected ref ERR_ConvoyService m_Convoys; protected ref ERR_ConvoyTask m_ConvoyTask; @@ -100,6 +116,7 @@ class ERR_HQ : ERR_CommandService protected ref ERR_MortarLogistics m_Logistics; protected ref ERR_InfantryResupply m_Resupply; protected ref ERR_ConvoyStartup m_ConvoyStartup; + protected ref ERR_SupplyConvoySystem m_SupplyConvoys; protected ref array m_Units = {}; protected ref array m_Contacts = {}; protected ref ERR_HQMemory m_Memory = new ERR_HQMemory(); @@ -113,7 +130,42 @@ class ERR_HQ : ERR_CommandService protected float m_NextNetwork; protected float m_NextAssignment; - void ERR_HQ(ERR_GameMode mode) { m_Mode = mode; m_Equipment = new ERR_EnemyEquipment(mode); m_ConvoyPool = new ERR_ConvoyPool(mode, 1); m_Convoys = new ERR_ConvoyService(mode, m_ConvoyPool); m_Mortars = new ERR_MortarSystem(this); m_Logistics = new ERR_MortarLogistics(this, mode); m_Resupply = new ERR_InfantryResupply(this, mode); m_ConvoyStartup = new ERR_ConvoyStartup(mode.Settings().Get("automaticConvoyEnabled") == 1); } + void ERR_HQ(ERR_GameMode mode) + { + m_Mode = mode; + m_Equipment = new ERR_EnemyEquipment(mode); + m_Hunters = new ERR_HunterService(mode, null); + m_ObjectiveDefence = new ERR_ObjectiveDefence(mode, this); + m_Scouts = new ERR_ScoutSystem(mode); + m_Recon = new ERR_AirReconSystem(mode); + m_AirAssault = new ERR_AirAssaultSystem(this, mode); + m_Airfield = new ERR_AirfieldSupport(this, mode); m_Recovery = new ERR_BodyRecovery(this, mode); + bool legacyFixture; +#ifdef WORKBENCH + // These pre-existing diagnostic scenarios specifically exercise the retained + // finite-route controller. Ordinary Workbench sessions use the full fleet. + string fixtureEnabled, fixtureOutcome; + legacyFixture = System.GetCLIParam("errSmoke", fixtureEnabled) && fixtureEnabled == "1" + && System.GetCLIParam("errSmokeOutcome", fixtureOutcome) && (fixtureOutcome == "convoy" || fixtureOutcome == "hq-memory"); +#endif + if (legacyFixture) + { + m_ConvoyPool = new ERR_ConvoyPool(mode, 1); + m_Convoys = new ERR_ConvoyService(mode, m_ConvoyPool); + } + else + { + int convoyCount = mode.Settings().Runtime("convoyCount"); + m_ConvoyPool = new ERR_ConvoyPool(mode, convoyCount, true); + ERR_SupplyConvoyService supply = new ERR_SupplyConvoyService(mode, m_ConvoyPool); + m_Convoys = supply; + m_SupplyConvoys = new ERR_SupplyConvoySystem(mode, m_ConvoyPool, supply, convoyCount, mode.Settings().Get("automaticConvoyEnabled") == 1); + } + m_Mortars = new ERR_MortarSystem(this); + m_Logistics = new ERR_MortarLogistics(this, mode); + m_Resupply = new ERR_InfantryResupply(this, mode); + m_ConvoyStartup = new ERR_ConvoyStartup(mode.Settings().Get("automaticConvoyEnabled") == 1); + } static ERR_HQ Get() { ERR_GameMode mode = ERR_GameMode.Get(); @@ -134,6 +186,7 @@ class ERR_HQ : ERR_CommandService ERR_ConvoyPool ConvoyPool() { return m_ConvoyPool; } ERR_ConvoyService Convoys() { return m_Convoys; } ERR_ConvoyTask ConvoyTask() { return m_ConvoyTask; } + ERR_SupplyConvoySystem SupplyConvoys() { return m_SupplyConvoys; } bool PrepareConvoy(vector seed) { if (!Replication.IsServer() || !MissionActive() || m_ConvoyTask) return false; @@ -188,6 +241,12 @@ class ERR_HQ : ERR_CommandService protected void AutomaticConvoy(float now) { if (!Replication.IsServer() || !m_Mode || m_Mode != ERR_GameMode.Get() || !m_Mode.Active()) return; + if (m_SupplyConvoys) + { + m_SupplyConvoys.Tick(now, ConvoyAdmissionReady()); + if (!m_ConvoyTask && m_Convoys.Count() > 0) m_ConvoyTask = m_Convoys.At(0); + return; + } if (!m_ConvoyStartup || m_ConvoyStartup.Finished()) return; string previous = m_ConvoyStartup.Status(); if (m_ConvoyStartup.Decide(now, m_ConvoyTask != null, ConvoyAdmissionReady())) @@ -197,6 +256,13 @@ class ERR_HQ : ERR_CommandService } bool StartScenarioConvoy() { + if (m_SupplyConvoys) + { + if (!ConvoyAdmissionReady()) return false; + bool started = m_SupplyConvoys.StartOne(); + if (!m_ConvoyTask && m_Convoys.Count() > 0) m_ConvoyTask = m_Convoys.At(0); + return started; + } if (!m_Mode || !m_Mode.Sites()) return false; ERR_SiteRuntime site = m_Mode.Sites().Find("everon-supply-1"); if (!site || !site.Definition) return false; @@ -205,7 +271,8 @@ class ERR_HQ : ERR_CommandService string ConvoyStatus() { string detail = m_Convoys.Status(); - if (m_ConvoyStartup) detail += "; automatic startup: " + m_ConvoyStartup.Status(); + if (m_SupplyConvoys) detail += "; " + m_SupplyConvoys.Status(); + else if (m_ConvoyStartup) detail += "; automatic startup: " + m_ConvoyStartup.Status(); if (!m_ConvoyFailure.IsEmpty()) detail += "; " + m_ConvoyFailure; return detail; } @@ -219,9 +286,45 @@ class ERR_HQ : ERR_CommandService if (unit.Group != group) continue; ReleaseUnit(unit, GetGame().GetWorld().GetWorldTime()); unit.ReservedForSupport = true; + m_Journal.Write("ROLE RESERVED", string.Format("group=%1 force=%2 home=%3; excluded from general HQ retasking", unit.Id, unit.ForceSourceId, unit.HomeId)); + } + } + void Dedicate(SCR_AIGroup group, string siteId) + { + ReserveGroup(group); + foreach (ERR_HQUnit unit : m_Units) + if (unit.Group == group) { unit.HomeId = siteId; unit.HomeGuard = true; } + } + protected void Detected(SCR_AIGroup group, SCR_AITargetInfo target) + { + if (!Replication.IsServer() || !m_Mode.Active() || m_Mode.Phase() <= ERR_Phase.PRISON || !group || !target || !target.m_Entity) return; + float now = GetGame().GetWorld().GetWorldTime(); + foreach (ERR_HQUnit unit : m_Units) + { + if (unit.Group != group) continue; + unit.NextReport = 0; + // Native combat reacts locally now; remote orders still require radio delivery. + group.ActivateAI(); + if (now >= unit.NextDetectionLog) + { + unit.NextDetectionLog = now + 10000; + m_Journal.Write("CONTACT LOCAL", string.Format("group=%1 force=%2 observed=%3 home=%4 dedicated=%5; native combat active, radio report due", unit.Id, unit.ForceSourceId, target.m_vWorldPos, unit.HomeId, unit.ReservedForSupport)); + } } } // Temporary reservations never alter the permanent support reservation. + void ReleaseMortarCrew(SCR_AIGroup group) + { + ERR_MortarBattery battery = m_Mortars.FindGroup(group); + if (!battery) return; + if (battery.Gun) + { + DamageManagerComponent damage = DamageManagerComponent.Cast(battery.Gun.FindComponent(DamageManagerComponent)); + if (!damage || !damage.IsDestroyed()) return; + } + foreach (ERR_HQUnit unit : m_Units) + if (unit.Group == group) unit.ReservedForSupport = false; + } int LogisticsToken(SCR_AIGroup group) { foreach (ERR_HQUnit unit : m_Units) if (unit.Group == group) return unit.LogisticsReservation; @@ -316,7 +419,7 @@ class ERR_HQ : ERR_CommandService ERR_HQJournal Journal() { return m_Journal; } string Status() { - return string.Format("HQ: %1 groups, %2 delivered contacts, %3 assignments", m_Units.Count(), m_Contacts.Count(), Assigned()) + string.Format("; %1 remembered tracks, %2 swept cells", m_Memory.Count(), m_Coverage.Count()) + "; " + m_Mode.Forces().Status() + "; " + m_Mortars.Status() + "; " + m_Logistics.Status() + "; " + m_Resupply.Status(); + return string.Format("HQ: %1 groups, %2 delivered contacts, %3 assignments", m_Units.Count(), m_Contacts.Count(), Assigned()) + string.Format("; %1 remembered tracks, %2 swept cells; aggression=%3/30 identified bodies=%4; ", m_Memory.Count(), m_Coverage.Count(), m_Watch.Aggression(), m_Watch.IdentifiedBodies()) + m_Hunters.Status() + "; " + m_Mode.Forces().Status() + "; " + m_Mortars.Status() + "; " + m_Logistics.Status() + "; " + m_Resupply.Status() + "; " + m_Recon.Status(); } protected void BindPhysical(ERR_HQUnit unit) @@ -328,11 +431,42 @@ class ERR_HQ : ERR_CommandService if (!unit.StatusSampler.Bound()) unit.StatusSampler.Bind(unit.Group, record.SourceId, record.InitialStrength, m_Mode.EnemyFaction()); if (unit.StatusSampler.Bound()) m_Bodies.RegisterGroup(unit.Group, unit.StatusSampler); } + protected void BindSpecialSkills(SCR_AIGroup group) + { + array specialists = {}; group.GetAgents(specialists); + foreach (AIAgent specialist : specialists) + { + if (!specialist || !specialist.GetControlledEntity()) continue; + SCR_AICombatComponent combat = SCR_AICombatComponent.Cast(specialist.GetControlledEntity().FindComponent(SCR_AICombatComponent)); + if (!combat) continue; + combat.ERR_BindEnemySkill(m_Mode, group); + if (!m_SpecialSkills.Contains(combat)) m_SpecialSkills.Insert(combat); + } + } + protected void AuditGroup(ERR_HQUnit unit) + { + SCR_AIGroup group = unit.Group; + string factionKey; + if (group.GetFaction()) factionKey = group.GetFaction().GetFactionKey(); + m_Journal.Write("REGISTER", string.Format("group=%1 force=%2 faction=%3 position=%4 members=%5 home=%6 dedicated=%7; policy=maximum skill/regular aim/alert recognition", unit.Id, unit.ForceSourceId, factionKey, group.GetOrigin(), m_Mode.ForceLiving(group), unit.HomeId, unit.ReservedForSupport)); + array auditAgents = {}; group.GetAgents(auditAgents); + foreach (AIAgent auditAgent : auditAgents) + { + if (!auditAgent || !auditAgent.GetControlledEntity()) continue; + IEntity actor = auditAgent.GetControlledEntity(); + string prefab; if (actor.GetPrefabData()) prefab = actor.GetPrefabData().GetPrefabName(); + m_Journal.Write("SPAWN MEMBER", string.Format("group=%1 force=%2 actor=%3 prefab=%4 position=%5", unit.Id, unit.ForceSourceId, actor, prefab, actor.GetOrigin())); + } + } + override void RegisterGroup(SCR_AIGroup group) { if (!Replication.IsServer() || !group) return; + // Other hostile factions retain their own intelligence, but receive the same + // scoped skill/aim profile. Do not share enemy HQ knowledge across hostile sides. + if (m_Mode.IsMissionEnemy(group.GetFaction()) && group.GetFaction() != m_Mode.EnemyFaction()) m_Equipment.RegisterGroup(group, 0, false); foreach (ERR_HQUnit known : m_Units) if (known.Group == group) { BindPhysical(known); return; } - if (m_Units.Count() >= 128) return; + if (m_Units.Count() >= 256) return; SCR_AIGroupUtilityComponent utility = SCR_AIGroupUtilityComponent.Cast(group.FindComponent(SCR_AIGroupUtilityComponent)); if (!utility || group.GetFaction() != m_Mode.EnemyFaction()) return; ERR_HQUnit unit = new ERR_HQUnit(); @@ -345,16 +479,25 @@ class ERR_HQ : ERR_CommandService if (home) { unit.HomeId = home.Definition.Id; + // Objective security is permanent; it can report contacts but cannot be tasked + // with searches, reinforcements, resupply or courier work away from its site. + unit.ReservedForSupport = ERR_ObjectiveDefence.Objective(home.Definition.Kind); unit.HomeGuard = !home.Definition.Patrol || home.Definition.Patrol.IsEmpty(); } int phase = unit.Id % 5; unit.NextReport = GetGame().GetWorld().GetWorldTime() + phase * 1000; m_Units.Insert(unit); - m_Equipment.RegisterGroup(group, unit.Id, !m_Mortars || !m_Mortars.FindGroup(group)); + // Scouts keep their observation post and authored sniper/radio loadout. + if ((m_Scouts && m_Scouts.Contains(group)) || (m_Recon && m_Recon.Owns(group)) || (m_Airfield && m_Airfield.Cargo() && m_Airfield.Cargo().Crew() == group)) + { + unit.ReservedForSupport = true; + BindSpecialSkills(group); + } + else m_Equipment.RegisterGroup(group, unit.Id, !m_Mortars || !m_Mortars.FindGroup(group)); BindPhysical(unit); unit.NextStatus = GetGame().GetWorld().GetWorldTime() + 10000 + phase * 1000; unit.AmmoReporting.Initialize(unit.Id, GetGame().GetWorld().GetWorldTime()); - m_Journal.Write("REGISTER", string.Format("group %1", unit.Id)); + AuditGroup(unit); } override void UnregisterGroup(SCR_AIGroup group) @@ -363,6 +506,7 @@ class ERR_HQ : ERR_CommandService foreach (ERR_HQUnit unit : m_Units) { if (unit.Group != group) continue; + if (unit.Detection) { unit.Detection.GetOnEnemyDetected().Remove(Detected); unit.Detection = null; } ReleaseUnit(unit, GetGame().GetWorld().GetWorldTime()); unit.Group = null; unit.Utility = null; @@ -443,7 +587,7 @@ class ERR_HQ : ERR_CommandService protected void Observe(ERR_HQUnit unit, float now) { if (!unit.Utility || unit.Uplink || now < unit.NextReport) return; - unit.NextReport = now + m_Mode.Settings().Get("reportIntervalSeconds") * 1000; + unit.NextReport = now + m_Mode.Settings().Runtime("reportIntervalSeconds") * 1000; array samples = {}; ERR_HQObservation.Gather(unit.Utility, now, samples); if (samples.IsEmpty()) return; @@ -572,7 +716,7 @@ class ERR_HQ : ERR_CommandService if (!m_Watch.InvestigationDue(entry.SourceId, now)) continue; ERR_HQUnit best; ERR_HQRoute bestRoute; - float distance = m_Mode.Settings().Get("responseRadiusMetres") + 1; + float distance = m_Mode.Settings().Runtime("responseRadiusMetres") + 1; int first = -1; int second = -1; foreach (ERR_HQUnit existing : m_Units) @@ -616,7 +760,10 @@ class ERR_HQ : ERR_CommandService // Delivered scalar body evidence survives native corpse cleanup during radio transit. // Memory still applies its own entity-identity rules; casualty accounting needs no live target. if (ERR_HQMemoryRules.Kind(report) == ERR_HQMemoryKind.BODY && m_Watch.IngestBody(report, now)) - m_Bodies.ConfirmDelivered(report.Target); + { + m_Bodies.ConfirmDelivered(report.Target); m_Recovery.ReportBody(report); + m_Journal.Write("AGGRESSION", string.Format("identified source=%1 slot=%2 bodies=%3 aggression=%4/30 hunter allowance=%5/15", report.CasualtySourceId, report.CasualtySlot, m_Watch.IdentifiedBodies(), m_Watch.Aggression(), m_Watch.HunterTarget()), report.MessageId); + } if (!m_Memory.Ingest(report, now)) return; if (ERR_HQMemoryRules.Kind(report) == ERR_HQMemoryKind.SIGHTING) m_Coverage.Forget(report.Position); m_Journal.Write("BELIEF", string.Format("delivered report M%1 retained; tracks=%2", report.MessageId, m_Memory.Count()), report.MessageId); @@ -659,7 +806,7 @@ class ERR_HQ : ERR_CommandService { ERR_HQTask task = unit.PendingTask; unit.CancelPending(); - if (!task || task.ReleaseOnly) return; + if (!task || task.ReleaseOnly || !task.SecuritySite.IsEmpty()) return; if (task.Investigation()) { FinishWatch(task, now); return; } foreach (ERR_HQUnit other : m_Units) { @@ -687,7 +834,7 @@ class ERR_HQ : ERR_CommandService { if (!WatchTaskValid(task)) { LostOrder(unit, now); return; } } - else + else if (task.SecuritySite.IsEmpty()) { ERR_HQBelief belief = m_Memory.GetById(task.BeliefId); if (!belief || belief.BeliefRevision != task.BeliefRevision @@ -699,7 +846,7 @@ class ERR_HQ : ERR_CommandService int deliveryId; if (unit.Downlink) deliveryId = unit.Downlink.MessageId; ResourceName waypointResource = ERR_Resources.SearchWaypoint(); - if (task.RoadIntercept) waypointResource = ERR_Resources.DefendWaypoint(); + if (task.RoadIntercept || !task.SecuritySite.IsEmpty()) waypointResource = ERR_Resources.DefendWaypoint(); AIWaypoint waypoint = AIWaypoint.Cast(ERR_Actors.Spawn(waypointResource, ERR_Actors.Ground(task.Destination))); if (!waypoint) { LostOrder(unit, now); m_Journal.Write("ORDER FAILED", "waypoint spawn failed", order.MessageId); return; } unit.Release(); @@ -718,7 +865,7 @@ class ERR_HQ : ERR_CommandService protected void Sweep(ERR_HQUnit unit, float now) { ERR_HQTask task = unit.Task; - if (!task || task.RoadIntercept || !unit.Assignment || task.SweepQueued || !unit.Waypoint || !unit.Eligible(m_Mode)) return; + if (!task || !task.SecuritySite.IsEmpty() || task.RoadIntercept || !unit.Assignment || task.SweepQueued || !unit.Waypoint || !unit.Eligible(m_Mode)) return; if (Fighting(unit) || vector.DistanceXZ(unit.Group.GetOrigin(), task.Destination) > 40) { task.ArrivedAt = -1; return; } // Quiet combat state alone does not establish a negative search. Use this @@ -866,8 +1013,12 @@ class ERR_HQ : ERR_CommandService } protected void PlanConvoy(float now) { - if (!m_ConvoyTask || m_ConvoyTask.Stopped || !m_ConvoyTask.Ready) return; - foreach (ERR_ConvoyVehicle vehicle : m_ConvoyTask.Vehicles) + for (int i = 0; i < m_Convoys.Count(); i++) PlanConvoyTask(m_Convoys.At(i), now); + } + protected void PlanConvoyTask(ERR_ConvoyTask task, float now) + { + if (!task || task.Stopped || !task.Ready) return; + foreach (ERR_ConvoyVehicle vehicle : task.Vehicles) { if (vehicle.Released || vehicle.Arrived || vehicle.SupplyToken > 0 || !vehicle.Registered || !vehicle.Group) continue; foreach (ERR_HQUnit unit : m_Units) @@ -880,11 +1031,11 @@ class ERR_HQ : ERR_CommandService if (vehicle.Combat.Held && contact.MessageId == vehicle.Combat.ReportId) break; if (contact.ObservedAt < vehicle.Combat.ObservedAt) break; } - else if (!vehicle.Combat.Held || now - vehicle.Combat.ObservedAt < 60000) break; + else if (vehicle.Combat.ReportId <= 0 || !vehicle.Combat.Held || now - vehicle.Combat.ObservedAt < 60000) break; ERR_HQRoute route = m_Network.Route(unit.Radio, true); if (!route) break; ERR_ConvoyCombatOrder order = new ERR_ConvoyCombatOrder(); - order.CommandId = m_Journal.Message(); order.SourceId = m_ConvoyTask.Receipt.SourceId; + order.CommandId = m_Journal.Message(); order.SourceId = task.Receipt.SourceId; order.VehicleIndex = vehicle.Index; order.Group = unit.Group; order.Hold = contact != null; order.IssuedAt = now; order.ExpiresAt = now + 30000; order.ReportId = vehicle.Combat.ReportId; order.ObservedAt = vehicle.Combat.ObservedAt; @@ -913,7 +1064,11 @@ class ERR_HQ : ERR_CommandService // starve a slower radio downlink. New threat evidence always invalidates RESUME. bool current = !order.Hold && !contact; if (order.Hold && contact) current = contact.ObservedAt >= order.ObservedAt; - if (current) accepted = m_Convoys.ApplyCombatOrder(m_ConvoyTask, order, now); + if (current) + { + if (contact && order.Hold) order.Position = contact.Position; + accepted = m_Convoys.ApplyCombatOrder(m_Convoys.Find(order.SourceId), order, now); + } } if (accepted) m_Journal.Write("CONVOY ORDER DELIVERED", "original crew applied radio travel command", order.CommandId); else if (order) m_Journal.Write("CONVOY ORDER REJECTED", "stale evidence or unavailable original crew; current order retained", order.CommandId); @@ -922,9 +1077,9 @@ class ERR_HQ : ERR_CommandService protected void Assign(float now) { - int globalLimit = m_Watch.SquadLimit(m_Mode.Settings().Get("supportSquadLimit")); + int globalLimit = m_Watch.SquadLimit(m_Mode.Settings().Runtime("supportSquadLimit")); int limit = ERR_HQPursuitRules.Limit(globalLimit); - int radius = m_Mode.Settings().Get("responseRadiusMetres"); + int radius = m_Mode.Settings().Runtime("responseRadiusMetres"); int assigned = Assigned(); int roadQueries; // Snapshot bounded own-force eligibility once per five-second planning pass. @@ -944,8 +1099,8 @@ class ERR_HQ : ERR_CommandService if (!unit.PlanEligible || assigned > globalLimit) { FinishWatch(unit.Task, now); FinishWatch(unit.PendingTask, now); unit.Release(); assigned--; continue; } if (unit.Task && now >= unit.Task.ExpiresAt) { FinishWatch(unit.Task, now); unit.ReleaseAssignment(); } if (unit.PendingTask && now >= unit.PendingTask.ExpiresAt) { FinishWatch(unit.PendingTask, now); unit.CancelPending(); } - if (unit.Task && !unit.Task.Investigation() && !m_Memory.GetById(unit.Task.BeliefId)) unit.ReleaseAssignment(); - if (unit.PendingTask && !unit.PendingTask.ReleaseOnly && !unit.PendingTask.Investigation() && !m_Memory.GetById(unit.PendingTask.BeliefId)) unit.CancelPending(); + if (unit.Task && unit.Task.SecuritySite.IsEmpty() && !unit.Task.Investigation() && !m_Memory.GetById(unit.Task.BeliefId)) unit.ReleaseAssignment(); + if (unit.PendingTask && !unit.PendingTask.ReleaseOnly && unit.PendingTask.SecuritySite.IsEmpty() && !unit.PendingTask.Investigation() && !m_Memory.GetById(unit.PendingTask.BeliefId)) unit.CancelPending(); } assigned = Assigned(); m_HomeAvailable.Clear(); @@ -1039,11 +1194,27 @@ class ERR_HQ : ERR_CommandService } } + override void Maintain(float now) + { + // Aircraft already airborne keep flying even when the server is empty. + m_Recon.Tick(now); + m_AirAssault.Maintain(now); + m_Airfield.Maintain(now); + } override void Tick(float now) { if (!Replication.IsServer()) return; m_Memory.Tick(now); m_Equipment.Tick(now); + foreach (SCR_AICombatComponent specialSkill : m_SpecialSkills) + { + if (!specialSkill) continue; + SCR_AIGroup specialGroup = ERR_Actors.Group(specialSkill.GetOwner()); + if (ERR_EnemyEquipmentRules.Eligible(m_Mode, specialGroup, specialSkill.GetOwner())) specialSkill.ERR_BindEnemySkill(m_Mode, specialGroup); + else specialSkill.ERR_ReleaseEnemySkill(m_Mode); + } + m_Hunters.Tick(now); + m_ObjectiveDefence.Tick(now); m_Convoys.Tick(now); AutomaticConvoy(now); m_Bodies.TickBudget(now); @@ -1053,6 +1224,11 @@ class ERR_HQ : ERR_CommandService for (int i = m_Units.Count() - 1; i >= 0; i--) { ERR_HQUnit unit = m_Units[i]; + if (!unit.Detection && unit.Utility && unit.Group) + { + unit.Detection = unit.Utility.m_Perception; + if (unit.Detection) unit.Detection.GetOnEnemyDetected().Insert(Detected); + } if (unit.Uplink) { int delivered = unit.Uplink.Advance(now, m_Journal); @@ -1084,12 +1260,23 @@ class ERR_HQ : ERR_CommandService m_Resupply.Tick(now); m_Logistics.Tick(now); m_Mortars.Tick(now); + m_AirAssault.Tick(now); + m_Airfield.Tick(now); m_Recovery.Tick(now); m_Journal.Flush(); } override void Stop() { + m_Hunters.Stop(); m_ObjectiveDefence.Stop(); + foreach (SCR_AICombatComponent specialSkill : m_SpecialSkills) if (specialSkill) specialSkill.ERR_ReleaseEnemySkill(m_Mode); + m_SpecialSkills.Clear(); + foreach (ERR_HQUnit detector : m_Units) if (detector.Detection) detector.Detection.GetOnEnemyDetected().Remove(Detected); + m_Airfield.Stop(); m_Recovery.Stop(); + m_AirAssault.Stop(); + m_Recon.Stop(); + m_Scouts.Stop(); m_ConvoyStartup.Stop(); + if (m_SupplyConvoys) m_SupplyConvoys.Stop(); m_Resupply.Stop(); m_Convoys.Stop(); m_Equipment.Stop(); diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_HQAdminProvider.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_HQAdminProvider.c index 8a69603..05bcec6 100644 --- a/addons/core/Scripts/Game/ERR/10_AI/ERR_HQAdminProvider.c +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_HQAdminProvider.c @@ -45,7 +45,7 @@ class ERR_HQAdminProvider : ERR_AdminProvider protected void ConvoyAutoSetting(ERR_GameMode mode, array parts, array replies) { string key = "automaticConvoyEnabled"; - string effect = "Applies next round only; current startup and manual convoy start unchanged. At most one finite initial convoy; losses are not replaced."; + string effect = "Applies next round only; current startup and manual convoy start unchanged. The saved convoy count determines the finite initial fleet; losses are not replaced."; string range = "0 disabled, 1 enabled (default)"; if (parts.Count() == 4 && parts[3] == "show") { replies.Insert(key + "=" + mode.Settings().Get(key).ToString() + " saved for next round. " + effect); return; } @@ -55,8 +55,38 @@ class ERR_HQAdminProvider : ERR_AdminProvider else if (parts.Count() == 4 && parts[3] == "help") replies.Insert(range + ". " + effect); else replies.Insert("Invalid value or settings could not be saved; previous setting retained. " + range + ". " + effect); } + protected void CountSetting(ERR_GameMode mode, string arguments, array replies) + { + array countParts = {}; arguments.Split(" ", countParts, true); + int offset = 1; + if (countParts[0] == "hq") offset = 3; + if (countParts.Count() == offset || (countParts.Count() == offset + 1 && countParts[offset] == "show")) + replies.Insert("Convoy count saved for next round: " + ERR_Settings.SelectionText(mode.Settings().Get("convoyCount")) + ". " + m_HQ.ConvoyStatus()); + else + { + int count; + if (countParts.Count() == offset + 2 && countParts[offset] == "set" && ERR_CommandArguments.Selection("convoyCount", countParts[offset + 1], count) && mode.Settings().Set("convoyCount", count)) + replies.Insert("Convoy count saved for next round: " + ERR_Settings.SelectionText(count) + "; current convoys unchanged."); + else replies.Insert("Use convoys show|set 0..20|random. Changes apply next round; lost convoys never respawn."); + } + } override bool Execute(ERR_GameMode mode, string arguments, array replies) { + if (arguments == "hq heli show") { replies.Insert(m_HQ.Recon().Status() + "; " + m_HQ.AirAssault().Status() + "; " + m_HQ.Airfield().Status() + "; " + m_HQ.Recovery().Status()); return true; } + if (arguments == "hq heli return") { m_HQ.Recon().Return(); replies.Insert(m_HQ.Recon().Status() + "; " + m_HQ.AirAssault().Status() + "; " + m_HQ.Airfield().Status() + "; " + m_HQ.Recovery().Status()); return true; } + if (arguments.IndexOf("hq heli timer set ") == 0) + { + array timerParts = {}; arguments.Split(" ", timerParts, true); + int minutes; + if (timerParts.Count() == 5 && ERR_CommandArguments.Integer(timerParts[4], minutes) && m_HQ.Recon().SetDelay(minutes)) replies.Insert(m_HQ.Recon().Status() + "; " + m_HQ.AirAssault().Status() + "; " + m_HQ.Airfield().Status() + "; " + m_HQ.Recovery().Status()); + else replies.Insert("Use /esc hq heli timer set 1..1440 (minutes). Save failure preserves the current countdown."); + return true; + } + if (arguments == "convoys" || arguments.IndexOf("convoys ") == 0 || arguments == "hq convoy count" || arguments.IndexOf("hq convoy count ") == 0) + { + CountSetting(mode, arguments, replies); + return true; + } if (arguments == "hq convoy auto" || arguments.IndexOf("hq convoy auto ") == 0) { if (!m_HQ) { replies.Insert("HQ unavailable."); return true; } @@ -91,10 +121,11 @@ class ERR_HQAdminProvider : ERR_AdminProvider override bool Help(string topic, array replies) { if (topic != "hq") return false; + replies.Insert("/esc convoys show|set 0..20|random | hq convoy count show|set N (default three; next round)"); replies.Insert("/esc hq show | hq memory | hq log show|next|set on|off | hq convoy show|start"); replies.Insert("/esc hq interval|squads|radius|stinger show|set N | hq convoy auto show|set 0|1|help"); replies.Insert("Stinger: 0 off, 1 every eligible soldier, 2..10000 one in N; applies only before each actor rolls."); - replies.Insert("Convoy auto defaults to 1; saves apply next round only. Auto and manual start share one finite initial deployment; losses are not replaced."); + replies.Insert("Convoy auto: default 1, next round, finite fleet. /esc hq heli show | hq heli timer set 1..1440 | hq heli return"); return true; } } diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_HQBodyObserver.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_HQBodyObserver.c index 20eb3d2..e79fc16 100644 --- a/addons/core/Scripts/Game/ERR/10_AI/ERR_HQBodyObserver.c +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_HQBodyObserver.c @@ -79,7 +79,7 @@ class ERR_HQBodyObserver foreach (ERR_HQBodyScan scan : m_Groups) if (scan.Group == group) known = true; if (!known) { - if (m_Groups.Count() >= 128) { Cap(); return; } + if (m_Groups.Count() >= 256) { Cap(); return; } ERR_HQBodyScan created = new ERR_HQBodyScan(); created.Group = group; m_Groups.Insert(created); } @@ -91,7 +91,7 @@ class ERR_HQBodyObserver bool found; foreach (ERR_HQBodyCandidate entry : m_Roster) if (entry.Corpse == actor) found = true; if (found) continue; - if (m_Roster.Count() >= 128) { Cap(); return; } + if (m_Roster.Count() >= 4096) { Cap(); return; } ERR_HQBodyCandidate candidate = new ERR_HQBodyCandidate(); candidate.Corpse = actor; candidate.Roster = sampler; candidate.SourceId = sampler.InitialSourceId(); candidate.Slot = member; candidate.Strength = sampler.InitialStrength(); diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_HQCoverage.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_HQCoverage.c index 7614b86..04c68a7 100644 --- a/addons/core/Scripts/Game/ERR/10_AI/ERR_HQCoverage.c +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_HQCoverage.c @@ -79,8 +79,8 @@ class ERR_HQCoverage report.BeliefRevision, report.SweepCompleted, report.ContactFound, report.ObservedAt, now)) return false; if (m_Messages.Contains(report.SourceId) && report.MessageId <= m_Messages.Get(report.SourceId)) return false; // One uplink per source gives monotonic message order. Never evict replay - // watermarks; the mission already caps its total physical formations at 128. - if (!m_Messages.Contains(report.SourceId) && m_Messages.Count() >= 128) return false; + // watermarks; the mission already caps its total physical formations at 256. + if (!m_Messages.Contains(report.SourceId) && m_Messages.Count() >= 256) return false; m_Messages.Set(report.SourceId, report.MessageId); int key = ERR_HQCoverageRules.Key(report.Position); if (m_Cells.Contains(key) && m_Cells.Get(key) >= report.ObservedAt) return false; diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_HQObservation.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_HQObservation.c index 0f02471..fab1c58 100644 --- a/addons/core/Scripts/Game/ERR/10_AI/ERR_HQObservation.c +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_HQObservation.c @@ -7,6 +7,7 @@ class ERR_HQVisualContact bool Escapist; string Travel = "unknown"; string Weapon = "unknown"; + string RoadSurface = "road unknown"; } class ERR_HQObservation @@ -52,6 +53,7 @@ class ERR_HQObservation seen.Entity = entity; seen.Position = target.GetLastSeenPosition(); seen.ObservedAt = now - target.GetTimeSinceSeen() * 1000; + seen.RoadSurface = ERR_ScoutRoad.Describe(seen.Position); SCR_ChimeraCharacter character = SCR_ChimeraCharacter.Cast(entity); if (character) { @@ -117,6 +119,7 @@ class ERR_HQObservation existing.ObservedAt = seen.ObservedAt; existing.Travel = seen.Travel; existing.Weapon = seen.Weapon; + existing.RoadSurface = seen.RoadSurface; } } } @@ -126,6 +129,7 @@ class ERR_HQObservation // New observations must not silently inherit old equipment/travel details. report.SeenEscapists = -1; report.TravelMode = "unknown"; + report.RoadStatus = "road unknown"; report.SeenWeapons = "unknown"; report.DetailsObservedAt = -1; if (report.Distress) @@ -143,6 +147,9 @@ class ERR_HQObservation return; report.DetailsObservedAt = anchor.ObservedAt; report.TravelMode = anchor.Travel; + report.RoadStatus = anchor.RoadSurface; + ERR_HQ hq = ERR_HQ.Get(); + if (hq && hq.Scouts()) hq.Scouts().DescribeMotion(report); report.SeenWeapons = anchor.Weapon; array counted = {}; array weapons = {}; diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_HQReport.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_HQReport.c index 85a7720..c727960 100644 --- a/addons/core/Scripts/Game/ERR/10_AI/ERR_HQReport.c +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_HQReport.c @@ -51,6 +51,7 @@ class ERR_HQReport bool Distress; int SeenEscapists = -1; string TravelMode = "unknown"; + string RoadStatus = "road unknown"; // Original formation identity captured by the local observer, only used after radio delivery. string CasualtySourceId; int CasualtySlot = -1; @@ -72,6 +73,7 @@ class ERR_HQReport copy.HasVelocity = HasVelocity; copy.SeenEscapists = SeenEscapists; copy.TravelMode = TravelMode; + copy.RoadStatus = RoadStatus; copy.CasualtySourceId = CasualtySourceId; copy.CasualtySlot = CasualtySlot; copy.CasualtyStrength = CasualtyStrength; @@ -118,7 +120,7 @@ class ERR_HQReport int heading = Math.Round(azimuth); motion = string.Format("%1 km/h, azimuth %2 degrees (%3)", Math.Round(speed * 3.6), heading % 360, TravelDirection()); } - string details = count + "; " + TravelMode + "; " + motion + "; seen weapons: " + SeenWeapons; + string details = count + "; " + TravelMode + "; " + RoadStatus + "; " + motion + "; seen weapons: " + SeenWeapons; if (brief) return details; string velocity = "unknown"; diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_HQTask.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_HQTask.c index 4b6605b..2bf68ec 100644 --- a/addons/core/Scripts/Game/ERR/10_AI/ERR_HQTask.c +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_HQTask.c @@ -1,6 +1,7 @@ // A radio order snapshots an inference. It never refreshes the source sighting. class ERR_HQTask { + string SecuritySite; bool ReleaseOnly; bool RoadIntercept; ref ERR_HQTask ReplacesTask; @@ -19,6 +20,7 @@ class ERR_HQTask int ApproachBearing = -1; string Name() { + if (!SecuritySite.IsEmpty()) return "secure compromised site " + SecuritySite; if (Investigation()) return "investigate missing patrol"; if (RoadIntercept) return "temporary infantry road interception"; if (Role == ERR_HQPursuitRole.INTERCEPT) return "intercept"; diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_HQWatch.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_HQWatch.c index a1f278f..5bdaafa 100644 --- a/addons/core/Scripts/Game/ERR/10_AI/ERR_HQWatch.c +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_HQWatch.c @@ -17,6 +17,8 @@ class ERR_HQStatusReport class ERR_HQWatchRules { + static int Aggression(int identifiedBodies) { return Math.Clamp(identifiedBodies / 3, 0, 30); } + static int Hunters(int aggression) { return (Math.Clamp(aggression, 0, 30) + 1) / 2; } static bool Valid(ERR_HQStatusReport report, float now) { if (!report || report.SourceId.IsEmpty() || report.SourceId.Length() > 96 || report.MessageId <= 0) @@ -66,6 +68,7 @@ class ERR_HQWatchEntry int ConfirmedLosses; ref ERR_HQAmmoSnapshot AmmoState; ref ERR_HQDeliveredCasualties Casualties = new ERR_HQDeliveredCasualties(); + ref array IdentifiedSlots = {}; float LastBodyDeliveredAt = -1; float ObservedAt = -1; float LastDeliveredAt = -1; @@ -80,6 +83,10 @@ class ERR_HQWatch protected ref array m_Entries = {}; protected ref map m_BySource = new map(); protected int m_ConfirmedLosses; + protected int m_IdentifiedBodies; + int IdentifiedBodies() { return m_IdentifiedBodies; } + int Aggression() { return ERR_HQWatchRules.Aggression(m_IdentifiedBodies); } + int HunterTarget() { return ERR_HQWatchRules.Hunters(Aggression()); } protected bool m_CapLogged; int Count() { return m_Entries.Count(); } ERR_HQWatchEntry Find(string sourceId) { return m_BySource.Get(sourceId); } @@ -102,9 +109,9 @@ class ERR_HQWatch protected ERR_HQWatchEntry Create(string sourceId, int strength) { // Closed identities remain tombstones: replays cannot recreate a formation. - if (m_Entries.Count() >= 128) + if (m_Entries.Count() >= 256) { - if (!m_CapLogged) Print("Reintroduced [watch]: 128-formation check-in cap reached."); + if (!m_CapLogged) Print("Reintroduced [watch]: 256-formation check-in cap reached."); m_CapLogged = true; return null; } @@ -164,6 +171,9 @@ class ERR_HQWatch if (entry && (entry.Strength != report.CasualtyStrength || now < entry.LastBodyDeliveredAt)) return false; if (!entry) entry = Create(report.CasualtySourceId, report.CasualtyStrength); if (!entry || !entry.Casualties.AcceptBody(report.CasualtySlot)) return false; + if (entry.IdentifiedSlots.Contains(report.CasualtySlot)) return false; + entry.IdentifiedSlots.Insert(report.CasualtySlot); + m_IdentifiedBodies++; entry.LastBodyDeliveredAt = now; ApplyLosses(entry); return true; @@ -211,6 +221,6 @@ class ERR_HQWatch } void Clear() { - m_Entries.Clear(); m_BySource.Clear(); m_ConfirmedLosses = 0; m_CapLogged = false; + m_Entries.Clear(); m_BySource.Clear(); m_ConfirmedLosses = 0; m_IdentifiedBodies = 0; m_CapLogged = false; } } diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_HunterService.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_HunterService.c new file mode 100644 index 0000000..aad73fa --- /dev/null +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_HunterService.c @@ -0,0 +1,173 @@ +class ERR_HunterVehicle : ERR_ConvoyVehicle +{ + string Source; + float Deadline; + float NextOrder; + ref ERR_HQRoute Downlink; + vector Destination; + int SourceMessage; + override void Release(ERR_GameMode mode) + { + if (Released) return; + if (!mode || !mode.Active() || ERR_ConvoyRules.Captured(Entity, Group)) { super.Release(mode); return; } + Released = true; Downlink = null; ClearOrder(); + ERR_ForceRecord record = mode.Forces().FindGroup(Group); + if (record) record.Pinned = false; + if (Group) + { + Group.SetPermanentLOD(-1); + array agents = {}; Group.GetAgents(agents); + foreach (AIAgent agent : agents) if (agent) agent.SetPermanentLOD(-1); + ERR_HQ hq = ERR_HQ.Cast(mode.Command()); + if (hq) hq.ReleaseRecovery(Group); + } + // Surviving original crew remain registered for skill, reports, intel and + // local combat. Only the driving task ends; on-foot survivors can serve HQ. + } +} + +// An escalation allowance of fifteen physical hunter UAZs, separate from supply +// convoys. Losses remain physical; aggression never replenishes killed crews. +class ERR_HunterService : ERR_ConvoyService +{ + protected ref array m_Hunters = {}; + protected float m_NextHunter; + protected float m_NextSpawn; + protected int m_Target; + int Deployed() { return m_Hunters.Count(); } + int ActiveHunters() + { + int count; + foreach (ERR_HunterVehicle unit : m_Hunters) if (!unit.Released) count++; + return count; + } + override string Status() { return string.Format("aggression UAZs: %1 active, %2/%3 deployed allowance (maximum 15)", ActiveHunters(), Deployed(), m_Target); } + protected bool StartHunter(ERR_HQ hq, float now) + { + if (m_Hunters.Count() >= m_Target || m_Hunters.Count() >= 15 || m_Mode.Forces().Count() >= 250) return false; + array players = {}; ERR_Actors.Players(players); + ERR_ConvoyPlacement placement = new ERR_ConvoyPlacement(); + for (int i = 0; i < m_Mode.Sites().Count(); i++) + { + ERR_SiteRuntime site = m_Mode.Sites().At((i + m_Hunters.Count()) % m_Mode.Sites().Count()); + if (!site || !site.Definition || (site.Definition.Kind != ERR_LocationKind.RADIO && site.Definition.Kind != ERR_LocationKind.DEPOT && site.Definition.Kind != ERR_LocationKind.OUTPOST)) continue; + if (site.Group && site.Group.GetFaction() != m_Mode.EnemyFaction()) continue; + vector position, angles; + vector seed = site.Definition.Position + Vector(Math.RandomFloat(-200, 200), 0, Math.RandomFloat(-200, 200)); + if (!ERR_SupplyConvoySystem.ApproachDirected(seed, position, angles) || !placement.Clear(position, angles[0])) continue; + bool nearPlayer; + foreach (IEntity player : players) if (player && vector.DistanceXZ(player.GetOrigin(), position) < 400) nearPlayer = true; + if (nearPlayer) continue; + ERR_HunterVehicle unit = new ERR_HunterVehicle(); + unit.Source = "aggression-uaz-" + (m_Hunters.Count() + 1).ToString(); + unit.Deadline = now + 30000; m_Hunters.Insert(unit); + unit.Group = SCR_AIGroup.Cast(ERR_Actors.Spawn(ERR_ConvoyResources.GroupPrefab(), position)); + unit.Entity = Vehicle.Cast(ERR_Actors.Spawn(ERR_ConvoyResources.VehiclePrefab(0), position, angles)); + if (unit.Group) m_Mode.Own(unit.Group); + if (unit.Entity) m_Mode.Own(unit.Entity); + if (!unit.Group || !unit.Entity || !ERR_ConvoyRules.EmptyCrewTemplate(unit.Group) || !FillCrew(unit)) + { unit.Release(m_Mode); ERR_HQ.Event("HUNTER FAILED", unit.Source + " native vehicle/crew spawn failed; allowance consumed"); return false; } + FactionAffiliationComponent affiliation = FactionAffiliationComponent.Cast(unit.Entity.FindComponent(FactionAffiliationComponent)); + if (affiliation) affiliation.SetAffiliatedFaction(m_Mode.EnemyFaction()); + AICarMovementComponent movement = AICarMovementComponent.Cast(unit.Entity.FindComponent(AICarMovementComponent)); + if (movement) movement.SetCruiseSpeed(45); + ERR_HQ.Event("HUNTER SPAWN", string.Format("%1 reason=identified bodies %2 aggression=%3/30 allowance=%4/15 base=%5 position=%6 crew=%7", unit.Source, hq.Watch().IdentifiedBodies(), hq.Watch().Aggression(), m_Target, site.Definition.Id, position, unit.Members.Count())); + return true; + } + ERR_HQ.Event("HUNTER WAIT", "deployment deferred: friendly road obstructed, occupied, budget full or players within 400m"); + return false; + } + protected bool AdmitHunter(ERR_HunterVehicle unit, ERR_HQ hq, float now) + { + if (!unit.CrewValid(m_Mode)) return false; + array agents = {}; unit.Group.GetAgents(agents); + if (agents.Count() != unit.Members.Count()) return false; + foreach (AIAgent agent : agents) if (!agent || !unit.Members.Contains(agent.GetControlledEntity()) || !ERR_Actors.CanFight(agent.GetControlledEntity())) return false; + SCR_AIGroupUtilityComponent utility = unit.Group.GetGroupUtilityComponent(); + SCR_AIVehicleUsageComponent usage = SCR_AIVehicleUsageComponent.Cast(unit.Entity.FindComponent(SCR_AIVehicleUsageComponent)); + if (!utility || !utility.m_VehicleMgr || !usage || !utility.m_VehicleMgr.TryAddVehicle(usage)) return false; + ERR_ForceRecord record = m_Mode.Forces().Register(unit.Source, ERR_ForceKind.CONVOY, unit.Entity.GetOrigin(), unit.Members.Count(), null, unit.Group, now); + if (!record) return false; + record.Pinned = true; unit.Registered = true; + m_Mode.RegisterGroup(unit.Group); hq.ReserveGroup(unit.Group); + utility.AddUsableVehicle(usage); unit.Group.SetPermanentLOD(0); unit.Group.ActivateAI(); + foreach (AIAgent active : agents) { active.SetPermanentLOD(0); active.ActivateAI(); } + ERR_HQ.Event("HUNTER READY", unit.Source + " driver and gunner seated; HQ radio registration active"); + return true; + } + protected void QueueDestination(ERR_HunterVehicle unit, ERR_HQ hq, float now) + { + if (now < unit.NextOrder || unit.Downlink) return; + unit.NextOrder = now + 30000; + array reports = {}; hq.SupportContacts(reports, now); + ERR_HQBelief best; + foreach (ERR_HQReport report : reports) + { + ERR_HQBelief belief = hq.Memory().Get(report.Target); + if (belief && belief.Actionable() && (!best || belief.ObservedAt > best.ObservedAt)) best = belief; + } + vector destination, angles; + string reason = "road patrol between friendly objectives"; + unit.SourceMessage = 0; + if (best) + { + if (!ERR_SupplyConvoySystem.ApproachDirected(best.PredictedPosition, destination, angles, 500)) return; + unit.SourceMessage = best.MessageId; reason = "intercept last delivered sighting; confidence=" + best.Confidence.ToString(); + } + else + { + if (unit.Waypoint && !unit.Waypoint.IsWithinCompletionRadius(unit.Group)) return; + bool found; + for (int i = 0; i < m_Mode.Sites().Count(); i++) + { + ERR_SiteRuntime site = m_Mode.Sites().At(Math.RandomInt(0, m_Mode.Sites().Count())); + if (!site || !site.Definition || !ERR_ObjectiveDefence.Objective(site.Definition.Kind) || (site.Group && site.Group.GetFaction() != m_Mode.EnemyFaction())) continue; + if (ERR_SupplyConvoySystem.ApproachDirected(site.Definition.Position, destination, angles) && vector.DistanceXZ(destination, unit.Entity.GetOrigin()) > 200) { found = true; break; } + } + if (!found) return; + } + unit.Destination = destination; + unit.Downlink = hq.Downlink(unit.Group, "HUNTER", unit.Source + " " + reason + " destination=" + destination.ToString(), unit.SourceMessage); + } + override void Tick(float now) + { + if (m_Stopped || !Replication.IsServer() || !m_Mode || !m_Mode.Active() || m_Mode != ERR_GameMode.Get() || m_Mode.Phase() <= ERR_Phase.PRISON || now < m_NextHunter) return; + m_NextHunter = now + 1000; + ERR_HQ hq = ERR_HQ.Cast(m_Mode.Command()); if (!hq) return; + m_Target = hq.Watch().HunterTarget(); + if (now >= m_NextSpawn && Deployed() < m_Target) { m_NextSpawn = now + 30000; StartHunter(hq, now); } + foreach (ERR_HunterVehicle unit : m_Hunters) + { + if (unit.Released) continue; + if (ERR_ConvoyRules.Captured(unit.Entity, unit.Group)) { unit.Release(m_Mode); ERR_HQ.Event("HUNTER RELEASE", unit.Source + " player captured vehicle/crew; orders removed"); continue; } + if (!unit.Registered) + { + if (AdmitHunter(unit, hq, now)) continue; + if (now >= unit.Deadline) { InspectReadiness(unit, now); unit.Release(m_Mode); ERR_HQ.Event("HUNTER FAILED", unit.Source + " native readiness timed out"); } + continue; + } + if (!unit.CrewValid(m_Mode)) { unit.Release(m_Mode); ERR_HQ.Event("HUNTER RELEASE", unit.Source + " vehicle or original crew no longer operational; no replacement spawn"); continue; } + if (unit.Downlink) + { + int delivered = unit.Downlink.Advance(now, hq.Journal()); + if (delivered != 0) + { + if (delivered > 0) + { + unit.ClearOrder(); + unit.Waypoint = AIWaypoint.Cast(ERR_Actors.Spawn(ERR_Resources.MoveWaypoint(), unit.Destination)); + if (unit.Waypoint) { unit.Waypoint.SetCompletionRadius(50); unit.Group.AddWaypoint(unit.Waypoint); } + ERR_HQ.Event("HUNTER ORDER", unit.Source + " radio delivered; destination=" + unit.Destination.ToString(), unit.SourceMessage); + } + unit.Downlink = null; + } + } + QueueDestination(unit, hq, now); + } + } + override void Stop() + { + m_Stopped = true; + foreach (ERR_HunterVehicle unit : m_Hunters) { unit.Downlink = null; unit.Release(m_Mode); } + } +} diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoAccess.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoAccess.c index b5a6155..3208af0 100644 --- a/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoAccess.c +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoAccess.c @@ -16,12 +16,15 @@ class ERR_InfantryAmmoAccess ActionsManagerComponent manager = ActionsManagerComponent.Cast(donor.FindComponent(ActionsManagerComponent)); if (!manager || !manager.IsEnabled()) return false; array contexts = {}; manager.GetContextList(contexts); - if (contexts.IsEmpty() || contexts.Count() > 64) return false; + // The stock Mi-8 alone authors 82 root contexts. Keep a finite bound + // that includes its real cargo-door action as well as ordinary trucks. + if (contexts.IsEmpty() || contexts.Count() > 128) return false; foreach (UserActionContext context : contexts) { if (!context) return false; array actions = {}; context.GetActionsList(actions); - if (actions.Count() > 16) return false; + // Native Mi-8 cargo-door context has 38 actions (including seat switches). + if (actions.Count() > 64) return false; bool storage; foreach (BaseUserAction action : actions) if (action && action.GetOwner() == donor && SCR_OpenVehicleStorageAction.Cast(action)) storage = true; diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoTransfer.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoTransfer.c index 1a1a663..86c3a65 100644 --- a/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoTransfer.c +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoTransfer.c @@ -148,7 +148,8 @@ class ERR_InfantryAmmoTransfer float speed = physics.GetVelocity().Length(); float angular = physics.GetAngularVelocity().Length(); float distance = vector.Distance(m_Donor.GetOrigin(), m_Recipient.GetOrigin()); - if (!(speed >= 0 && speed <= 0.25 && angular >= 0 && angular <= 0.1 && distance >= 0 && distance <= 4)) return false; + if (!(speed >= 0 && speed <= 0.25 && angular >= 0 && angular <= 0.1 && distance >= 0 && distance <= 15)) return false; + if (distance > 4 && !m_Donor.FindComponent(VehicleHelicopterSimulation)) return false; if (!Compatible(m_Recipient, m_Magazine)) return false; m_Driver = driver; m_DonorRecord = donorRecord; m_RecipientRecord = recipientRecord; return true; diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c index ffd082a..9f46788 100644 --- a/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryResupply.c @@ -81,7 +81,7 @@ class ERR_InfantryResupply || !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]; + && m_Convoy.Receipt.Records.Count() >= 6 && record.Id == m_Convoy.Receipt.Records[1]; } protected bool Quiet(ERR_HQUnit unit) { diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarBattery.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarBattery.c index f1a40f8..ffdef0b 100644 --- a/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarBattery.c +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarBattery.c @@ -37,6 +37,7 @@ class ERR_MortarBattery ref ERR_MortarRefresh Refresh; bool RefreshRejected; // latched through an already committed projectile protected ref ERR_MortarReadiness m_Readiness; + protected ref ERR_MortarStation m_Station; protected ref ERR_MortarSupplyTransfer m_Transfer; protected ref array m_AttemptedShells = {}; protected bool m_Stopped; @@ -316,6 +317,7 @@ class ERR_MortarBattery m_Stopped = true; Cancel("HQ stopped"); if (m_Readiness) m_Readiness.Stop(); + if (m_Station) m_Station.Stop(); } ERR_MortarSupplyState SupplyState(float now) @@ -515,6 +517,7 @@ class ERR_MortarBattery void Update(float now) { if (m_Stopped) return; + if (m_Station) m_Station.Update(now); if (!StartupActivated) { if (!SpawnFailure.IsEmpty()) return; @@ -522,6 +525,8 @@ class ERR_MortarBattery ERR_MortarSupplyState startup = m_Readiness.Poll(now); if (startup != ERR_MortarSupplyState.READY) return; StartupActivated = true; + m_Station = new ERR_MortarStation(this); + m_Station.Update(now); } if (m_Transfer) m_Transfer.Poll(now); if (!Operational()) diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarLogistics.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarLogistics.c index 8c3d42d..b551c84 100644 --- a/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarLogistics.c +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarLogistics.c @@ -15,7 +15,7 @@ class ERR_MortarLogisticsRules static bool Near(float distance) { return distance >= 0 && distance <= 12; } static bool ActiveTrip(bool server, bool stopped, int trip, int current, bool fresh, bool ownershipValid) { return server && !stopped && trip > 0 && trip == current && fresh && ownershipValid; } } -// One finite western-cache courier, owned and ticked exclusively by HQ. +// One finite depot courier shared by the authored batteries, owned and ticked by HQ. class ERR_MortarLogistics { protected ERR_HQ m_HQ; @@ -94,11 +94,14 @@ class ERR_MortarLogistics m_Started = true; ERR_ScenarioComponent scenario = ERR_ScenarioComponent.Cast(m_Mode.FindComponent(ERR_ScenarioComponent)); if (!scenario || !scenario.Sites()) return false; + // The retired vehicle-cache fixture retains its original courier source. + // Production uses the existing guard outpost; no replacement car/cache is created. m_Site = scenario.Sites().Find("everon-supply-2"); + if (!m_Site) m_Site = scenario.Sites().Find("everon-outpost-1"); if (!m_Site || !m_Site.Group || !m_Site.PatrolCycle || !scenario.Sites().Owns(m_Site.Container)) return false; m_Cache = m_Site.Container; m_Group = m_Site.Group; array batteries = {}; m_HQ.Mortars().Batteries(batteries); - if (batteries.Count() != 1) return false; + if (batteries.IsEmpty()) return false; m_Battery = batteries[0]; m_OriginalGun = m_Battery.Gun; m_OriginalBatteryGroup = m_Battery.Group; InventoryStorageManagerComponent inventory = Inventory(m_Cache); if (!inventory || !inventory.CanInsertResource(ERR_MortarBattery.SHELL, EStoragePurpose.PURPOSE_DEPOSIT)) return false; @@ -125,6 +128,27 @@ class ERR_MortarLogistics } return true; } + // Select only between trips. A pending radio report or native item transfer + // keeps its original battery identity and cannot be retargeted in flight. + protected void SelectBattery() + { + if (m_State != 1 || m_Report || m_Move || m_Order) return; + if (m_Battery && TargetAvailable() && ERR_MortarLogisticsRules.Need(m_Battery.CountShells())) return; + array batteries = {}; m_HQ.Mortars().Batteries(batteries); + ERR_MortarBattery selected; + float nearest = float.MAX; + foreach (ERR_MortarBattery candidate : batteries) + { + if (!candidate.StartupActivated || candidate.Stopped() || !candidate.Operational() || !ERR_MortarLogisticsRules.Need(candidate.CountShells())) continue; + float distance = vector.DistanceXZ(m_Cache.GetOrigin(), candidate.Position); + if (distance >= nearest) continue; + nearest = distance; selected = candidate; + } + if (!selected || selected == m_Battery) return; + m_Battery = selected; m_OriginalGun = selected.Gun; m_OriginalBatteryGroup = selected.Group; + m_BatteryMembers.Clear(); + m_NextReport = 0; + } protected bool OriginalGroup() { if (!m_Site || m_Site.Group != m_Group || m_Site.Container != m_Cache || !m_Group || !m_Cache || m_Group.GetPlayerCount(true) > 0 || m_Group.GetFaction() != m_Mode.EnemyFaction()) return false; @@ -294,11 +318,12 @@ class ERR_MortarLogistics foreach (IEntity originalShell : m_Stock) if (!originalShell || !shells.Contains(originalShell)) failed = true; if (m_Stock.Count() != INITIAL_SHELLS) failed = true; if (failed) { Audit("STARTUP FAILED", "one-time native stock allocation incomplete; no refill"); Stop(); return; } - m_State = 1; Audit("READY", "12 distinct original HE shells physically confirmed in existing western cache"); + m_State = 1; Audit("READY", "12 distinct original HE shells physically confirmed in existing depot cache"); } if (m_State == 1) { if (m_Move) { m_Move.Poll(now); if (m_Move.Unresolved()) return; m_Move = null; } + SelectBattery(); if (!OriginalGroup() || !BindBatteryMembers() || !TargetAvailable()) return; bool available; foreach (IEntity stocked : m_Stock) if (Contains(m_Cache, stocked) && !m_AttemptedPickup.Contains(stocked)) available = true; if (!available) return; @@ -307,7 +332,7 @@ class ERR_MortarLogistics int nextTrip = m_Trip + 1; if (!m_HQ.ReserveLogistics(m_Group, nextTrip)) return; m_Trip = nextTrip; m_ConsumedMessage = m_Report.MessageId; - m_Order = m_HQ.Downlink(m_Group, "MORTAR SUPPLY", "collect finite western-cache HE; walk to reported battery", m_Report.MessageId); + m_Order = m_HQ.Downlink(m_Group, "MORTAR SUPPLY", "collect finite depot HE; walk to reported battery", m_Report.MessageId); m_State = 2; if (!m_Order) { Finish("no native courier downlink"); return; } Audit("QUEUED", "original patrol reserved pending physical radio command delivery"); diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSalvo.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSalvo.c index 1a4a07b..9bcf031 100644 --- a/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSalvo.c +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSalvo.c @@ -2,7 +2,7 @@ class ERR_MortarSalvo { static const int ROUNDS = 8; - static const float RADIUS_METRES = 40; + static const float RADIUS_METRES = 80; static const float TIMEOUT_MS = 120000; static vector Offset(int site, int order, int shot) diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarStation.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarStation.c new file mode 100644 index 0000000..2602a99 --- /dev/null +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarStation.c @@ -0,0 +1,126 @@ +// A permanent assignment to the original physical gun, independent of fire orders. +class ERR_MortarStation +{ + protected ERR_MortarBattery m_Battery; + protected ref array m_Controllers = {}; + protected ref SCR_AIGetInVehicle m_Mount; + protected IEntity m_Gunner; + protected float m_NextMount; + protected bool m_Stopped; + void ERR_MortarStation(ERR_MortarBattery battery) { m_Battery = battery; } + IEntity Gunner() { return m_Gunner; } + bool GunIntact() + { + if (!m_Battery || !m_Battery.Gun) return false; + DamageManagerComponent damage = DamageManagerComponent.Cast(m_Battery.Gun.FindComponent(DamageManagerComponent)); + return damage && !damage.IsDestroyed(); + } + bool Holds(IEntity actor) + { + return Replication.IsServer() && !m_Stopped && GunIntact() && ERR_HQ.MissionActive() && actor && !ERR_Actors.Player(actor) && ERR_Actors.Group(actor) == m_Battery.Group; + } + bool HoldsSeat(IEntity actor, IEntity vehicle) + { + return Holds(actor) && vehicle == m_Battery.Gun && CompartmentAccessComponent.GetVehicleIn(actor) == vehicle; + } + bool HoldsPosition(IEntity actor) { return Holds(actor) && actor != m_Gunner && ERR_Actors.CanFight(actor); } + void Stop() + { + if (m_Stopped) return; + m_Stopped = true; + if (m_Mount) m_Mount.Complete(); + m_Mount = null; + foreach (SCR_CharacterControllerComponent controller : m_Controllers) + if (controller) controller.ERR_ClearMortarStation(this); + m_Controllers.Clear(); m_Gunner = null; + } + void Update(float now) + { + if (m_Stopped || !Replication.IsServer()) return; + if (!GunIntact()) + { + Stop(); + ERR_HQ hq = ERR_HQ.Get(); + if (hq) hq.ReleaseMortarCrew(m_Battery.Group); + m_Battery.Audit("CREW RELEASED", "original mortar destroyed or removed; surviving crew may leave"); + return; + } + if (!m_Battery.Group || !ERR_HQ.MissionActive()) return; + array agents = {}; m_Battery.Group.GetAgents(agents); + foreach (AIAgent agent : agents) + { + if (!agent || !agent.GetControlledEntity() || ERR_Actors.Player(agent.GetControlledEntity())) continue; + SCR_CharacterControllerComponent controller = SCR_CharacterControllerComponent.Cast(agent.GetControlledEntity().FindComponent(SCR_CharacterControllerComponent)); + if (!controller || m_Controllers.Contains(controller)) continue; + controller.ERR_SetMortarStation(this); m_Controllers.Insert(controller); + } + SCR_AIVehicleUsageComponent usage = SCR_AIVehicleUsageComponent.Cast(m_Battery.Gun.FindComponent(SCR_AIVehicleUsageComponent)); + if (!usage || !usage.GetTurretCompartmentSlot()) return; + TurretCompartmentSlot seat = usage.GetTurretCompartmentSlot(); + IEntity occupant = seat.GetOccupant(); + if (occupant) + { + if (Holds(occupant) && ERR_Actors.CanFight(occupant)) m_Gunner = occupant; + return; // never evict a player, incapacitated occupant or unrelated crew + } + if (!Holds(m_Gunner) || !ERR_Actors.CanFight(m_Gunner)) + { + if (m_Mount) m_Mount.Complete(); + m_Mount = null; m_Gunner = null; + foreach (AIAgent candidate : agents) + { + if (!candidate) continue; + IEntity actor = candidate.GetControlledEntity(); + if (Holds(actor) && actor != m_Battery.RadioOperator && ERR_Actors.CanFight(actor)) { m_Gunner = actor; break; } + } + } + if (!m_Gunner || m_Battery.Activity || now < m_NextMount) return; + SCR_ChimeraAIAgent gunnerAgent = SCR_ChimeraAIAgent.Cast(SCR_AIUtils.GetAIAgent(m_Gunner)); + if (!gunnerAgent || !gunnerAgent.m_UtilityComponent) return; + // Native deselection can reset terminal action state to EVALUATED. Queue + // membership, rather than that transient state, determines whether it is pending. + array actions = {}; gunnerAgent.m_UtilityComponent.GetActions(actions); + if (m_Mount && actions.Contains(m_Mount)) return; + // Native walking/boarding only; no teleport, respawn, or ammunition creation. + m_Mount = new SCR_AIGetInVehicle(gunnerAgent.m_UtilityComponent, null, m_Battery.Gun, seat, EAICompartmentType.Turret, 1000); + gunnerAgent.m_UtilityComponent.AddAction(m_Mount); + m_NextMount = now + 10000; + } +} + +modded class SCR_CharacterControllerComponent +{ + protected ERR_MortarStation m_ERRMortarStation; + protected bool m_ERRMortarSpeedHeld; + void ERR_SetMortarStation(ERR_MortarStation station) { m_ERRMortarStation = station; } + void ERR_ClearMortarStation(ERR_MortarStation station) + { + if (m_ERRMortarStation != station) return; + m_ERRMortarStation = null; + if (m_ERRMortarSpeedHeld) OverrideMaxSpeed(-1); + m_ERRMortarSpeedHeld = false; + } + ERR_MortarStation ERR_MortarStationDuty() { return m_ERRMortarStation; } + protected override void OnApplyControls(IEntity owner, float timeSlice) + { + super.OnApplyControls(owner, timeSlice); + // Keep support crew in their positions; aiming, firing, radio and damage remain active. + bool held = m_ERRMortarStation && m_ERRMortarStation.HoldsPosition(owner); + if (held) OverrideMaxSpeed(0); + else if (m_ERRMortarSpeedHeld) OverrideMaxSpeed(-1); + m_ERRMortarSpeedHeld = held; + } +} + +modded class SCR_AIGetOutVehicle +{ + override float CustomEvaluate() + { + if (m_Utility && m_Utility.m_OwnerEntity) + { + SCR_CharacterControllerComponent controller = SCR_CharacterControllerComponent.Cast(m_Utility.m_OwnerEntity.FindComponent(SCR_CharacterControllerComponent)); + if (controller && controller.ERR_MortarStationDuty() && controller.ERR_MortarStationDuty().HoldsSeat(m_Utility.m_OwnerEntity, m_Vehicle.m_Value)) return 0; + } + return super.CustomEvaluate(); + } +} diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSystem.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSystem.c index b09e66e..ea34118 100644 --- a/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSystem.c +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSystem.c @@ -30,12 +30,32 @@ class ERR_MortarSystem { if (!Replication.IsServer() || m_Prepared || m_Stopped) return false; m_Prepared = true; - vector position = ERR_Actors.Ground("6000 0 7000"); - if (position[1] < 1) return false; + ERR_SiteService sites = ERR_GameMode.Get().Sites(); + if (!sites) { Print("Reintroduced [mortars]: site service unavailable", LogLevel.ERROR); return false; } + for (int index = 0; index < sites.Count(); index++) + { + ERR_SiteRuntime site = sites.At(index); + if (site.Definition.Kind != ERR_LocationKind.MORTAR) continue; + PrintFormat("Reintroduced [mortars]: preparing %1 location=%2 authored=%3", site.Definition.Id, site.Location.Position(), site.Definition.Position); + if (!CreateBattery(site.Location.Position(), m_Batteries.Count() + 1)) return false; + } + #ifdef WORKBENCH + // Old geometry-dependent fixtures explicitly load LegacySites.conf. + string fixture; + if (m_Batteries.IsEmpty() && System.GetCLIParam("errSmokeOutcome", fixture) && !fixture.IsEmpty()) + return CreateBattery("6000 0 7000", 1); + #endif + return !m_Batteries.IsEmpty(); + } + protected bool CreateBattery(vector authoredPosition, int id) + { + vector position = ERR_Actors.Ground(authoredPosition); + if (position[1] < 1) { PrintFormat("Reintroduced [mortars]: below land at %1", position); return false; } IEntity gun = ERR_Actors.Spawn(ERR_MortarBattery.GUN, position); SCR_AIGroup group = SCR_AIGroup.Cast(ERR_Actors.Spawn(MortarGroup(), ERR_Actors.Ground(position + "0 0 4"))); if (!gun || !group) { + PrintFormat("Reintroduced [mortars]: creation failed gun=%1 group=%2 at %3", gun != null, group != null, position); ERR_Actors.DeleteSpawned(gun); ERR_MortarReadiness.RetireGroup(group); ERR_Actors.DeleteSpawned(group); @@ -43,6 +63,7 @@ class ERR_MortarSystem } if (group.GetFaction() != ERR_GameMode.Get().EnemyFaction()) { + Print("Reintroduced [mortars]: crew faction mismatch", LogLevel.ERROR); ERR_Actors.DeleteSpawned(gun); ERR_MortarReadiness.RetireGroup(group); ERR_Actors.DeleteSpawned(group); @@ -51,7 +72,7 @@ class ERR_MortarSystem FactionAffiliationComponent affiliation = FactionAffiliationComponent.Cast(gun.FindComponent(FactionAffiliationComponent)); if (affiliation) affiliation.SetAffiliatedFaction(ERR_GameMode.Get().EnemyFaction()); ERR_MortarBattery battery = new ERR_MortarBattery(); - battery.Bind(1, group, gun, GetGame().GetWorld().GetWorldTime()); + battery.Bind(id, group, gun, GetGame().GetWorld().GetWorldTime()); m_Batteries.Insert(battery); ERR_GameMode mode = ERR_GameMode.Get(); mode.Own(gun); diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirAssaultProbe.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirAssaultProbe.c new file mode 100644 index 0000000..d4f689e --- /dev/null +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirAssaultProbe.c @@ -0,0 +1,114 @@ +#ifdef WORKBENCH +modded class ERR_AirAssaultLoad +{ + int ERR_TestGrounded() + { + int count; + foreach (ERR_AirPassenger passenger : m_Passengers) + if (passenger.Jumped && ERR_Actors.CanFight(passenger.Actor) && !CompartmentAccessComponent.GetVehicleIn(passenger.Actor) && passenger.Actor.GetOrigin()[1] - SCR_TerrainHelper.GetTerrainY(passenger.Actor.GetOrigin()) < 3) count++; + return count; + } + int ERR_TestReleased() + { + int count; + foreach (ERR_AirAssaultTeam team : m_Teams) { if (team.Released) count++; + } + return count; + } + void ERR_TestCoverEnd(float now) { m_CoverUntil = now; + } +} +modded class ERR_GameMode +{ + protected int m_ERRAirStage; + protected float m_ERRAirDeadline; + protected ERR_AirAssaultLoad m_ERRAirLoad; + protected Vehicle m_ERRAirframe; + protected bool m_ERRAirStopped; + protected override void EOnInit(IEntity owner) + { + super.EOnInit(owner); + string fixture; + if (!Replication.IsServer() || SCR_Global.IsEditMode() || !System.GetCLIParam("errSmokeOutcome", fixture) || fixture != "air-assault") return; + m_ERRAirDeadline = GetWorld().GetWorldTime() + 650000; + GetGame().GetCallqueue().CallLater(ERR_AirTestTick, 500, true); + OnStop().Insert(ERR_AirTestStop); + } + protected void ERR_AirTestStop() { m_ERRAirStopped = true; + GetGame().GetCallqueue().Remove(ERR_AirTestTick); + } + protected bool ERR_AirCheck(bool result, string detail) + { + if (result) Print("ERR SMOKE PASS: air assault " + detail); + else { Print("ERR SMOKE FAIL: air assault " + detail, LogLevel.ERROR); + ERR_AirTestStop(); + } + return result; + } + protected void ERR_AirTestTick() + { + float now = GetWorld().GetWorldTime(); + if (now > m_ERRAirDeadline) { ERR_AirCheck(false, "deadline stage=" + m_ERRAirStage.ToString() + " " + ERR_HQ.Get().Recon().Status()); + return; + } + if (m_ERRAirStopped || !Active() || Phase() == ERR_Phase.PREPARING) return; + ERR_HQ hq = ERR_HQ.Get(); + if (m_ERRAirStage == 0) + { + array players = {}; + ERR_Actors.Players(players, true); + if (players.IsEmpty()) return; + if (!UnlockPrison(players[0])) return; + if (hq.SupplyConvoys()) hq.SupplyConvoys().Stop(); + hq.Recon().ERR_TestDeparture(now + 3000); + m_ERRAirStage = 1; + return; + } + ERR_ReconFlightComponent flight = hq.Recon().Current(); + if (!flight) { if (hq.Recon().ERR_TestWaves() > 0) ERR_AirCheck(false, "aircraft lost: " + hq.Recon().Status()); + return; + } + if (m_ERRAirStage == 1) + { + if (flight.Phase() == ERR_ReconPhase.CREW) return; + m_ERRAirLoad = flight.Assault(); + m_ERRAirframe = flight.Aircraft(); + if (!ERR_AirCheck(m_ERRAirLoad && m_ERRAirLoad.Count() == 8 && m_ERRAirLoad.Aboard() == 8, "eight original passengers physically seated before takeoff")) return; + m_ERRAirStage = 2; + } + if (m_ERRAirStage == 2) + { + if (!m_ERRAirLoad.Ready()) return; + ERR_AirDropOrder order = new ERR_AirDropOrder(); + order.ExpiresAt = now + 180000; + order.Target = flight.Home(); + order.Report = new ERR_HQReport(); + order.Report.Position = order.Target; + order.Report.ObservedAt = now; + // Controlled geometry/transfer fixture; policy and physical radio authorization + // are verified independently. This does not fabricate a live sighting result. + if (!ERR_AirCheck(m_ERRAirLoad.Begin(order, now), "controlled order finds real clear landing corridor")) return; + m_ERRAirStage = 3; + return; + } + if (m_ERRAirStage == 3) + { + if (m_ERRAirLoad.ERR_TestGrounded() < 8 || m_ERRAirLoad.ERR_TestReleased() < 2) return; + if (!ERR_AirCheck(flight.Aircraft() == m_ERRAirframe && flight.ERR_TestCrew() >= 2, "same eight actors landed and two original groups released; original aircrew retained")) return; + vector center; + if (!ERR_AirCheck(m_ERRAirLoad.Cover(now, center) && vector.DistanceXZ(center, flight.Home()) < 1, "post-drop cover active")) return; + m_ERRAirLoad.ERR_TestCoverEnd(now); + m_ERRAirStage = 4; + return; + } + if (m_ERRAirStage == 4) + { + if (flight.Assault() == m_ERRAirLoad || flight.Phase() != ERR_ReconPhase.TAKEOFF) return; + if (!ERR_AirCheck(flight.Aircraft() == m_ERRAirframe && flight.Assault().Aboard() == 8, "same helicopter returned, serviced and departed with another native squad")) return; + if (!ERR_AirCheck(hq.Airfield().Cargo() && hq.Airfield().Cargo().AtAirport(), "separate cargo helicopter waiting at airport")) return; + ERR_AirTestStop(); + Print("ERR SMOKE COMPLETE: native airborne cycle completed"); + } + } +} +#endif diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirLogisticsProbe.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirLogisticsProbe.c new file mode 100644 index 0000000..375104e --- /dev/null +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirLogisticsProbe.c @@ -0,0 +1,174 @@ +#ifdef WORKBENCH +modded class ERR_AirfieldSupport +{ + bool ERR_TestFailed() { return m_Mission && m_Mission.Finished() && m_Mission.ERR_TestDelivered() == 0; } + int ERR_TestDelivered() { if (m_Mission) return m_Mission.ERR_TestDelivered(); + return 0; } +} +modded class ERR_AirAmmoMission +{ + int ERR_TestDelivered() { return m_Delivered; } +} +modded class ERR_HQ +{ + void ERR_TestCheckin(SCR_AIGroup group) + { + foreach (ERR_HQUnit unit : m_Units) if (unit.Group == group) unit.NextStatus = 0; + } +} +modded class ERR_GameMode +{ + protected int m_ERRLogisticsStage; + protected float m_ERRLogisticsDeadline, m_ERRLogisticsRadioDeadline, m_ERRLogisticsDiagnostic; + protected SCR_AIGroup m_ERRLogisticsRecipient; + protected ref ERR_PrisonPatrol m_ERRLogisticsRadio = new ERR_PrisonPatrol(); + protected IEntity m_ERRForensicBody; + protected bool m_ERRForensicPassed, m_ERRDeliveryPassed; + protected override void EOnInit(IEntity owner) + { + super.EOnInit(owner); + string fixture; + if (!Replication.IsServer() || SCR_Global.IsEditMode() || !System.GetCLIParam("errSmokeOutcome", fixture) || fixture != "air-logistics") return; + m_ERRLogisticsDeadline = GetWorld().GetWorldTime() + 720000; + GetGame().GetCallqueue().CallLater(ERR_LogisticsTestTick, 1000, true); + OnStop().Insert(ERR_LogisticsTestStop); + } + protected void ERR_LogisticsTestStop() { GetGame().GetCallqueue().Remove(ERR_LogisticsTestTick); } + protected void ERR_LogisticsFail(string reason) + { + Print("ERR SMOKE FAIL: air logistics " + reason, LogLevel.ERROR); + ERR_LogisticsTestStop(); + } + protected void ERR_LogisticsBody() + { + array locations = {}; + Locations(locations); + foreach (ERR_LocationComponent location : locations) + { + if (location.Kind() != ERR_LocationKind.RADIO) continue; + ERR_SiteRuntime site = Sites().Find(location.Id()); + if (!site || !site.Group) continue; + array agents = {}; + site.Group.GetAgents(agents); + foreach (AIAgent agent : agents) + { + IEntity actor = agent.GetControlledEntity(); + ERR_BodyEvidence record = ERR_GameMode.Get().Evidence().Find(actor); + if (!record || record.Issued.IsEmpty() || !ERR_Actors.CanFight(actor)) continue; + m_ERRForensicBody = actor; + // Test setup removes an actually issued folder. Production inspection only + // sees it missing; it cannot consult a player's inventory or discovery map. + foreach (ERR_IssuedIntel issued : record.Issued) if (issued.Folder) SCR_EntityHelper.DeleteEntityAndChildren(issued.Folder); + DamageManagerComponent damage = DamageManagerComponent.Cast(actor.FindComponent(DamageManagerComponent)); + damage.SetHealthScaled(0); + SCR_GarbageSystem garbage = SCR_GarbageSystem.GetByEntityWorld(actor); + if (!garbage || garbage.Insert(actor, 1)) { ERR_LogisticsFail("unsearched military body was not retained"); return; } + Print("ERR SMOKE PASS: air logistics native corpse retention; actual issued document now absent"); + return; + } + } + } + protected void ERR_LogisticsTestTick() + { + float now = GetWorld().GetWorldTime(); + if (now > m_ERRLogisticsDeadline) { ERR_LogisticsFail("deadline stage=" + m_ERRLogisticsStage.ToString() + "; " + ERR_HQ.Get().Airfield().Status() + "; " + ERR_HQ.Get().Recovery().Status()); return; } + if (!Active() || Phase() == ERR_Phase.PREPARING) return; + ERR_HQ hq = ERR_HQ.Get(); + if (m_ERRLogisticsStage == 0) + { + array players = {}; + ERR_Actors.Players(players, true); + if (players.IsEmpty() || !UnlockPrison(players[0])) return; + if (hq.SupplyConvoys()) hq.SupplyConvoys().Stop(); + m_ERRLogisticsStage = 1; + } + if (!m_ERRForensicBody) ERR_LogisticsBody(); + if (m_ERRForensicBody && !m_ERRForensicPassed) + { + ERR_BodyEvidence evidence = ERR_GameMode.Get().Evidence().Find(m_ERRForensicBody); + if (evidence && evidence.Searched && evidence.Reported) + { + Print("ERR SMOKE PASS: air logistics special native recovery team searched body and delivered missing-intel report"); + m_ERRForensicPassed = true; + } + } + if (now >= m_ERRLogisticsDiagnostic) + { + m_ERRLogisticsDiagnostic = now + 30000; + Print("ERR AIR LOGISTICS STATUS: " + hq.Airfield().Status() + "; " + hq.Recovery().Status()); + } + ERR_ReconFlightComponent cargo = hq.Airfield().Cargo(); + if (!cargo || !cargo.AtAirport()) { if (m_ERRLogisticsStage < 3) return; } + if (m_ERRLogisticsStage == 1) + { + ActionsManagerComponent accessManager = ActionsManagerComponent.Cast(cargo.Aircraft().FindComponent(ActionsManagerComponent)); + if (!accessManager) { ERR_LogisticsFail("no aircraft action manager"); return; } + array accessContexts = {}; + accessManager.GetContextList(accessContexts); + PrintFormat("ERR AIR CARGO ACCESS: enabled=%1 contexts=%2", accessManager.IsEnabled(), accessContexts.Count()); + foreach (UserActionContext accessContext : accessContexts) + { + if (!accessContext) { Print("ERR AIR CARGO ACCESS: null context"); continue; } + array accessActions = {}; + accessContext.GetActionsList(accessActions); + if (accessActions.Count() > 64) PrintFormat("ERR AIR CARGO ACCESS: dense context=%1 actions=%2", accessContext.GetContextName(), accessActions.Count()); + foreach (BaseUserAction accessAction : accessActions) + { + if (!SCR_OpenVehicleStorageAction.Cast(accessAction)) continue; + vector accessTransform[4]; + bool transformed = accessContext.GetTransformationWorld(accessTransform); + PrintFormat("ERR AIR CARGO ACCESS: storage context=%1 rootOwner=%2 transformed=%3 point=%4", accessContext.GetContextName(), accessAction.GetOwner() == cargo.Aircraft(), transformed, accessTransform[3]); + } + } + array initialAccess = {}; + if (!ERR_InfantryAmmoAccess.Points(cargo.Aircraft(), initialAccess)) { ERR_LogisticsFail("airport cargo-access preflight refused; see context diagnostics"); return; } + + vector position; + if (!ERR_ReconAirports.FindClearPad(cargo.Home() + "250 0 0", position)) return; + m_ERRLogisticsRecipient = SCR_AIGroup.Cast(ERR_Actors.Spawn("{EC9F1AA42D0B7863}Prefabs/ERR/PrisonPatrol.et", position)); + if (!m_ERRLogisticsRecipient || !ERR_PrisonPatrol.Configure(m_ERRLogisticsRecipient, FactionSelection().Choice("enemy").Group, EnemyFaction())) { ERR_LogisticsFail("recipient creation failed"); return; } + Own(m_ERRLogisticsRecipient); + m_ERRLogisticsRecipient.ActivateAI(); + m_ERRLogisticsRadioDeadline = now + 60000; + m_ERRLogisticsStage = 2; + return; + } + if (m_ERRLogisticsStage == 2) + { + if (now > m_ERRLogisticsRadioDeadline) { ERR_LogisticsFail("recipient loadout/radio timeout"); return; } + if (!m_ERRLogisticsRecipient.IsExpandComplete()) return; + if (m_ERRLogisticsRadio.Radio(this, m_ERRLogisticsRecipient, m_ERRLogisticsRadioDeadline) != ERR_PrepareResult.READY) return; + array agents = {}; + m_ERRLogisticsRecipient.GetAgents(agents); + foreach (AIAgent agent : agents) + { + agent.SetPermanentLOD(0); agent.ActivateAI(); + IEntity actor = agent.GetControlledEntity(); + InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(actor.FindComponent(InventoryStorageManagerComponent)); + array items = {}; ERR_Inventory.Items(inventory, items); + foreach (IEntity item : items) + { + BaseMagazineComponent magazine = BaseMagazineComponent.Cast(item.FindComponent(BaseMagazineComponent)); + if (magazine) magazine.SetAmmoCount(0); + } + } + RegisterGroup(m_ERRLogisticsRecipient); + hq.ERR_TestCheckin(m_ERRLogisticsRecipient); + Print("ERR SMOKE PASS: air logistics native infantry low-ammunition request setup; waiting for real radio/HQ dispatch"); + m_ERRLogisticsStage = 3; + } + if (m_ERRLogisticsStage == 3 && hq.Airfield().ERR_TestFailed()) { ERR_LogisticsFail("first delivery ended without a native transfer; see AIR AMMUNITION journal reason"); return; } + if (m_ERRLogisticsStage == 3 && hq.Airfield().ERR_TestDelivered() > 0) + { + Print("ERR SMOKE PASS: air logistics aircraft transported airport-loaded magazine and native inventory transfer confirmed"); + m_ERRDeliveryPassed = true; + m_ERRLogisticsStage = 4; + } + if (m_ERRDeliveryPassed && m_ERRForensicPassed) + { + Print("ERR SMOKE COMPLETE: native radio-requested air ammunition delivery and physical forensic recovery"); + ERR_LogisticsTestStop(); + } + } +} +#endif diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirReconProbe.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirReconProbe.c new file mode 100644 index 0000000..5e3483f --- /dev/null +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirReconProbe.c @@ -0,0 +1,169 @@ +#ifdef WORKBENCH +modded class ERR_AirReconSystem +{ + void ERR_TestDeparture(float due) { m_Schedule.Started = true; m_Schedule.Deadline = due; m_PadAttempts = 0; } + float ERR_TestDeadline() { return m_Schedule.Deadline; } + int ERR_TestWaves() { return m_Serial; } + bool ERR_TestAirport(vector pad) + { + foreach (vector airport : m_Airports.m_Positions) if (vector.DistanceXZ(airport, pad) < 250) return true; + return false; + } +} +modded class ERR_ReconFlightComponent +{ + int ERR_TestCrew() { return m_OriginalCrew.Count(); } + bool ERR_TestPilot() { return LivingPilot(); } + bool ERR_TestSeen(IEntity actor) { return m_Observation && m_Observation.Target == actor; } + protected override void Search(float now) + { + super.Search(now); + string fixture; + if (System.GetCLIParam("errSmokeOutcome", fixture) && fixture == "air-recon") + m_Center = m_Home + Vector(0, 0, 800); // Controlled runway-sector encounter, native perception unchanged. + } +} +modded class ERR_GameMode +{ + protected int m_ERRReconStage; + protected float m_ERRReconDeadline, m_ERRReconDue, m_ERRReconWait; + protected Vehicle m_ERRReconFirst; + protected IEntity m_ERRReconPlayer; + protected bool m_ERRReconDamage, m_ERRReconTakeoverOnly; + protected override void EOnInit(IEntity owner) + { + super.EOnInit(owner); + string fixture; + if (!Replication.IsServer() || SCR_Global.IsEditMode() || !System.GetCLIParam("errSmokeOutcome", fixture) || fixture != "air-recon") return; + string takeoverOnly; m_ERRReconTakeoverOnly = System.GetCLIParam("errReconTakeoverOnly", takeoverOnly); + m_ERRReconDeadline = GetWorld().GetWorldTime() + 540000; + GetGame().GetCallqueue().CallLater(ERR_ReconTestTick, 500, true); + OnStop().Insert(ERR_ReconTestStop); + } + protected void ERR_ReconTestStop() + { + GetGame().GetCallqueue().Remove(ERR_ReconTestTick); + if (m_ERRReconPlayer) + { + DamageManagerComponent damage = DamageManagerComponent.Cast(m_ERRReconPlayer.FindComponent(DamageManagerComponent)); + if (damage) damage.EnableDamageHandling(m_ERRReconDamage); + } + } + protected bool ERR_ReconCheck(bool result, string text) + { + if (result) { Print("ERR SMOKE PASS: air recon " + text); return true; } + Print("ERR SMOKE FAIL: air recon " + text, LogLevel.ERROR); ERR_ReconTestStop(); return false; + } + protected void ERR_ReconTestTick() + { + float now = GetWorld().GetWorldTime(); + if (now > m_ERRReconDeadline) { ERR_ReconCheck(false, "deadline stage=" + m_ERRReconStage.ToString() + "; " + ERR_HQ.Get().Recon().Status()); return; } + if (!Active() || Phase() == ERR_Phase.PREPARING) return; + ERR_AirReconSystem system = ERR_HQ.Get().Recon(); + if (m_ERRReconStage == 0) + { + array players = {}; ERR_Actors.Players(players, true); + if (players.IsEmpty()) return; + m_ERRReconPlayer = players[0]; + if (!ERR_ReconCheck(UnlockPrison(m_ERRReconPlayer), "normal prison escape enables departure countdown")) return; + if (ERR_HQ.Get().SupplyConvoys()) ERR_HQ.Get().SupplyConvoys().Stop(); + DamageManagerComponent damage = DamageManagerComponent.Cast(m_ERRReconPlayer.FindComponent(DamageManagerComponent)); + m_ERRReconDamage = damage.IsDamageHandlingEnabled(); damage.EnableDamageHandling(false); + ChimeraCharacter actor = ChimeraCharacter.Cast(m_ERRReconPlayer); + vector transform[4]; actor.GetWorldTransform(transform); transform[3] = ERR_Actors.Ground("4550 0 11080"); actor.Teleport(transform); + m_ERRReconDue = now + 3000; system.ERR_TestDeparture(m_ERRReconDue); + m_ERRReconStage = 1; return; + } + ERR_ReconFlightComponent flight = system.Current(); + if (m_ERRReconStage == 1) + { + if (now < m_ERRReconDue) { if (!ERR_ReconCheck(!flight && system.ERR_TestWaves() == 0, "no aircraft before scheduled deadline")) return; return; } + if (!flight || flight.Phase() == ERR_ReconPhase.CREW) return; + if (!ERR_ReconCheck(flight.Phase() == ERR_ReconPhase.TAKEOFF && flight.ERR_TestCrew() >= 2 && flight.ERR_TestPilot(), "native original pilot/gunners seated before takeoff")) return; + if (!ERR_ReconCheck(system.ERR_TestAirport(flight.Home()) && system.ERR_TestWaves() == 1 && system.ERR_TestDeadline() < 0, "one actual airfield departure disarms launch timer")) return; + m_ERRReconFirst = flight.Aircraft(); + if (m_ERRReconTakeoverOnly) { m_ERRReconStage = 8; return; } + ChimeraCharacter encounter = ChimeraCharacter.Cast(m_ERRReconPlayer); + vector encounterTransform[4]; encounter.GetWorldTransform(encounterTransform); + encounterTransform[3] = ERR_Actors.Ground(flight.Home() + Vector(0, 0, 400)); encounter.Teleport(encounterTransform); + if (!ERR_ReconCheck(ERR_Actors.CanFight(m_ERRReconPlayer), "visible encounter player is alive and conscious")) return; + m_ERRReconStage = 2; return; + } + if (m_ERRReconStage == 2) + { + if (!flight || flight.Phase() == ERR_ReconPhase.RELEASED) { ERR_ReconCheck(false, system.Status()); return; } + float distance = vector.DistanceXZ(flight.Aircraft().GetOrigin(), flight.Home()); + if (distance < 300 || flight.Phase() < ERR_ReconPhase.SEARCH || !flight.ERR_TestSeen(m_ERRReconPlayer)) return; + array contacts = {}; ERR_HQ.Get().SupportContacts(contacts, now); + bool delivered; + foreach (ERR_HQReport contact : contacts) if (contact.Source == flight.Crew() && contact.Target == m_ERRReconPlayer) delivered = true; + if (!delivered) return; + if (!ERR_ReconCheck(flight.Phase() == ERR_ReconPhase.SHADOW, "real native player sighting enters shadow orbit and reaches HQ through crew radio")) return; + if (!ERR_ReconCheck(ERR_Actors.Alive(flight.Aircraft()) && flight.ERR_TestPilot() && flight.Aircraft().GetOrigin()[1] - SCR_TerrainHelper.GetTerrainY(flight.Aircraft().GetOrigin()) > 80, "airport takeoff and more than 300 metres of terrain-cleared search flight")) return; + system.Return(); + if (!ERR_ReconCheck(flight.Phase() == ERR_ReconPhase.RETURNING, "production return-home request accepted")) return; + m_ERRReconStage = 3; return; + } + if (m_ERRReconStage == 3) + { + if (!flight || flight.Phase() != ERR_ReconPhase.PARKED) return; + if (!ERR_ReconCheck(ERR_Actors.Alive(flight.Aircraft()) && vector.DistanceXZ(flight.Aircraft().GetOrigin(), flight.Home()) < 4 && flight.ERR_TestPilot(), "same intact helicopter and crew returned and landed on airfield")) return; + m_ERRReconWait = now + 4000; m_ERRReconStage = 4; return; + } + if (m_ERRReconStage == 4) + { + if (now < m_ERRReconWait) return; + if (!ERR_ReconCheck(flight && flight.Phase() == ERR_ReconPhase.PARKED && system.ERR_TestWaves() == 1, "parking does not create a replacement")) return; + DamageManagerComponent aircraftDamage = DamageManagerComponent.Cast(m_ERRReconFirst.FindComponent(DamageManagerComponent)); + aircraftDamage.SetHealthScaled(0); + m_ERRReconStage = 5; return; + } + if (m_ERRReconStage == 5) + { + if (flight) return; + if (!ERR_ReconCheck(system.ERR_TestDeadline() - now > 899000 && system.ERR_TestWaves() == 1, "actual destruction starts full 15-minute replacement delay")) return; + system.ERR_TestDeparture(now + 3000); m_ERRReconStage = 6; return; + } + if (m_ERRReconStage == 6) + { + if (!flight || flight.Phase() != ERR_ReconPhase.TAKEOFF) return; + if (!ERR_ReconCheck(system.ERR_TestWaves() == 2 && flight.Aircraft() != m_ERRReconFirst && !ERR_Actors.Alive(m_ERRReconFirst), "delayed replacement is a new aircraft and wreck is retained")) return; + m_ERRReconStage = 8; m_ERRReconWait = now + 500; return; + } + if (m_ERRReconStage == 8) + { + if (now < m_ERRReconWait) return; + if (!ERR_ReconCheck(ERR_Actors.SetFaction(flight.Aircraft(), PlayerFaction()), "native aircraft faction transferred to escapists")) return; + m_ERRReconWait = now + 15000; + m_ERRReconStage = 7; return; + } + if (m_ERRReconStage == 7) + { + if (!flight || flight.Phase() != ERR_ReconPhase.RELEASED) + { + if (now >= m_ERRReconWait) ERR_ReconCheck(false, "native faction handover did not release flight"); + return; + } + if (!ERR_ReconCheck(SCR_FactionManager.SGetFaction(flight.Aircraft()) == PlayerFaction(), "aircraft retains transferred faction")) return; + int expectedWaves = 2; if (m_ERRReconTakeoverOnly) expectedWaves = 1; + if (!ERR_ReconCheck(system.ERR_TestWaves() == expectedWaves && system.ERR_TestDeadline() < 0 && !flight.Lost(), "faction takeover releases scripted flight without creating replacement")) return; + if (m_ERRReconTakeoverOnly) + { + m_ERRReconStage = 9; m_ERRReconWait = now + 1000; return; + } + Print("ERR SMOKE COMPLETE: air recon scheduled airport launch, native search flight, return/landing, loss delay and takeover"); + ERR_ReconTestStop(); + } + if (m_ERRReconStage == 9) + { + if (now < m_ERRReconWait) return; + SCR_EntityHelper.DeleteEntityAndChildren(flight.Aircraft()); m_ERRReconStage = 10; return; + } + if (m_ERRReconStage == 10) + { + if (!ERR_ReconCheck(!flight && system.ERR_TestWaves() == 1 && system.ERR_TestDeadline() - now >= 898000, "native entity deletion schedules full delay without duplicate aircraft")) return; + Print("ERR SMOKE COMPLETE: air recon native faction takeover and explicit deletion loss timer"); ERR_ReconTestStop(); + } + } +} +#endif diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarStationProbe.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarStationProbe.c new file mode 100644 index 0000000..8518d4a --- /dev/null +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeMortarStationProbe.c @@ -0,0 +1,103 @@ +#ifdef WORKBENCH +modded class ERR_MortarBattery +{ + ERR_MortarStation ERR_StationProbe() { return m_Station; } +} +modded class ERR_GameMode +{ + protected int m_ERRStationStage, m_ERRStationDeadline; + protected float m_ERRStationWait; + protected ERR_MortarBattery m_ERRStationBattery; + protected IEntity m_ERRStationGunner; + protected ref array m_ERRStationSupport = {}; + protected ref array m_ERRStationOrigins = {}; + protected ref SCR_AIGetOutVehicle m_ERRStationExit; + protected override void EOnInit(IEntity owner) + { + super.EOnInit(owner); + string outcome; + if (!Replication.IsServer() || SCR_Global.IsEditMode() || !System.GetCLIParam("errSmokeOutcome", outcome) || outcome != "mortar-station") return; + m_ERRStationDeadline = System.GetTickCount() + 180000; + GetGame().GetCallqueue().CallLater(ERR_StationProbeTick, 500, true); + } + protected bool ERR_StationCheck(bool condition, string detail) + { + if (condition) { Print("ERR SMOKE PASS: mortar station " + detail); return true; } + Print("ERR SMOKE FAIL: mortar station " + detail, LogLevel.ERROR); + GetGame().GetCallqueue().Remove(ERR_StationProbeTick); return false; + } + protected void ERR_StationProbeTick() + { + if (System.GetTickCount() > m_ERRStationDeadline || !PreparationError().IsEmpty()) { ERR_StationCheck(false, "deadline/preparation " + PreparationError()); return; } + if (!Active() || GetWorld().GetWorldTime() < m_ERRStationWait) return; + SCR_PlayerController controller = SCR_PlayerController.Cast(GetGame().GetPlayerController()); + if (!controller || !controller.GetControlledEntity()) return; + float now = GetWorld().GetWorldTime(); + if (m_ERRStationStage == 0) + { + array batteries = {}; ERR_MortarSystem.Get().Batteries(batteries); + if (batteries.IsEmpty()) return; + m_ERRStationBattery = batteries[0]; + DamageManagerComponent.Cast(controller.GetControlledEntity().FindComponent(DamageManagerComponent)).EnableDamageHandling(false); + if (!ERR_StationCheck(UnlockPrison(controller.GetControlledEntity()), "normal prison release starts crew AI")) return; + m_ERRStationStage = 1; return; + } + ERR_MortarStation station = m_ERRStationBattery.ERR_StationProbe(); + if (m_ERRStationStage == 1) + { + if (!m_ERRStationBattery.StartupActivated || !station) return; + m_ERRStationGunner = station.Gunner(); + if (!m_ERRStationGunner || CompartmentAccessComponent.GetVehicleIn(m_ERRStationGunner) != m_ERRStationBattery.Gun) return; + if (!ERR_StationCheck(!m_ERRStationBattery.CommandOpen && m_ERRStationBattery.TotalShots == 0, "gunner boards original gun while idle without manufacturing fire orders")) return; + array agents = {}; m_ERRStationBattery.Group.GetAgents(agents); + foreach (AIAgent agent : agents) + { + IEntity actor = agent.GetControlledEntity(); + DamageManagerComponent.Cast(actor.FindComponent(DamageManagerComponent)).EnableDamageHandling(false); + if (actor == m_ERRStationGunner) continue; + m_ERRStationSupport.Insert(actor); m_ERRStationOrigins.Insert(actor.GetOrigin()); + SCR_ChimeraAIAgent ai = SCR_ChimeraAIAgent.Cast(agent); + ai.m_UtilityComponent.AddAction(new SCR_AIMoveIndividuallyBehavior(ai.m_UtilityComponent, null, ERR_Actors.Ground(actor.GetOrigin() + "40 0 0"), 1000)); + } + SCR_ChimeraAIAgent gunner = SCR_ChimeraAIAgent.Cast(SCR_AIUtils.GetAIAgent(m_ERRStationGunner)); + m_ERRStationExit = new SCR_AIGetOutVehicle(gunner.m_UtilityComponent, null, m_ERRStationBattery.Gun, priority: 2000); + if (!ERR_StationCheck(m_ERRStationExit.CustomEvaluate() == 0, "even high-priority AI dismount is refused for intact gun")) return; + gunner.m_UtilityComponent.AddAction(m_ERRStationExit); + m_ERRStationBattery.Cancel("native station retention test"); + m_ERRStationWait = now + 15000; m_ERRStationStage = 2; return; + } + if (m_ERRStationStage == 2) + { + if (!ERR_StationCheck(CompartmentAccessComponent.GetVehicleIn(m_ERRStationGunner) == m_ERRStationBattery.Gun, "gunner remains seated after cancellation and competing dismount")) return; + bool stayed = m_ERRStationSupport.Count() == 3; + foreach (int i, IEntity support : m_ERRStationSupport) + if (vector.DistanceXZ(support.GetOrigin(), m_ERRStationOrigins[i]) > 1.5) stayed = false; + if (!ERR_StationCheck(stayed, "all three support crew remain on station despite competing movement")) return; + DamageManagerComponent damage = DamageManagerComponent.Cast(m_ERRStationBattery.Gun.FindComponent(DamageManagerComponent)); + vector hit[3]; hit[0] = m_ERRStationBattery.Gun.GetOrigin(); hit[1] = "0 0 1"; hit[2] = "0 0 -1"; + damage.HandleDamage(new SCR_DamageContext(EDamageType.TRUE, 100000, hit, m_ERRStationBattery.Gun, damage.GetDefaultHitZone(), Instigator.CreateInstigator(controller.GetControlledEntity()), null, -1, -1)); + m_ERRStationWait = now + 3000; m_ERRStationStage = 3; return; + } + if (m_ERRStationStage == 3) + { + if (!ERR_StationCheck(!station.GunIntact() && !station.Holds(m_ERRStationGunner) && m_ERRStationExit.CustomEvaluate() > 0, "destroying the gun removes station and dismount restrictions")) return; + foreach (IEntity survivor : m_ERRStationSupport) + { + SCR_ChimeraAIAgent ai = SCR_ChimeraAIAgent.Cast(SCR_AIUtils.GetAIAgent(survivor)); + ai.m_UtilityComponent.AddAction(new SCR_AIMoveIndividuallyBehavior(ai.m_UtilityComponent, null, ERR_Actors.Ground(survivor.GetOrigin() + "30 0 0"), 2000)); + } + m_ERRStationWait = now + 15000; m_ERRStationStage = 4; return; + } + if (m_ERRStationStage == 4) + { + bool moved; + foreach (int i, IEntity survivor : m_ERRStationSupport) + if (vector.DistanceXZ(survivor.GetOrigin(), m_ERRStationOrigins[i]) > 3) moved = true; + if (!ERR_StationCheck(moved, "surviving support crew physically leave after destruction")) return; + GetGame().GetCallqueue().Remove(ERR_StationProbeTick); + Transition(ERR_Phase.DEFEAT); + Print("ERR SMOKE COMPLETE: permanent mortar station retention and release; scripted local fixture"); + } + } +} +#endif diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeScoutProbe.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeScoutProbe.c new file mode 100644 index 0000000..04dde90 --- /dev/null +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_NativeScoutProbe.c @@ -0,0 +1,54 @@ +#ifdef WORKBENCH +modded class ERR_HQ +{ + bool ERR_ProbeScoutReservation(SCR_AIGroup group) + { + foreach (ERR_HQUnit unit : m_Units) + if (unit.Group == group) return unit.ReservedForSupport && !unit.Eligible(m_Mode) && !ReserveLogistics(group, 888); + return false; + } +} +class ERR_NativeScoutProbe +{ + static bool Run() + { + ERR_HQ hq = ERR_HQ.Get(); + ERR_ScoutSystem scouts = hq.Scouts(); + if (scouts.Count() != 10) return false; + for (int index = 0; index < scouts.Count(); index++) + { + ERR_ScoutPost post = scouts.At(index); + if (!post.Ready || !ERR_Actors.CanFight(post.Actor) || post.Group.GetAgentsCount() != 1 || !hq.ERR_ProbeScoutReservation(post.Group)) return false; + if (post.Group.GetGroupUtilityComponent().GetCombatModeExternal() != EAIGroupCombatMode.RETURN_FIRE || ERR_HQRadio.Capability(post.Actor) != 2) return false; + if (SCR_FactionManager.SGetFaction(post.Actor) != ERR_GameMode.Get().EnemyFaction()) return false; + InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(post.Actor.FindComponent(InventoryStorageManagerComponent)); + if (!inventory || !post.Pack || inventory.CanInsertResourceInStorage(post.Magazine, post.Pack)) return false; + array magazines = {}; post.Pack.GetAll(magazines); + int matches; + foreach (IEntity item : magazines) + { + if (!item || !item.GetPrefabData() || item.GetPrefabData().GetPrefabName() != post.Magazine) return false; + MagazineComponent magazine = MagazineComponent.Cast(item.FindComponent(MagazineComponent)); + if (!magazine || magazine.GetAmmoCount() != magazine.GetMaxAmmoCount()) return false; + matches++; + } + if (matches < 1 || matches != post.Magazines) return false; + for (int other = 0; other < index; other++) + if (vector.DistanceXZ(post.Position, scouts.At(other).Position) < 900) return false; + PrintFormat("Escapists [scout probe]: PASS post=%1 height=%2 full magazines=%3 physical manpack, return fire, reserved", index + 1, post.Position[1], matches); + } + ERR_HQReport report = new ERR_HQReport(); report.RoadStatus = "on road"; + ERR_HQReport snapshot = report.Snapshot(); report.RoadStatus = "off road"; + if (snapshot.RoadStatus != "on road") return false; + ERR_HQReport before = new ERR_HQReport(); before.Target = scouts.At(0).Actor; before.Source = scouts.At(0).Group; + before.Position = "100 20 100"; before.ObservedAt = 1000; before.TravelMode = "on foot"; + ERR_HQReport after = before.Snapshot(); after.Position = "110 22 100"; after.ObservedAt = 11000; + ERR_ScoutMotion.Estimate(after, before); + if (!after.HasVelocity || after.Velocity != "1 0 0" || after.TravelDirection() != "E") return false; + after.ObservedAt = 42000; ERR_ScoutMotion.Estimate(after, before); + if (after.HasVelocity) return false; + Print("Escapists [scout probe]: PASS observed motion, direction, stale-sighting refusal and immutable road snapshot"); + return true; + } +} +#endif diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_ObjectiveDefence.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_ObjectiveDefence.c new file mode 100644 index 0000000..8942f27 --- /dev/null +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_ObjectiveDefence.c @@ -0,0 +1,105 @@ +class ERR_ObjectiveDefenceEntry +{ + ERR_SiteRuntime Site; + SCR_AIGroup Group; + AIWaypoint Hold; + bool Activated; + bool Spawned; + bool Admitted; + float Deadline; + Faction GuardFaction; + ResourceName GuardProfile; +} + +// One permanent garrison per objective, with one finite relief crew if its +// original garrison is absent. Player proximity activates defence, not HQ intel. +class ERR_ObjectiveDefence +{ + protected ERR_GameMode m_Mode; + protected ERR_HQ m_HQ; + protected ref array m_Entries = {}; + protected float m_Next; + protected bool m_Stopped; + void ERR_ObjectiveDefence(ERR_GameMode mode, ERR_HQ hq) { m_Mode = mode; m_HQ = hq; } + static bool Objective(int kind) + { + return kind == ERR_LocationKind.RADIO || kind == ERR_LocationKind.DEPOT + || kind == ERR_LocationKind.OUTPOST || kind == ERR_LocationKind.EXTRACTION; + } + protected void Initialize() + { + for (int i = 0; i < m_Mode.Sites().Count(); i++) + { + ERR_SiteRuntime site = m_Mode.Sites().At(i); + if (!site || !site.Definition || !Objective(site.Definition.Kind)) continue; + ERR_ObjectiveDefenceEntry entry = new ERR_ObjectiveDefenceEntry(); + entry.Site = site; + entry.GuardFaction = m_Mode.EnemyFaction(); entry.GuardProfile = m_Mode.FactionSelection().Choice("enemy").Group; + if (site.Group) + { + entry.GuardFaction = site.Group.GetFaction(); + if (site.Group.GetPrefabData()) entry.GuardProfile = site.Group.GetPrefabData().GetPrefabName(); + } + m_Entries.Insert(entry); + } + } + void Tick(float now) + { + if (m_Stopped || !Replication.IsServer() || !m_Mode.Active() || now < m_Next || m_Mode.Phase() <= ERR_Phase.PRISON) return; + m_Next = now + 5000; + if (m_Entries.IsEmpty()) Initialize(); + array players = {}; ERR_Actors.Players(players); + foreach (ERR_ObjectiveDefenceEntry entry : m_Entries) + { + if (entry.Spawned && !entry.Admitted && entry.Group) + { + if (entry.Group.IsExpandComplete() && m_Mode.ForceLiving(entry.Group) == entry.Group.m_aUnitPrefabSlots.Count() && m_Mode.ForceLiving(entry.Group) > 0) + { + string source = "defence-" + entry.Site.Definition.Id; + if (entry.Group.GetFaction() == m_Mode.EnemyFaction()) + { + ERR_ForceRecord record = m_Mode.Forces().Register(source, ERR_ForceKind.GARRISON, entry.Site.Location.Position(), m_Mode.ForceLiving(entry.Group), null, entry.Group, now); + if (!record) continue; + } + m_Mode.RegisterGroup(entry.Group); m_HQ.Dedicate(entry.Group, entry.Site.Definition.Id); + entry.Hold = AIWaypoint.Cast(ERR_Actors.Spawn(ERR_Resources.DefendWaypoint(), entry.Site.Location.Position())); + if (entry.Hold) { m_Mode.Own(entry.Hold); entry.Hold.SetCompletionRadius(40); entry.Group.AddWaypoint(entry.Hold); } + entry.Group.ActivateAI(); entry.Admitted = true; + ERR_HQ.Event("OBJECTIVE DEFENCE", source + " relief crew admitted; permanent local defence; position=" + entry.Site.Location.Position().ToString()); + } + else if (now >= entry.Deadline) { ERR_HQ.Event("OBJECTIVE DEFENCE", entry.Site.Definition.Id + " relief startup expired; no further spawn"); entry.Admitted = true; } + continue; + } + if (entry.Spawned) continue; + float nearest = 1e20; + foreach (IEntity player : players) if (player && ERR_Actors.Alive(player)) nearest = Math.Min(nearest, vector.DistanceXZ(player.GetOrigin(), entry.Site.Location.Position())); + if (nearest > 600) continue; + if (entry.Site.Group && m_Mode.ForceLiving(entry.Site.Group) > 0) + { + if (!entry.Activated) + { + entry.Activated = true; m_HQ.Dedicate(entry.Site.Group, entry.Site.Definition.Id); + ERR_HQ.Event("OBJECTIVE DEFENCE", entry.Site.Definition.Id + " existing garrison activated; permanent local defence; position=" + entry.Site.Location.Position().ToString()); + } + continue; + } + // No surprise materialisation on top of a player, nor infinite replenishment. + if (nearest < 200 || m_Mode.Forces().Count() >= 250) continue; + vector point = ERR_Actors.Ground(entry.Site.Location.Position() + "20 0 20"); + if (!ERR_HQRoadIntercept.Standable(point)) continue; + entry.Spawned = true; entry.Deadline = now + 30000; + entry.Group = SCR_AIGroup.Cast(ERR_Actors.Spawn("{EC9F1AA42D0B7863}Prefabs/ERR/PrisonPatrol.et", point)); + if (!entry.Group) continue; + m_Mode.Own(entry.Group); + // Retained ownership survives deletion of the original wiped-out group. + if (!ERR_PrisonPatrol.Configure(entry.Group, entry.GuardProfile, entry.GuardFaction)) entry.Admitted = true; + ERR_HQ.Event("OBJECTIVE DEFENCE", entry.Site.Definition.Id + " relief requested; position=" + point.ToString() + "; one relief crew maximum"); + } + } + void Stop() + { + m_Stopped = true; + foreach (ERR_ObjectiveDefenceEntry entry : m_Entries) + if (entry.Hold) { if (entry.Group) entry.Group.RemoveWaypoint(entry.Hold); ERR_Actors.DeleteSpawned(entry.Hold); entry.Hold = null; } + } +} diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_ReconAirports.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_ReconAirports.c new file mode 100644 index 0000000..c364b0f --- /dev/null +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_ReconAirports.c @@ -0,0 +1,118 @@ +// Adapted from the owner's original search-helicopter source; bounded native runway/tower discovery. +// Airport discovery is spread across updates instead of scanning the island +// in a single frame. An explicitly named ERR_ReconAirport marker takes priority. +class ERR_ReconAirports +{ + ref array m_Positions = {}; + protected ref array m_PositionSamples = {}; + protected vector m_vMin; + protected vector m_vMax; + protected vector m_vCursor; + protected bool m_bStarted; + protected bool m_bComplete; + void Update() + { + if (m_bComplete || !GetGame().GetWorldEntity()) + return; + if (!m_bStarted) + { + IEntity marker = GetGame().GetWorld().FindEntityByName("ERR_ReconAirport"); + if (marker && ERR_AirfieldPlacement.Clear(ERR_Actors.Ground(marker.GetOrigin()))) + { + m_Positions.Insert(marker.GetOrigin()); + m_PositionSamples.Insert(1); + m_bComplete = true; + return; + } + GetGame().GetWorldEntity().GetWorldBounds(m_vMin, m_vMax); + m_vCursor = m_vMin; + m_bStarted = true; + } + vector minimum = Vector(m_vCursor[0], -1000, m_vCursor[2]); + vector maximum = Vector(Math.Min(m_vCursor[0] + 2000, m_vMax[0]), 5000, Math.Min(m_vCursor[2] + 2000, m_vMax[2])); + GetGame().GetWorld().QueryEntitiesByAABB(minimum, maximum, AddAirport, IsAirportStructure, queryFlags: EQueryEntitiesFlags.ALL); + m_vCursor[0] = m_vCursor[0] + 2000; + if (m_vCursor[0] >= m_vMax[0]) + { + m_vCursor[0] = m_vMin[0]; + m_vCursor[2] = m_vCursor[2] + 2000; + } + m_bComplete = m_vCursor[2] >= m_vMax[2]; + if (m_bComplete) + { + PrintFormat("Escapists AI [air recon]: airport search finished; airports=%1", m_Positions.Count()); + for (int airportIndex = 0; airportIndex < m_Positions.Count(); airportIndex++) + PrintFormat("Escapists AI [air recon]: airport=%1 centre=%2 runway/tower samples=%3", airportIndex, m_Positions[airportIndex], m_PositionSamples[airportIndex]); + } + } + + protected bool IsAirportStructure(IEntity entity) + { + if (!entity || !entity.GetPrefabData()) + return false; + string prefabPath = entity.GetPrefabData().GetPrefabName(); + prefabPath.ToLower(); + // Airport-labelled props, bunkers and map locations can occur anywhere. + // Use physical runway infrastructure and control towers as anchors. + if (!prefabPath.Contains("prefabs/structures/")) + return false; + return prefabPath.Contains("/runway") || prefabPath.Contains("/lightrunway_") || prefabPath.Contains("/aircontroltower") || prefabPath.Contains("/airportcontroltower") || prefabPath.Contains("/controltower"); + } + + protected bool AddAirport(IEntity entity) + { + for (int index = 0; index < m_Positions.Count(); index++) + { + if (vector.DistanceXZ(m_Positions[index], entity.GetOrigin()) >= 1000) + continue; + // Use the cluster centre, rather than the first light at a runway edge. + int samples = m_PositionSamples[index]; + float sampleWeight = 1.0 / (samples + 1); + m_Positions[index] = vector.Lerp(m_Positions[index], entity.GetOrigin(), sampleWeight); + m_PositionSamples[index] = samples + 1; + return true; + } + m_Positions.Insert(entity.GetOrigin()); + m_PositionSamples.Insert(1); + PrintFormat("Escapists AI [air recon]: airport structure=%1 position=%2", entity.GetPrefabData().GetPrefabName(), entity.GetOrigin()); + return true; + } + + static bool FindClearPad(vector center, out vector position) + { + for (int attempt = 0; attempt < 12; attempt++) + { + float angleCandidate = Math.RandomFloat(0, Math.PI2); + float radiusCandidate = Math.RandomFloat(35, 220); + vector candidate = center + Vector(Math.Cos(angleCandidate) * radiusCandidate, 0, Math.Sin(angleCandidate) * radiusCandidate); + if (candidate == vector.Zero || vector.DistanceXZ(center, candidate) > 250 || ChimeraWorldUtils.TryGetWaterSurfaceSimple(GetGame().GetWorld(), candidate)) + continue; + candidate[1] = SCR_TerrainHelper.GetTerrainY(candidate); + bool flat = true; + for (int side = 0; side < 4; side++) + { + float angle = side * Math.PI / 2; + vector edge = candidate + Vector(Math.Cos(angle) * 12, 0, Math.Sin(angle) * 12); + if (Math.AbsFloat(SCR_TerrainHelper.GetTerrainY(edge) - candidate[1]) > 1.5) + flat = false; + } + if (!flat) + continue; + // Keep low crates, vehicles and people out of the pad footprint too; + // the overhead sweep alone starts above some of these obstacles. + if (!SCR_WorldTools.TraceCilinderUtil(candidate + Vector(0, 2.5, 0), 14, 4, TraceFlags.ENTS)) + continue; + TraceBox clearance = new TraceBox(); + clearance.Start = candidate + Vector(0, 4, 0); + clearance.End = candidate + Vector(0, 150, 0); + clearance.Mins = "-14 -2 -14"; + clearance.Maxs = "14 2 14"; + clearance.Flags = TraceFlags.ENTS | TraceFlags.WORLD; + if (GetGame().GetWorld().TraceMove(clearance, null) < 1) + continue; + position = candidate + Vector(0, 1.5, 0); + return true; + } + return false; + } +} diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_ReconCrewLocks.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_ReconCrewLocks.c new file mode 100644 index 0000000..18fbdcf --- /dev/null +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_ReconCrewLocks.c @@ -0,0 +1,19 @@ +// Retain the original pilots/gunners in flight; release on landing/loss/takeover. +modded class SCR_AIGetOutVehicle +{ + override float CustomEvaluate() + { + if (m_Utility && m_Utility.m_OwnerEntity) + { + ERR_HQ hq = ERR_HQ.Get(); + if (hq && hq.AirAssault() && hq.AirAssault().HoldsSeat(m_Utility.m_OwnerEntity)) return 0; + IEntity aircraft = CompartmentAccessComponent.GetVehicleIn(m_Utility.m_OwnerEntity); + if (aircraft) + { + ERR_ReconFlightComponent flight = ERR_ReconFlightComponent.Cast(aircraft.FindComponent(ERR_ReconFlightComponent)); + if (flight && flight.HoldsSeat(m_Utility.m_OwnerEntity)) return 0; + } + } + return super.CustomEvaluate(); + } +} diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_ReconFlightComponent.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_ReconFlightComponent.c new file mode 100644 index 0000000..a6d4fd2 --- /dev/null +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_ReconFlightComponent.c @@ -0,0 +1,359 @@ +// Flight/orbit/terrain correction adapted from the owner's original recon and +// helicopter base components. Native physics remains authoritative on server. +enum ERR_ReconPhase { CREW, TAKEOFF, SEARCH, SHADOW, RETURNING, LANDING, PARKED, RELEASED } +class ERR_ReconFlightRules +{ + static vector Cruise(vector position, vector center, bool returning) + { + vector toward = center - position; toward[1] = 0; + float distance = toward.Length(); + float speed = 40; + if (returning) speed = Math.Min(speed, Math.Max(8, distance * 0.2)); + vector desired = toward.Normalized() * speed; + if (!returning && distance < 650) + desired = Vector(-toward[2], 0, toward[0]).Normalized() * 28 + toward.Normalized() * Math.Clamp((distance - 300) * 0.15, -20, 25); + return desired; + } + static vector StandOff(vector aircraft, vector observed, vector velocity) + { + vector away = aircraft - observed; away[1] = 0; + float distance = away.Length(); + if (distance >= 180) return velocity; + if (distance < 1) away = "1 0 0"; + away.Normalize(); + float inward = vector.Dot(velocity, away); + if (inward < 0) velocity -= away * inward; + return velocity + away * Math.Clamp((180 - distance) * 0.5, 0, 25); + } +} +[ComponentEditorProps(category: "Reintroduced", description: "Airport reconnaissance helicopter")] +class ERR_ReconFlightComponentClass : ScriptComponentClass {} +class ERR_ReconFlightComponent : ScriptComponent +{ + protected bool m_Logistics, m_HoldAtAirport, m_Delivery; + protected vector m_DeliveryPad, m_TakeoffBase; + bool Logistics() { return m_Logistics; } + bool AtAirport() { return m_Phase == ERR_ReconPhase.PARKED && vector.DistanceXZ(m_Aircraft.GetOrigin(), m_Home) < 10; } + vector LandingTarget() + { + if (m_Delivery) return m_DeliveryPad; + return m_Home; + } + void LaunchDelivery(vector pad) + { + if (!m_Logistics || !AtAirport() || Captured() || !LivingPilot()) return; + m_Delivery = true; m_DeliveryPad = pad; RestartFlight(); + } + void RestartFlight() + { + if (!Replication.IsServer() || m_Phase != ERR_ReconPhase.PARKED || Captured() || !LivingPilot()) return; + m_TakeoffBase = m_Aircraft.GetOrigin(); m_Started = GetGame().GetWorld().GetWorldTime(); m_Settled = 0; + m_HoldAtAirport = false; + Locks(true); + Engines(true); + m_Phase = ERR_ReconPhase.TAKEOFF; + // A helicopter waiting at the airport may have gone to physics sleep. + // Wake it here: its simulation callback cannot wake itself while asleep. + Physics physics = m_Aircraft.GetPhysics(); + if (physics) physics.SetActive(ActiveState.ACTIVE); + } + void ReloadPassengers() + { + if (!AtAirport() || m_Logistics) return; + if (m_Assault && m_Assault.Aboard() > 0) { m_Assault.ReuseRemaining(); return; } + m_Assault = ERR_HQ.Get().AirAssault().Load(this, m_Home, m_Serial); + } + protected ERR_GameMode m_Mode; + protected Vehicle m_Aircraft; + protected SCR_AIGroup m_Crew; + protected ref ERR_AirAssaultLoad m_Assault; + ERR_AirAssaultLoad Assault() { return m_Assault; } + protected ref array m_Seats = {}; + protected ref array m_OriginalCrew = {}; + protected ref ERR_HelicopterAvailability m_Availability = new ERR_HelicopterAvailability(); + protected ERR_ReconPhase m_Phase; + protected vector m_Home, m_Center, m_Velocity; + protected float m_Started, m_NextSearch, m_ObservedAt = -1, m_LandingStarted, m_Settled, m_NextLog; + protected ref ERR_HQReport m_Observation; + protected int m_Serial; + protected bool m_Lost, m_Initialized, m_CrewLocked; + protected string m_Reason = "creating crew"; + Vehicle Aircraft() { return m_Aircraft; } + SCR_AIGroup Crew() { return m_Crew; } + ERR_ReconPhase Phase() { return m_Phase; } + vector Home() { return m_Home; } + vector Destination() { return m_Center; } + bool Lost() { return m_Lost; } + string Status() { return typename.EnumToString(ERR_ReconPhase, m_Phase) + ": " + m_Reason; } + override void OnPostInit(IEntity owner) + { + super.OnPostInit(owner); + if (!SCR_Global.IsEditMode() && Replication.IsServer()) SetEventMask(owner, EntityEvent.SIMULATE); + } + protected void Seats(IEntity entity) + { + SCR_BaseCompartmentManagerComponent manager = SCR_BaseCompartmentManagerComponent.Cast(entity.FindComponent(SCR_BaseCompartmentManagerComponent)); + if (manager) + { + array slots = {}; manager.GetCompartments(slots); + foreach (BaseCompartmentSlot slot : slots) + if (slot && (slot.GetType() == ECompartmentType.PILOT || slot.GetType() == ECompartmentType.TURRET) && !m_Seats.Contains(slot)) m_Seats.Insert(slot); + } + IEntity child = entity.GetChildren(); + while (child) { Seats(child); child = child.GetSibling(); } + } + void Initialize(ERR_GameMode mode, vector pad, int serial, bool logistics = false) + { + if (m_Initialized || !Replication.IsServer()) return; + m_Initialized = true; m_Mode = mode; m_Aircraft = Vehicle.Cast(GetOwner()); m_Home = pad; m_Center = pad; m_Serial = serial; + m_Logistics = logistics; m_HoldAtAirport = logistics; m_TakeoffBase = pad; + m_Started = GetGame().GetWorld().GetWorldTime(); + if (!m_Aircraft || !ERR_Actors.SetFaction(m_Aircraft, mode.EnemyFaction())) { Fail("aircraft faction unavailable"); return; } + m_Crew = SCR_AIGroup.Cast(ERR_Actors.Spawn("{C31F210ABE078195}Prefabs/ERR/ReconCrew.et", pad)); + if (!m_Crew) { Fail("crew group unavailable"); return; } + mode.Own(m_Crew); m_Crew.SetFaction(mode.EnemyFaction()); m_Crew.SetPermanentLOD(0); + m_Crew.GetGroupUtilityComponent().SetCombatMode(EAIGroupCombatMode.FIRE_AT_WILL); + Seats(m_Aircraft); + if (m_Seats.Count() < 2 || m_Seats.Count() > 8) { Fail("unsupported pilot/gunner seat layout"); return; } + ResourceName pilot = "{C31F210ABE078197}Prefabs/ERR/ReconPilotEast.et"; + string faction = mode.EnemyFaction().GetFactionKey(); + if (faction == "US" || faction == "RHS_USAF") pilot = "{C31F210ABE078199}Prefabs/ERR/ReconPilotWest.et"; + foreach (BaseCompartmentSlot seat : m_Seats) + { + if (seat.IsOccupied() || !seat.IsCompartmentAccessible()) { Fail("crew seat obstructed"); return; } + AIGroup nativeCrew = m_Crew; + IEntity initialCrew = seat.SpawnCharacterInCompartment(pilot, nativeCrew, "{C31F210ABE078195}Prefabs/ERR/ReconCrew.et"); + if (initialCrew) m_OriginalCrew.Insert(initialCrew); + if (nativeCrew != m_Crew) { Fail("native boarding changed crew identity"); return; } + } + m_Crew.ActivateAI(); Locks(true); + if (!logistics) m_Assault = ERR_HQ.Get().AirAssault().Load(this, pad, serial); + } + protected bool Captured() + { + if (!m_Crew || m_Crew.GetPlayerCount(true) > 0 || m_Crew.GetFaction() != m_Mode.EnemyFaction() || SCR_FactionManager.SGetFaction(m_Aircraft) != m_Mode.EnemyFaction()) return true; + array players = {}; GetGame().GetPlayerManager().GetPlayers(players); + foreach (int id : players) + { + IEntity actor = GetGame().GetPlayerManager().GetPlayerControlledEntity(id); + if (actor && CompartmentAccessComponent.GetVehicleIn(actor) == m_Aircraft) return true; + } + return false; + } + protected bool LivingPilot() + { + foreach (BaseCompartmentSlot seat : m_Seats) + if (seat && seat.GetType() == ECompartmentType.PILOT && m_OriginalCrew.Contains(seat.GetOccupant()) && ERR_Actors.CanFight(seat.GetOccupant()) && !ERR_Actors.Player(seat.GetOccupant())) return true; + return false; + } + protected void Engines(bool on) + { + if (!m_Aircraft) return; + VehicleHelicopterSimulation simulation = VehicleHelicopterSimulation.Cast(m_Aircraft.FindComponent(VehicleHelicopterSimulation)); + if (!simulation) return; + if (on) { simulation.EngineStart(); simulation.SetThrottle(1); simulation.RotorSetForceScaleState(0, 2); simulation.RotorSetForceScaleState(1, 1); } + else { simulation.EngineStop(); simulation.SetThrottle(0); simulation.RotorSetForceScaleState(0, 0); simulation.RotorSetForceScaleState(1, 0); } + } + protected void Locks(bool locked) { m_CrewLocked = locked; } + bool HoldsSeat(IEntity actor) + { + return Replication.IsServer() && m_CrewLocked && m_Mode && m_Mode.Active() && m_Phase >= ERR_ReconPhase.CREW && m_Phase <= ERR_ReconPhase.PARKED + && m_OriginalCrew.Contains(actor) && !ERR_Actors.Player(actor) && ERR_Actors.Group(actor) == m_Crew && ERR_Actors.Alive(m_Aircraft) + && CompartmentAccessComponent.GetVehicleIn(actor) == m_Aircraft; + } + protected void Fail(string reason) { m_Lost = true; m_Reason = reason; Release(false); ERR_HQ.Event("HELICOPTER FAILURE", reason); } + void Release(bool captured) + { + if (m_Phase == ERR_ReconPhase.RELEASED) return; + m_Phase = ERR_ReconPhase.RELEASED; + ClearEventMask(GetOwner(), EntityEvent.SIMULATE); + if (!captured && m_Aircraft && !Captured()) Engines(false); + Locks(false); + } + protected bool FinishCrew(float now) + { + m_Crew.ActivateAI(); + array boardingAgents = {}; m_Crew.GetAgents(boardingAgents); + foreach (AIAgent boardingAgent : boardingAgents) { boardingAgent.SetPermanentLOD(0); boardingAgent.ActivateAI(); } + if (m_Assault && m_Assault.Preparing()) return false; + if (now - m_Started > 45000) { Fail("native crew boarding timed out; partial spawn retained"); return false; } + foreach (BaseCompartmentSlot seat : m_Seats) + if (!seat || !seat.GetOccupant() || !ERR_Actors.CanFight(seat.GetOccupant()) || ERR_Actors.Group(seat.GetOccupant()) != m_Crew) return false; + // Native loadouts can complete after seating; keep the original boarding deadline. + if (ERR_HQRadio.Capability(m_Seats[0].GetOccupant()) != 2) return false; + foreach (BaseCompartmentSlot occupied : m_Seats) + { + IEntity actor = occupied.GetOccupant(); + if (!ERR_Actors.SetFaction(actor, m_Mode.EnemyFaction())) { Fail("crew faction unavailable"); return false; } + if (!m_OriginalCrew.Contains(actor)) m_OriginalCrew.Insert(actor); + } + ERR_ForceRecord record = m_Mode.Forces().Register("air-recon-" + m_Serial.ToString(), ERR_ForceKind.PATROL, m_Home, m_OriginalCrew.Count(), null, m_Crew, now); + if (!record) { Fail("finite force ledger refused crew"); return false; } + record.Pinned = true; m_Mode.RegisterGroup(m_Crew); m_Crew.ActivateAI(); + array agents = {}; m_Crew.GetAgents(agents); + foreach (AIAgent agent : agents) { agent.SetPermanentLOD(0); agent.ActivateAI(); } + Locks(true); + m_Aircraft.GetPhysics().SetActive(ActiveState.ACTIVE); + if (m_HoldAtAirport) { m_Phase = ERR_ReconPhase.PARKED; m_Reason = "ammunition helicopter awaiting HQ order"; } + else { Engines(true); m_Phase = ERR_ReconPhase.TAKEOFF; m_Reason = "vertical airport departure"; } + return true; + } + void ReturnHome() + { + if (!Replication.IsServer() || m_Lost || Captured() || m_Phase == ERR_ReconPhase.RELEASED) return; + if (m_Logistics && m_Delivery) + { + m_Delivery = false; + if (m_Phase == ERR_ReconPhase.PARKED) { RestartFlight(); return; } + m_Center = m_Home; + if (m_Phase == ERR_ReconPhase.TAKEOFF) return; + m_Phase = ERR_ReconPhase.RETURNING; + m_Reason = "cargo mission finished; returning to airport"; + return; + } + if (m_Phase < ERR_ReconPhase.SEARCH || m_Phase > ERR_ReconPhase.SHADOW) return; + if (m_Assault) m_Assault.Abort(); + m_Phase = ERR_ReconPhase.RETURNING; + m_Center = m_Home; + m_Reason = "returning to departure airfield"; + m_LandingStarted = GetGame().GetWorld().GetWorldTime(); + ERR_HQ.Event("HELICOPTER RETURN", m_Reason); + } + protected void Search(float now) + { + if (m_Logistics) { m_Phase = ERR_ReconPhase.RETURNING; m_Center = LandingTarget(); m_Reason = "HQ ammunition transport"; return; } + m_Phase = ERR_ReconPhase.SEARCH; m_NextSearch = now + 90000; + // Only delivered HQ snapshots are available as off-aircraft search hints. + array delivered = {}; ERR_HQ.Get().SupportContacts(delivered, now); + if (!delivered.IsEmpty()) { m_Center = delivered[delivered.Count() - 1].Position; m_Reason = "searching delivered HQ sighting"; return; } + vector low, high; GetGame().GetWorldEntity().GetWorldBounds(low, high); + for (int attempt = 0; attempt < 16; attempt++) + { + vector point = ERR_Actors.Ground(Vector(Math.RandomFloat(low[0], high[0]), 0, Math.RandomFloat(low[2], high[2]))); + if (ChimeraWorldUtils.TryGetWaterSurfaceSimple(GetGame().GetWorld(), point)) continue; + m_Center = point; m_Reason = "searching island sector"; return; + } + m_Center = m_Home; + } + protected bool IsEscapistTarget(IEntity target) + { + array players = {}; ERR_Actors.Players(players, true); + foreach (IEntity player : players) + if (target == player || CompartmentAccessComponent.GetVehicleIn(player) == target) return true; + return false; + } + protected void Observe(float now) + { + // The same real native-perception adapter used by ground scouts. HQ's own + // registered-crew observation tick sends these contacts through actual radios. + array visible = {}; ERR_HQObservation.Gather(m_Crew.GetGroupUtilityComponent(), now, visible); + ERR_HQVisualContact selected; + foreach (ERR_HQVisualContact contact : visible) + if (IsEscapistTarget(contact.Entity) && vector.DistanceXZ(m_Aircraft.GetOrigin(), contact.Position) <= 1200 + && (!selected || (m_Observation && contact.Entity == m_Observation.Target))) selected = contact; + if (!selected || (m_Observation && selected.Entity == m_Observation.Target && selected.ObservedAt - m_ObservedAt < 2000)) return; + ERR_HQReport sighting = new ERR_HQReport(); sighting.Target = selected.Entity; sighting.Source = m_Crew; + sighting.Position = selected.Position; sighting.ObservedAt = selected.ObservedAt; sighting.TravelMode = selected.Travel; + ERR_ScoutMotion.Estimate(sighting, m_Observation); m_Observation = sighting; m_ObservedAt = sighting.ObservedAt; + } + void Update(float now) + { + if (!m_Initialized || m_Lost || !m_Mode || !m_Mode.Active()) return; + if (!m_Aircraft || !ERR_Actors.Alive(m_Aircraft)) { Fail("aircraft destroyed or removed"); return; } + if (m_Phase == ERR_ReconPhase.CREW) { FinishCrew(now); return; } + SCR_VehicleDamageManagerComponent damage = SCR_VehicleDamageManagerComponent.Cast(m_Aircraft.FindComponent(SCR_VehicleDamageManagerComponent)); + bool captured = Captured(); + bool disabled = !damage || !damage.GetEngineFunctional() || damage.GetMovementDamage() >= 1 || damage.IsOnFire(); + Physics physics = m_Aircraft.GetPhysics(); + if (!physics) { Fail("aircraft physics unavailable"); return; } + if (m_Phase == ERR_ReconPhase.TAKEOFF) physics.SetActive(ActiveState.ACTIVE); + string loss = m_Availability.Check(now, m_Started, false, disabled, LivingPilot(), captured, m_Phase == ERR_ReconPhase.PARKED, + m_Aircraft.GetOrigin()[1] - SCR_TerrainHelper.GetTerrainY(m_Aircraft.GetOrigin()), physics.GetVelocity().Length()); + if (!loss.IsEmpty()) { Fail(loss); return; } + if (captured) { m_Reason = "player takeover; flight controls released"; Release(true); return; } + if (m_Phase == ERR_ReconPhase.RELEASED || m_Phase == ERR_ReconPhase.PARKED) return; + if (now >= m_NextLog) { m_NextLog = now + 15000; ERR_HQ.Event("HELICOPTER STATUS", Status() + "; position=" + m_Aircraft.GetOrigin().ToString()); } + if (m_Phase == ERR_ReconPhase.RETURNING && vector.DistanceXZ(m_Aircraft.GetOrigin(), LandingTarget()) < 100) + { m_Phase = ERR_ReconPhase.LANDING; m_LandingStarted = now; m_Reason = "landing at airfield"; } + if (m_Phase == ERR_ReconPhase.LANDING && now - m_LandingStarted > 180000) { m_Phase = ERR_ReconPhase.RETURNING; m_Reason = "landing retry"; return; } + if (m_Phase != ERR_ReconPhase.SEARCH && m_Phase != ERR_ReconPhase.SHADOW) return; + vector cover; if (m_Assault && m_Assault.Cover(now, cover)) { Observe(now); m_Center = cover; m_Reason = "covering landed airborne squad"; return; } + FuelManagerComponent fuel = FuelManagerComponent.Cast(m_Aircraft.FindComponent(FuelManagerComponent)); + if (fuel && fuel.GetTotalFuel() < 50) { ReturnHome(); return; } + Observe(now); + if (m_Observation && now - m_ObservedAt <= 15000) + { + m_Phase = ERR_ReconPhase.SHADOW; + m_Center = ERR_HQReport.Predict(m_Observation.Position, m_Observation.Velocity, Math.Min(8, (now - m_ObservedAt) / 1000)); + m_Reason = "orbiting last visible contact"; + } + else if (m_Observation && now - m_ObservedAt <= 120000) + { + m_Phase = ERR_ReconPhase.SEARCH; + if (now >= m_NextSearch) + { + float angle = Math.RandomFloat(0, Math.PI2); float radius = Math.Min(600, 150 + (now - m_ObservedAt) / 200); + m_Center = m_Observation.Position + Vector(Math.Cos(angle) * radius, 0, Math.Sin(angle) * radius); + m_NextSearch = now + 30000; m_Reason = "searching around lost sighting"; + } + } + else if (now >= m_NextSearch) Search(now); + } + override void EOnSimulate(IEntity owner, float timeSlice) + { + if (!Replication.IsServer() || !m_Initialized || m_Phase == ERR_ReconPhase.CREW || m_Phase >= ERR_ReconPhase.PARKED) return; + if (!m_Mode || !m_Mode.Active() || Captured()) { Release(true); return; } + if (!LivingPilot() || !ERR_Actors.Alive(m_Aircraft)) { Fail("pilot or airframe lost"); return; } + Physics physics = owner.GetPhysics(); if (!physics) { Fail("physics lost"); return; } + vector position = owner.GetOrigin(); float now = GetGame().GetWorld().GetWorldTime(); + if (m_Phase == ERR_ReconPhase.TAKEOFF) + { + float climb; if (now - m_Started >= 10000) climb = 5; + physics.SetVelocity(Vector(0, climb, 0)); physics.SetAngularVelocity(vector.Zero); + if (position[1] - m_TakeoffBase[1] >= 120) Search(now); + return; + } + if (m_Phase == ERR_ReconPhase.LANDING) + { + vector toward = LandingTarget() - position; float vertical = toward[1]; toward[1] = 0; + vector angles = owner.GetYawPitchRoll(); owner.SetYawPitchRoll(Vector(angles[0], Math.Lerp(angles[1], 0, Math.Clamp(timeSlice * 2, 0, 1)), Math.Lerp(angles[2], 0, Math.Clamp(timeSlice * 2, 0, 1)))); + vector landing = toward.Normalized() * Math.Min(8, toward.Length() * 0.5); + landing[1] = Math.Clamp(vertical * 0.3, -3, 3); if (toward.Length() > 15) landing[1] = Math.Max(0, landing[1]); + physics.SetVelocity(landing); physics.SetAngularVelocity(vector.Zero); + if (toward.Length() < 3 && Math.AbsFloat(vertical) < 1 && physics.GetVelocity().Length() < 1) m_Settled += timeSlice; else m_Settled = 0; + if (m_Settled >= 2) { m_Phase = ERR_ReconPhase.PARKED; m_Reason = "landed; original helicopter retained"; Engines(false); physics.SetVelocity(vector.Zero); } + return; + } + vector destination = m_Center; bool dropRun; + vector dropDestination; + if (m_Assault && m_Assault.Approach(dropDestination)) { dropRun = true; destination = dropDestination; } + vector desired = ERR_ReconFlightRules.Cruise(position, destination, dropRun || m_Phase == ERR_ReconPhase.RETURNING); + if (dropRun && desired.Length() > 24) desired = desired.Normalized() * 24; + m_Velocity = vector.Lerp(m_Velocity, desired, Math.Clamp(timeSlice * 0.6, 0, 1)); m_Velocity[1] = 0; + if (!dropRun && m_Phase != ERR_ReconPhase.RETURNING && m_Observation && now - m_ObservedAt <= 120000) m_Velocity = ERR_ReconFlightRules.StandOff(position, m_Observation.Position, m_Velocity); + vector ahead = position + m_Velocity.Normalized() * 100; + float terrain = Math.Max(SCR_TerrainHelper.GetTerrainY(ahead, GetGame().GetWorld(), noUnderwater: true), SCR_TerrainHelper.GetTerrainY(position, GetGame().GetWorld(), noUnderwater: true)); + physics.SetVelocity(Vector(m_Velocity[0], Math.Clamp((terrain + 120 - position[1]) * 2, -2, 24), m_Velocity[2])); + if (m_Velocity.Length() > 1) NoseDown(); + } + protected void NoseDown() + { + vector direction[4]; Math3D.DirectionAndUpMatrix(m_Velocity.Normalized(), vector.Up, direction); + float pitch[4], base[4], rotation[4]; + SCR_Math3D.QuatAngleAxis(Math.Lerp(0, 20, Math.Clamp(m_Velocity.Length() / 70, 0, 1)) * Math.DEG2RAD, direction[0], pitch); + Math3D.MatrixToQuat(direction, base); Math3D.QuatMultiply(rotation, pitch, base); + vector axes[3]; Math3D.QuatToMatrix(rotation, axes); + vector transform[4]; transform[0] = axes[0]; transform[1] = axes[1]; transform[2] = axes[2]; transform[3] = m_Aircraft.GetOrigin(); + m_Aircraft.SetTransform(transform); + } + override void OnDelete(IEntity owner) + { + if (Replication.IsServer()) + { + Release(false); + ERR_HQ hq = ERR_HQ.Get(); + if (m_Mode && m_Mode.Active() && hq && hq.Recon()) hq.Recon().Removed(this); + } + super.OnDelete(owner); + } +} diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_ScoutSystem.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_ScoutSystem.c new file mode 100644 index 0000000..19c7ac4 --- /dev/null +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_ScoutSystem.c @@ -0,0 +1,305 @@ +// Ten finite observation posts on Everon. Survey and stock finish before player +// admission. No replacements, periodic ammunition grants or target-position polling. +class ERR_ScoutPost +{ + vector Position; + float Heading; + SCR_AIGroup Group; + IEntity Actor; + BaseInventoryStorageComponent Pack; + ResourceName Magazine; + int Magazines; + bool Ready; + ref ERR_EnemyEquipmentCallback Operation; + ref array MotionSamples = {}; +} + +class ERR_ScoutTerrain +{ + // Reject low/flat terrain; prefer local crests with several downhill views. + static bool Hill(float height, float islandHigh, float meanDrop, int lowerSamples) + { + return height >= Math.Max(35, islandHigh * 0.18) && meanDrop >= 6 && lowerSamples >= 4; + } + static bool Separated(vector point, array posts, ERR_ScenarioDefinition definition) + { + foreach (ERR_ScoutPost post : posts) if (vector.DistanceXZ(point, post.Position) < 900) return false; + foreach (ERR_SiteDefinition site : definition.Sites) + { + float minimum = 150; + if (site.Kind == ERR_LocationKind.PRISON) minimum = 600; + if (vector.DistanceXZ(point, site.Position) < minimum) return false; + } + return true; + } + static bool Survey(vector point, float islandHigh, out float heading) + { + float drop; int lower; + for (int sample = 0; sample < 8; sample++) + { + float angle = sample * Math.PI / 4; + vector edge = ERR_Actors.Ground(point + Vector(Math.Sin(angle) * 150, 0, Math.Cos(angle) * 150)); + float delta = point[1] - edge[1]; drop += delta; + if (delta >= 5) lower++; + } + if (!Hill(point[1], islandHigh, drop / 8, lower) || !ERR_HQRoadIntercept.Standable(point)) return false; + int views; float best = -1; + for (int ray = 0; ray < 8; ray++) + { + float bearing = ray * Math.PI / 4; + vector end = ERR_Actors.Ground(point + Vector(Math.Sin(bearing) * 350, 0, Math.Cos(bearing) * 350)); + TraceParam sight = new TraceParam(); + sight.Start = point + "0 1.7 0"; sight.End = end + "0 1.7 0"; + sight.Flags = TraceFlags.ENTS | TraceFlags.WORLD; + float fraction = GetGame().GetWorld().TraceMove(sight, null); + if (fraction >= 0.95) views++; + if (fraction > best) { best = fraction; heading = ray * 45; } + } + return views >= 2; + } +} + +class ERR_ScoutSystem +{ + protected ERR_GameMode m_Mode; + protected ref array m_Posts = {}; + protected ERR_ScenarioDefinition m_Definition; + protected vector m_Low, m_High; + protected float m_IslandHigh; + protected int m_Started, m_HeightSamples, m_Attempts; + protected float m_Deadline; + protected bool m_Begun, m_Surveyed, m_Ready, m_Stopped; + protected string m_Error; + void ERR_ScoutSystem(ERR_GameMode mode) { m_Mode = mode; } + string Error() { return m_Error; } + int Count() { return m_Posts.Count(); } + ERR_ScoutPost At(int index) { return m_Posts[index]; } + bool Contains(SCR_AIGroup group) + { + foreach (ERR_ScoutPost post : m_Posts) if (post.Group == group) return true; + return false; + } + // The source estimates motion from two clear sightings of the same identity. + // HQ receives this frozen estimate through the normal physical radio route. + void DescribeMotion(ERR_HQReport report) + { + if (!report || !report.Target || report.Distress || report.DetailsObservedAt < 0 || m_Stopped) return; + foreach (ERR_ScoutPost post : m_Posts) + { + if (!post.Ready || post.Group != report.Source) continue; + for (int index = post.MotionSamples.Count() - 1; index >= 0; index--) + { + ERR_HQReport previous = post.MotionSamples[index]; + if (!previous.Target || report.ObservedAt - previous.ObservedAt > 30000) { post.MotionSamples.Remove(index); continue; } + if (previous.Target != report.Target) continue; + if (report.ObservedAt <= previous.ObservedAt) return; + ERR_ScoutMotion.Estimate(report, previous); + post.MotionSamples[index] = report.Snapshot(); + return; + } + if (post.MotionSamples.Count() >= 64) post.MotionSamples.Remove(0); + post.MotionSamples.Insert(report.Snapshot()); + return; + } + } + protected ERR_PrepareResult Fail(string reason) + { + m_Error = "Hill scout preparation: " + reason; + Print(m_Error, LogLevel.ERROR); + Stop(); + return ERR_PrepareResult.FAILED; + } + protected vector RandomPoint() + { + return ERR_Actors.Ground(Vector(Math.RandomFloat(m_Low[0] + 50, m_High[0] - 50), 0, Math.RandomFloat(m_Low[2] + 50, m_High[2] - 50))); + } + protected ERR_PrepareResult Survey() + { + int tick = System.GetTickCount(); + while (m_HeightSamples < 500) + { + vector heightSample = RandomPoint(); m_HeightSamples++; + m_IslandHigh = Math.Max(m_IslandHigh, heightSample[1]); + if (System.GetTickCount() - tick >= 6) return ERR_PrepareResult.PENDING; + } + while (m_Posts.Count() < m_Definition.ScoutCount) + { + if (++m_Attempts > 100000 || System.GetTickCount() - m_Started > 45000) + return Fail(string.Format("only %1/%2 safe, separated hilltops found; adjust ScoutCount or terrain criteria", m_Posts.Count(), m_Definition.ScoutCount)); + vector point = RandomPoint(); float heading; + if (ERR_ScoutTerrain.Separated(point, m_Posts, m_Definition) && ERR_ScoutTerrain.Survey(point, m_IslandHigh, heading)) + { + ERR_ScoutPost post = new ERR_ScoutPost(); post.Position = point; post.Heading = heading; m_Posts.Insert(post); + PrintFormat("Escapists [scout survey]: post=%1 position=%2 heading=%3", m_Posts.Count(), point, heading); + } + if (System.GetTickCount() - tick >= 6) return ERR_PrepareResult.PENDING; + } + m_Surveyed = true; + m_Deadline = GetGame().GetWorld().GetWorldTime() + 60000; + return ERR_PrepareResult.READY; + } + protected bool Spawn(ERR_ScoutPost post) + { + post.Group = SCR_AIGroup.Cast(ERR_Actors.Spawn("{DF862ED195094E21}Prefabs/ERR/ScoutGroup.et", post.Position, Vector(post.Heading, 0, 0))); + if (!post.Group) return false; + m_Mode.Own(post.Group); + post.Group.SetFaction(m_Mode.EnemyFaction()); + ResourceName soldier = "{CF862ED195094E28}Prefabs/ERR/ScoutEast.et"; + post.Magazine = "{9CCB46C6EE632C1A}Prefabs/Weapons/Magazines/Magazine_762x54_SVD_10rnd_Sniper.et"; + string faction = m_Mode.EnemyFaction().GetFactionKey(); + if (faction == "US" || faction == "RHS_USAF") + { + soldier = "{CF862ED195094E2A}Prefabs/ERR/ScoutWest.et"; + post.Magazine = "{627255315038152A}Prefabs/Weapons/Magazines/Magazine_762x51_M14_20rnd_SpecialBall.et"; + } + post.Group.m_aUnitPrefabSlots = {soldier}; + SCR_AIGroupUtilityComponent utility = post.Group.GetGroupUtilityComponent(); + if (!utility) return false; + utility.SetCombatMode(EAIGroupCombatMode.RETURN_FIRE); + AIWaypoint hold = AIWaypoint.Cast(ERR_Actors.Spawn(ERR_Resources.DefendWaypoint(), post.Position)); + if (!hold) return false; + m_Mode.Own(hold); hold.SetCompletionRadius(8); post.Group.AddWaypoint(hold); + post.Group.SetSpawnImmediately(true); post.Group.RequestSpawn(1); + return true; + } + protected ERR_PrepareResult Stock(ERR_ScoutPost post) + { + if (!post.Group.IsExpandComplete()) return ERR_PrepareResult.PENDING; + array agents = {}; post.Group.GetAgents(agents); + if (agents.Count() != 1 || !agents[0]) return ERR_PrepareResult.PENDING; + if (!post.Actor) + { + post.Actor = agents[0].GetControlledEntity(); + if (!post.Actor) return ERR_PrepareResult.PENDING; + if (!ERR_Actors.SetFaction(post.Actor, m_Mode.EnemyFaction())) return Fail("scout faction affiliation unavailable"); + // Native group spawn may choose an offset. Place the original body on the + // surveyed standing point, facing its longest checked view, before release. + ChimeraCharacter actor = ChimeraCharacter.Cast(post.Actor); + if (!actor) return Fail("scout character unavailable"); + vector transform[4]; Math3D.AnglesToMatrix(Vector(post.Heading, 0, 0), transform); transform[3] = post.Position; actor.Teleport(transform); + SCR_ChimeraAIAgent nativeAgent = SCR_ChimeraAIAgent.Cast(agents[0]); + if (nativeAgent) nativeAgent.ERR_HoldForPrison(); + } + if (!ERR_Actors.CanFight(post.Actor)) return Fail("scout died before admission; no replacement"); + InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(post.Actor.FindComponent(InventoryStorageManagerComponent)); + if (!inventory) return ERR_PrepareResult.PENDING; + if (!post.Pack) + { + array storages = {}; inventory.GetStorages(storages); + foreach (BaseInventoryStorageComponent storage : storages) + if (storage && storage.GetOwner().GetPrefabData() && storage.GetOwner().GetPrefabData().GetPrefabName().Contains("/ScoutRadioPack.et")) { post.Pack = storage; break; } + if (!post.Pack) return ERR_PrepareResult.PENDING; + } + if (post.Operation) + { + if (!post.Operation.Finished) return ERR_PrepareResult.PENDING; + if (!post.Operation.Succeeded) return Fail("native magazine insertion failed"); + post.Magazines++; post.Operation = null; + } + if (inventory.CanInsertResourceInStorage(post.Magazine, post.Pack)) + { + if (post.Magazines >= 128) return Fail("backpack capacity exceeds bounded magazine allowance"); + post.Operation = new ERR_EnemyEquipmentCallback(); + if (!inventory.TrySpawnPrefabToStorage(post.Magazine, post.Pack, -1, EStoragePurpose.PURPOSE_ANY, post.Operation)) return Fail("native magazine insertion refused"); + return ERR_PrepareResult.PENDING; + } + if (post.Magazines < 1 || ERR_HQRadio.Capability(post.Actor) != 2) return Fail("full backpack or physical long-range radio missing"); + array items = {}; inventory.GetItems(items); + bool binoculars, rifle; + foreach (IEntity item : items) + { + if (item.FindComponent(SCR_BinocularsComponent)) binoculars = true; + BaseWeaponComponent weapon = BaseWeaponComponent.Cast(item.FindComponent(BaseWeaponComponent)); + if (weapon && weapon.GetWeaponType() == EWeaponType.WT_SNIPERRIFLE) rifle = true; + } + if (!binoculars || !rifle) return Fail("binoculars or scoped sniper rifle missing"); + ERR_ForceRecord record = m_Mode.Forces().Register("hill-scout-" + (m_Posts.Find(post) + 1).ToString(), ERR_ForceKind.GARRISON, post.Position, 1, null, post.Group, GetGame().GetWorld().GetWorldTime()); + if (!record) return Fail("finite force ledger admission refused"); + record.Pinned = true; + m_Mode.RegisterGroup(post.Group); + post.Ready = true; + PrintFormat("Escapists [scout ready]: position=%1 backpack magazines=%2", post.Position, post.Magazines); + return ERR_PrepareResult.READY; + } + ERR_PrepareResult Prepare(ERR_ScenarioDefinition definition) + { + if (m_Stopped || !Replication.IsServer() || !definition) return ERR_PrepareResult.FAILED; + if (m_Ready) return ERR_PrepareResult.READY; + if (!m_Begun) + { + m_Begun = true; m_Definition = definition; m_Started = System.GetTickCount(); + GetGame().GetWorldEntity().GetWorldBounds(m_Low, m_High); + } + if (!m_Surveyed) + { + ERR_PrepareResult survey = Survey(); + if (survey != ERR_PrepareResult.READY) return survey; + } + if (GetGame().GetWorld().GetWorldTime() > m_Deadline) return Fail("native scout spawn/equipment deadline exceeded"); + bool pending; + foreach (ERR_ScoutPost post : m_Posts) + { + if (post.Ready) continue; + if (!post.Group) + { + if (!Spawn(post)) return Fail("scout group spawn failed"); + return ERR_PrepareResult.PENDING; // One group per preparation frame. + } + ERR_PrepareResult stock = Stock(post); + if (stock == ERR_PrepareResult.FAILED) return stock; + if (stock == ERR_PrepareResult.PENDING) pending = true; + } + if (pending) return ERR_PrepareResult.PENDING; + m_Ready = true; + return ERR_PrepareResult.READY; + } + void Stop() + { + if (m_Stopped) return; + m_Stopped = true; + // GameMode owns bodies, groups, equipment and waypoints. No new work is queued. + } +} + +// Classify only an already visible, captured coordinate against real road +// geometry. Vehicles in the air and nearby verges are not reported as on-road. +class ERR_ScoutRoad +{ + static bool OnSegment(vector point, vector start, vector end, float width) + { + vector delta = end - start; delta[1] = 0; + float lengthSquared = vector.Dot(delta, delta); + if (lengthSquared < 0.01 || width <= 0) return false; + vector offset = point - start; offset[1] = 0; + float fraction = Math.Clamp(vector.Dot(offset, delta) / lengthSquared, 0, 1); + vector nearest = vector.Lerp(start, end, fraction); + return vector.DistanceXZ(point, nearest) <= width * 0.5 && Math.AbsFloat(point[1] - nearest[1]) <= 3; + } + static string Describe(vector observed) + { + SCR_AIWorld world = SCR_AIWorld.Cast(GetGame().GetAIWorld()); + if (!world || !world.GetRoadNetworkManager()) return "road unknown"; + BaseRoad road; float distance; + world.GetRoadNetworkManager().GetClosestRoad(observed, road, distance, skipNavlinks: true); + if (!road) return "off road"; + array points = {}; road.GetPoints(points); + if (points.Count() < 2 || points.Count() > 1024) return "road unknown"; + for (int i = 1; i < points.Count(); i++) if (OnSegment(observed, points[i - 1], points[i], road.GetWidth())) return "on road"; + return "off road"; + } +} + +// Average observed ground motion, never a read of the target's current physics. +class ERR_ScoutMotion +{ + static void Estimate(ERR_HQReport report, ERR_HQReport previous) + { + report.HasVelocity = false; report.Velocity = vector.Zero; + if (!previous || !report.Target || report.Target != previous.Target || report.Source != previous.Source || report.Distress || previous.Distress) return; + float seconds = (report.ObservedAt - previous.ObservedAt) / 1000; + if (seconds > 30 || !ERR_HQMemoryRules.MotionCredible(seconds, vector.DistanceXZ(previous.Position, report.Position), previous.TravelMode, report.TravelMode)) return; + report.Velocity = (report.Position - previous.Position) / seconds; + report.Velocity[1] = 0; + report.HasVelocity = true; + } +} diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoyService.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoyService.c new file mode 100644 index 0000000..7da7eb5 --- /dev/null +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoyService.c @@ -0,0 +1,227 @@ +// Full supply convoys reuse finite vehicle creation and cargo ownership. The +// legacy finite-route service remains available for isolated migration fixtures. +class ERR_SupplyConvoyService : ERR_ConvoyService +{ + void ERR_SupplyConvoyService(ERR_GameMode mode, ERR_ConvoyPool pool) {} + protected ref ERR_SupplyConvoyTask m_Creating; + protected ref array m_Bases = {}; + void SetBases(array bases) { m_Bases.Copy(bases); } + protected override ERR_ConvoyTask NewTask() + { + m_Creating = new ERR_SupplyConvoyTask(); m_Creating.Bases.Copy(m_Bases); + return m_Creating; + } + protected override ERR_ConvoyVehicle NewVehicle() { return new ERR_SupplyConvoyVehicle(); } + protected override bool FillCrew(ERR_ConvoyVehicle unit) + { + if (m_Creating) m_Creating.Starts.Insert(unit.Entity.GetOrigin()); + if (unit.Index != 2) return super.FillCrew(unit); + array all = {}, drivers = {}, cargo = {}; + if (!m_Creating || !ERR_ConvoyRules.CollectSeats(unit.Entity, all)) return false; + foreach (BaseCompartmentSlot seat : all) + { + if (!seat || seat.IsOccupied() || !seat.IsCompartmentAccessible()) continue; + if (seat.GetType() == ECompartmentType.PILOT) drivers.Insert(seat); + if (seat.GetType() == ECompartmentType.CARGO) cargo.Insert(seat); + } + if (drivers.Count() != 1 || cargo.Count() != 14) return false; + AIGroup nativeGroup = unit.Group; + IEntity driver = drivers[0].SpawnCharacterInCompartment(ERR_ConvoyResources.Soldier(), nativeGroup, ERR_ConvoyResources.GroupPrefab()); + if (driver) { m_Mode.Own(driver); unit.Members.Insert(driver); unit.Seats.Insert(drivers[0]); unit.Driver = driver; } + if (!driver || nativeGroup != unit.Group) return false; + for (int index = 0; index < 2; index++) + { + ERR_SupplyTeam team = new ERR_SupplyTeam(); m_Creating.Teams.Insert(team); + team.Group = SCR_AIGroup.Cast(ERR_Actors.Spawn(ERR_ConvoyResources.GroupPrefab(), unit.Entity.GetOrigin())); + if (team.Group) m_Mode.Own(team.Group); + if (!ERR_ConvoyRules.EmptyCrewTemplate(team.Group)) return false; + AIFormationComponent formation = AIFormationComponent.Cast(team.Group.FindComponent(AIFormationComponent)); + if (formation) formation.SetFormation("Line"); + nativeGroup = team.Group; + for (int slot = index; slot < 14; slot += 2) + { + IEntity actor = cargo[slot].SpawnCharacterInCompartment(ERR_ConvoyResources.Soldier(), nativeGroup, ERR_ConvoyResources.GroupPrefab()); + if (actor) { m_Mode.Own(actor); team.Members.Insert(actor); team.Seats.Insert(cargo[slot]); } + if (!actor || nativeGroup != team.Group) return false; + } + } + return true; + } + protected void Wake(SCR_AIGroup group) + { + if (!group) return; + group.SetPermanentLOD(0); group.ActivateAI(); + array agents = {}; group.GetAgents(agents); + foreach (AIAgent agent : agents) if (agent) { agent.SetPermanentLOD(0); agent.ActivateAI(); } + } + protected override bool Admit(ERR_ConvoyTask task, float now) + { + ERR_SupplyConvoyTask supply = ERR_SupplyConvoyTask.Cast(task); + if (!supply || supply.Teams.Count() != 2) return false; + // Distant native agents must wake before compartment membership can settle. + foreach (ERR_ConvoyVehicle vehicle : supply.Vehicles) + { + Wake(vehicle.Group); + foreach (IEntity member : vehicle.Members) ERR_ConvoyMountedCrew.Hold(member, vehicle.Entity); + } + foreach (ERR_SupplyTeam infantry : supply.Teams) Wake(infantry.Group); + if (!super.Admit(supply, now)) return false; + SCR_AIVehicleUsageComponent truck = SCR_AIVehicleUsageComponent.Cast(supply.Vehicles[2].Entity.FindComponent(SCR_AIVehicleUsageComponent)); + for (int index = 0; index < supply.Teams.Count(); index++) + { + ERR_SupplyTeam team = supply.Teams[index]; + if (team.Registered) continue; + if (!team.Group || team.Group.GetFaction() != m_Mode.EnemyFaction() || team.Members.Count() != 7) return false; + array agents = {}; team.Group.GetAgents(agents); + if (agents.Count() != 7) return false; + foreach (AIAgent agent : agents) + if (!agent || !team.Members.Contains(agent.GetControlledEntity()) || !ERR_Actors.CanFight(agent.GetControlledEntity()) || ERR_Actors.Player(agent.GetControlledEntity())) return false; + for (int slot = 0; slot < 7; slot++) + if (team.Seats[slot].GetOccupant() != team.Members[slot] || ERR_Actors.Group(team.Members[slot]) != team.Group) return false; + SCR_AIGroupUtilityComponent utility = team.Group.GetGroupUtilityComponent(); + if (!utility || !truck) return false; + utility.AddUsableVehicle(truck); + ERR_ForceRecord record = m_Mode.Forces().Register(supply.Receipt.SourceId + "-vehicle-" + (index + 6).ToString(), ERR_ForceKind.CONVOY, team.Group.GetOrigin(), 7, null, team.Group, now); + if (!record || !m_Pool.BindRecord(supply.Receipt, index + 6, record)) { supply.Stop(m_Mode, "infantry ledger admission failed; no replacement"); return false; } + record.Pinned = true; team.Registered = true; + m_Mode.RegisterGroup(team.Group); + ERR_HQ hq = ERR_HQ.Cast(m_Mode.Command()); + if (hq) hq.ReserveGroup(team.Group); + team.Group.SetPermanentLOD(0); team.Group.ActivateAI(); + foreach (AIAgent active : agents) { active.SetPermanentLOD(0); active.ActivateAI(); } + } + supply.Tactics = new ERR_SupplyConvoyTactics(m_Mode, supply); + supply.TravelDeadline = now + 600000; + return true; + } + protected override void IssueCargo(ERR_ConvoyTask task) + { + ERR_SupplyConvoyTask supply = ERR_SupplyConvoyTask.Cast(task); + if (!supply || supply.CargoIssued || supply.Stopped) return; + supply.CargoIssued = true; + InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(supply.Vehicles[1].Entity.FindComponent(InventoryStorageManagerComponent)); + if (!inventory) { supply.MagazinesIssued = true; return; } + ERR_Inventory.Items(inventory, supply.CargoBefore); + SCR_EntityCatalogManagerComponent catalog = SCR_EntityCatalogManagerComponent.GetInstance(); + array weapons = {}; + if (catalog) catalog.GetFactionArsenalItems(weapons, SCR_Faction.Cast(m_Mode.EnemyFaction()), -1, SCR_EArsenalItemMode.WEAPON); + for (int i = 0; i < 8; i++) + { + ResourceName prefab = ERR_ConvoyResources.Rifle(); + if (!weapons.IsEmpty()) + { + SCR_ArsenalItem choice = weapons[Math.RandomInt(0, weapons.Count())]; + if (choice) prefab = choice.GetItemResourceName(); + } + ERR_ConvoyCargoCallback operation = new ERR_ConvoyCargoCallback(); operation.Prefab = prefab; supply.Cargo.Insert(operation); + if (!inventory.TrySpawnPrefabToStorage(prefab, null, -1, EStoragePurpose.PURPOSE_DEPOSIT, operation)) operation.Finished = true; + } + } + protected void IssueMagazines(ERR_SupplyConvoyTask task, float now) + { + if (task.MagazinesIssued || !task.CargoIssued || task.Stopped) return; + foreach (ERR_ConvoyCargoCallback operation : task.Cargo) + if (!operation.Finished && now < task.Deadline + 30000) return; + task.MagazinesIssued = true; + InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(task.Vehicles[1].Entity.FindComponent(InventoryStorageManagerComponent)); + if (!inventory) return; + array items = {}; ERR_Inventory.Items(inventory, items); + array expected = {}; + foreach (ERR_ConvoyCargoCallback weaponOperation : task.Cargo) + if (weaponOperation.Finished && weaponOperation.Succeeded) expected.Insert(weaponOperation.Prefab); + int issued; + foreach (IEntity item : items) + { + if (!item || task.CargoBefore.Contains(item) || !item.GetPrefabData()) continue; + int match = expected.Find(item.GetPrefabData().GetPrefabName()); + if (match < 0) continue; + expected.Remove(match); + BaseWeaponComponent weapon = BaseWeaponComponent.Cast(item.FindComponent(BaseWeaponComponent)); + if (!weapon) continue; + array muzzles = {}; weapon.GetMuzzlesList(muzzles); + foreach (BaseMuzzleComponent muzzle : muzzles) + { + ResourceName magazine = muzzle.GetDefaultMagazineOrProjectileName(); + if (magazine.IsEmpty()) continue; + for (int mag = 0; mag < 6 && issued < 96; mag++) + { + ERR_ConvoyCargoCallback load = new ERR_ConvoyCargoCallback(); load.Prefab = magazine; task.Cargo.Insert(load); issued++; + if (!inventory.TrySpawnPrefabToStorage(magazine, null, -1, EStoragePurpose.PURPOSE_DEPOSIT, load)) load.Finished = true; + } + } + } + task.CargoBefore.Clear(); + ERR_HQ.Event("CONVOY CARGO", task.Receipt.SourceId + ": eight weapon requests and matching finite ammunition batch; no refill"); + } + protected bool Captured(ERR_SupplyConvoyTask task) + { + foreach (ERR_ConvoyVehicle vehicle : task.Vehicles) + if (ERR_ConvoyRules.Captured(vehicle.Entity, vehicle.Group)) return true; + foreach (ERR_SupplyTeam team : task.Teams) + { + if (team.Group && team.Group.GetPlayerCount(true) > 0) return true; + foreach (IEntity member : team.Members) if (ERR_Actors.Player(member)) return true; + } + return false; + } + protected void Circuit(ERR_SupplyConvoyTask task, float now) + { + bool surviving, pending; + foreach (ERR_ConvoyVehicle vehicle : task.Vehicles) + { + if (!vehicle.Released && now >= task.TravelDeadline && task.TravelDeadline > 0) { vehicle.ClearOrder(); vehicle.Arrived = true; } + if (!vehicle.Released && task.Legs > 0 && vector.Distance(vehicle.Entity.GetOrigin(), task.Bases[task.LastBase]) <= 250) + { vehicle.ClearOrder(); vehicle.Arrived = true; } + vehicle.Tick(m_Mode, task.Route, now); + if (!vehicle.Released) { surviving = true; if (!vehicle.Arrived) pending = true; } + } + if (!surviving) { task.Stop(m_Mode, "no surviving drivable convoy vehicles"); return; } + if (pending) return; + if (!task.Waiting) { task.Waiting = true; task.Departure = now + Math.RandomFloat(45000, 90000); return; } + if (now < task.Departure || task.Bases.Count() < 2) return; + int next = ERR_SupplyConvoyRules.NextBase(task.Bases.Count(), task.LastBase, Math.RandomInt(0, task.Bases.Count() - 1)); + if (task.LastBase < 0) next = Math.RandomInt(0, task.Bases.Count()); + if (next < 0) return; + ERR_ForceRoute leg = new ERR_ForceRoute(); leg.Add(task.Bases[next]); leg.Seal(); + task.Route = leg; task.LastBase = next; task.Legs++; task.Waiting = false; task.TravelDeadline = now + 600000; + foreach (ERR_ConvoyVehicle departure : task.Vehicles) + { + if (departure.Released) continue; + departure.ClearOrder(); departure.RouteIndex = 0; departure.Arrived = false; + } + ERR_HQ.Event("CONVOY DEPARTURE", string.Format("%1 leg=%2 base=%3; native road navigation", task.Receipt.SourceId, task.Legs, task.Bases[next])); + } + override void Tick(float now) + { + if (!Current() || !ERR_ForceRules.Finite(now)) return; + foreach (ERR_ConvoyTask baseTask : m_Tasks) + { + ERR_SupplyConvoyTask task = ERR_SupplyConvoyTask.Cast(baseTask); + if (!task || task.Stopped || now < task.NextCheck) continue; + task.NextCheck = now + 1000; + if (Captured(task)) { task.Stop(m_Mode, "player captured convoy vehicle or crew"); continue; } + if (!task.Ready) + { + if (now >= task.Deadline) { task.Stop(m_Mode, "native crew readiness expired; partial convoy retained"); continue; } + if (!Admit(task, now)) continue; + task.Ready = true; IssueCargo(task); + } + IssueMagazines(task, now); + foreach (ERR_ConvoyVehicle checked : task.Vehicles) + if (!checked.Released && !checked.CrewValid(m_Mode)) checked.Release(m_Mode); + if (task.Tactics && task.Tactics.Tick(now)) continue; + Circuit(task, now); + } + } + override bool ApplyCombatOrder(ERR_ConvoyTask task, ERR_ConvoyCombatOrder order, float now) + { + ERR_SupplyConvoyTask supply = ERR_SupplyConvoyTask.Cast(task); + if (!supply || !supply.Tactics || !order) return false; + // Fresh delivered sightings may extend combat or interrupt reboarding. Only + // this controller may resume while the two infantry teams are still out. + if (!order.Hold && supply.Tactics.State() != 0) return false; + bool accepted = super.ApplyCombatOrder(task, order, now); + if (accepted && order.Hold) supply.Tactics.Report(order.Position, order.ObservedAt, now); + return accepted; + } +} diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoySystem.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoySystem.c new file mode 100644 index 0000000..dd0fbe8 --- /dev/null +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoySystem.c @@ -0,0 +1,133 @@ +class ERR_SupplyConvoyRules +{ + static int NextBase(int count, int last, int roll) + { + if (count < 2 || last < -1 || last >= count || roll < 0 || roll >= count - 1) return -1; + if (last >= 0 && roll >= last) return roll + 1; + return roll; + } + static bool Separated(vector position, array starts, float distance) + { + foreach (vector start : starts) if (vector.DistanceXZ(start, position) < distance) return false; + return true; + } +} + +// Original finite startup target, eight bounded road candidates per attempt, +// separated initial positions and base-to-base circulation; never replacement spawns. +class ERR_SupplyConvoySystem +{ + protected ERR_GameMode m_Mode; + protected ERR_ConvoyPool m_Pool; + protected ERR_SupplyConvoyService m_Service; + protected ref array m_Bases = {}; + protected ref array m_Starts = {}; + protected int m_Target; + protected int m_Attempts; + protected bool m_Automatic; + protected bool m_Stopped; + protected float m_Began = -1; + protected float m_Next; + protected string m_Reason; + void ERR_SupplyConvoySystem(ERR_GameMode mode, ERR_ConvoyPool pool, ERR_SupplyConvoyService service, int target, bool automatic) + { + m_Mode = mode; m_Pool = pool; m_Service = service; + m_Target = Math.Clamp(target, 0, 20); m_Automatic = automatic; + } + int Target() { return m_Target; } + static bool Approach(vector center, out vector position, float radius = 500) + { + vector angles; + return ApproachDirected(center, position, angles, radius); + } + static bool ApproachDirected(vector center, out vector position, out vector angles, float radius = 500) + { + SCR_AIWorld world = SCR_AIWorld.Cast(GetGame().GetAIWorld()); + if (!world || !world.GetRoadNetworkManager()) return false; + array roads = {}; + world.GetRoadNetworkManager().GetRoadsInAABB(center - Vector(radius, 1000, radius), center + Vector(radius, 1000, radius), roads); + if (roads.Count() > 128) return false; + float nearest = radius; bool found; + foreach (BaseRoad road : roads) + { + if (!road || road.GetWidth() < 4) continue; + array points = {}; road.GetPoints(points); + if (points.Count() > 1024) continue; + for (int i = 1; i < points.Count(); i++) + { + vector delta = points[i] - points[i - 1]; delta[1] = 0; + float length = vector.Dot(delta, delta); + if (length < 0.01) continue; + vector offset = center - points[i - 1]; offset[1] = 0; + float fraction = Math.Clamp(vector.Dot(offset, delta) / length, 0, 1); + vector candidate = ERR_Actors.Ground(vector.Lerp(points[i - 1], points[i], fraction)); + float distance = vector.DistanceXZ(center, candidate); + if (distance >= nearest || ChimeraWorldUtils.TryGetWaterSurfaceSimple(GetGame().GetWorld(), candidate)) continue; + nearest = distance; position = candidate; angles = Vector(Math.Atan2(delta[0], delta[2]) * Math.RAD2DEG, 0, 0); found = true; + } + } + return found; + } + protected void FindBases() + { + m_Bases.Clear(); + if (!m_Mode.Sites()) return; + for (int i = 0; i < m_Mode.Sites().Count(); i++) + { + ERR_SiteRuntime site = m_Mode.Sites().At(i); + if (!site || !site.Definition) continue; + ERR_LocationKind kind = site.Definition.Kind; + if (kind != ERR_LocationKind.OUTPOST && kind != ERR_LocationKind.DEPOT && kind != ERR_LocationKind.RADIO) continue; + if (site.Group && site.Group.GetFaction() != m_Mode.EnemyFaction()) continue; + vector approach; + if (Approach(site.Definition.Position, approach) && ERR_SupplyConvoyRules.Separated(approach, m_Bases, 300)) m_Bases.Insert(approach); + } + m_Service.SetBases(m_Bases); + } + bool StartOne() + { + if (m_Stopped || !Replication.IsServer() || !m_Mode || m_Mode != ERR_GameMode.Get() || !m_Mode.Active() || m_Service.Count() >= m_Target) return false; + if (m_Bases.Count() < 2) FindBases(); + if (m_Bases.Count() < 2) { m_Reason = "waiting for two friendly military road approaches"; return false; } + if (!GetGame().GetWorldEntity()) return false; + vector low, high; GetGame().GetWorldEntity().GetWorldBounds(low, high); + float separation = Math.Min(1000, Math.Max(high[0] - low[0], high[2] - low[2]) * 0.1); + for (int attempt = 0; attempt < 8; attempt++) + { + vector seed = Vector(Math.RandomFloat(low[0], high[0]), 0, Math.RandomFloat(low[2], high[2])); + // A nearby base is the first candidate; remaining attempts cover the island. + if (attempt == 0) seed = m_Bases[(m_Attempts + m_Service.Count()) % m_Bases.Count()]; + seed = ERR_Actors.Ground(seed); + array positions, angles; ERR_ForceRoute route; + if (!ERR_ConvoyRoadPlan.Build(seed, positions, angles, route) || !ERR_SupplyConvoyRules.Separated(positions[0], m_Starts, separation)) continue; + string source = "supply-convoy-" + (m_Service.Count() + 1).ToString(); + ERR_ConvoyReceipt receipt = m_Pool.Reserve(source); + if (!receipt || receipt.Consumed) { m_Reason = "configured convoy capacity or shared force budget unavailable"; return false; } + ERR_ConvoyTask task = m_Service.Dispatch(receipt, positions, angles, route, GetGame().GetWorld().GetWorldTime()); + if (!task) { m_Reason = "road preflight changed; no entities created"; return false; } + m_Starts.Insert(positions[0]); + m_Reason = "finite convoy slot deployed"; + if (task.Stopped) m_Reason = "partial startup retained; this slot cannot respawn"; + ERR_HQ.Event("CONVOY STARTUP", string.Format("%1/%2 at %3: %4", m_Service.Count(), m_Target, positions[0], m_Reason)); + return !task.Stopped; + } + m_Reason = "no clear separated road formation in this bounded survey"; + return false; + } + void Tick(float now, bool admitted) + { + if (m_Stopped || !m_Automatic || m_Target == 0 || m_Attempts >= 120 || m_Service.Count() >= m_Target || !ERR_ForceRules.Finite(now) || now < 0) return; + if (m_Began < 0) { m_Began = now; m_Next = now + 30000; } + if (now < m_Next) return; + m_Next = now + 5000; + if (!admitted) { m_Reason = "waiting for existing force admission"; return; } + m_Attempts++; + StartOne(); + if (m_Attempts == 120 && m_Service.Count() < m_Target) ERR_HQ.Event("CONVOY STARTUP", "bounded survey exhausted; deployed slots retained without replacement"); + } + string Status() + { + return string.Format("This round: %1/%2 convoy slots; automatic=%3, startup attempts=%4/120; %5", m_Service.Count(), m_Target, m_Automatic, m_Attempts, m_Reason); + } + void Stop() { m_Stopped = true; } +} diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoyTactics.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoyTactics.c new file mode 100644 index 0000000..956639e --- /dev/null +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_SupplyConvoyTactics.c @@ -0,0 +1,404 @@ +// Original convoy tactics adapted to native AI waypoints. No old framework hooks. +class ERR_SupplyTeam +{ + SCR_AIGroup Group; + ref array Members = {}; + ref array Seats = {}; + ref array Orders = {}; + bool Registered; + bool Released; + vector OrderedContact; + void Clear() + { + foreach (AIWaypoint waypoint : Orders) + { + if (Group && waypoint) Group.RemoveWaypoint(waypoint); + if (waypoint) SCR_EntityHelper.DeleteEntityAndChildren(waypoint); + } + Orders.Clear(); + } + void Add(AIWaypoint waypoint) + { + if (!waypoint) return; + if (!Group || Released) { SCR_EntityHelper.DeleteEntityAndChildren(waypoint); return; } + Orders.Insert(waypoint); Group.AddWaypoint(waypoint); + } + void Release(ERR_GameMode mode) + { + if (Released) return; + Released = true; Clear(); + if (!Group) return; + if (mode && mode.Command()) mode.Command().UnregisterGroup(Group); + ERR_ForceRecord record; + if (mode && mode.Forces()) record = mode.Forces().FindGroup(Group); + if (record) record.Pinned = false; + Group.SetPermanentLOD(-1); + array agents = {}; Group.GetAgents(agents); + foreach (AIAgent agent : agents) if (agent) agent.SetPermanentLOD(-1); + } + bool Living() + { + foreach (IEntity member : Members) + if (ERR_Actors.CanFight(member) && !ERR_Actors.Player(member) && ERR_Actors.Group(member) == Group) return true; + return false; + } + bool Aboard(Vehicle truck, bool required) + { + foreach (IEntity member : Members) + { + if (!ERR_Actors.CanFight(member) || ERR_Actors.Group(member) != Group) continue; + if ((CompartmentAccessComponent.GetVehicleIn(member) == truck) != required) return false; + } + return true; + } +} + +// Only the exact original vehicle crews are retained. Infantry never enters this map. +class ERR_ConvoyMountedCrew +{ + protected static ref map s_Crews = new map(); + static void Hold(IEntity actor, Vehicle vehicle) { if (actor && vehicle) s_Crews.Set(actor, vehicle); } + static void Release(IEntity actor) { if (actor) s_Crews.Remove(actor); } + static bool Retain(IEntity actor, IEntity vehicle) + { + if (!actor || !vehicle || !s_Crews.Contains(actor) || s_Crews.Get(actor) != vehicle || ERR_Actors.Player(actor) || !ERR_Actors.CanFight(actor)) return false; + if (CompartmentAccessComponent.GetVehicleIn(actor) != vehicle) return false; + SCR_VehicleDamageManagerComponent damage = SCR_VehicleDamageManagerComponent.Cast(vehicle.FindComponent(SCR_VehicleDamageManagerComponent)); + // Let native emergency abandonment take over on critical damage or drivetrain failure. + return damage && damage.GetState() != EDamageState.DESTROYED && damage.GetHealthScaled() > 0.25 && damage.GetEngineFunctional() && damage.GetGearboxFunctional(); + } + static bool RetainGroup(SCR_AIGroup group, IEntity vehicle) + { + if (!group || group.GetPlayerCount(true) > 0) return false; + IEntity leader = group.GetLeaderEntity(); + if (!leader) return false; + if (!vehicle) vehicle = CompartmentAccessComponent.GetVehicleIn(leader); + return Retain(leader, vehicle); + } + +} +modded class SCR_AIGetOutVehicle +{ + override float CustomEvaluate() + { + if (m_Utility && ERR_ConvoyMountedCrew.Retain(m_Utility.m_OwnerEntity, m_Vehicle.m_Value)) return 0; + return super.CustomEvaluate(); + } + override float EvaluatePriorityLevel() + { + if (m_Utility && ERR_ConvoyMountedCrew.Retain(m_Utility.m_OwnerEntity, m_Vehicle.m_Value)) return 0; + return super.EvaluatePriorityLevel(); + } +} +modded class SCR_AIGetOutActivity +{ + override float CustomEvaluate() + { + if (m_Utility && ERR_ConvoyMountedCrew.RetainGroup(m_Utility.m_Owner, m_Vehicle.m_Value)) return 0; + return super.CustomEvaluate(); + } + override float EvaluatePriorityLevel() + { + if (m_Utility && ERR_ConvoyMountedCrew.RetainGroup(m_Utility.m_Owner, m_Vehicle.m_Value)) return 0; + return super.EvaluatePriorityLevel(); + } +} + +class ERR_SupplyConvoyVehicle : ERR_ConvoyVehicle +{ + override bool CrewValid(ERR_GameMode mode) + { + if (!Group || !Entity || !ERR_Actors.Alive(Entity) || Group.GetFaction() != mode.EnemyFaction() || !ERR_Actors.CanFight(Driver)) return false; + if (ERR_Actors.Player(Driver) || ERR_Actors.Group(Driver) != Group || !ERR_ConvoyRules.PartOf(CompartmentAccessComponent.GetVehicleIn(Driver), Entity)) return false; + foreach (IEntity member : Members) + if (ERR_Actors.Alive(member) && (ERR_Actors.Player(member) || ERR_Actors.Group(member) != Group)) return false; + return true; + } + override void Release(ERR_GameMode mode) + { + foreach (IEntity member : Members) ERR_ConvoyMountedCrew.Release(member); + super.Release(mode); + } +} + +class ERR_SupplyConvoyTask : ERR_ConvoyTask +{ + ref array Teams = {}; + ref ERR_SupplyConvoyTactics Tactics; + ref array Bases = {}; + ref array Starts = {}; + int LastBase = -1; + int Legs; + float Departure; + float TravelDeadline; + bool Waiting; + bool MagazinesIssued; + ref array CargoBefore = {}; + override void Stop(ERR_GameMode mode, string reason) + { + if (Stopped) return; + if (Tactics) Tactics.Stop(); + foreach (ERR_SupplyTeam team : Teams) team.Release(mode); + super.Stop(mode, reason); + } +} + +class ERR_SupplyConvoyTactics +{ + protected ERR_GameMode m_Mode; + protected ERR_SupplyConvoyTask m_Task; + protected ref array m_Support = {}; + protected int m_State; // mounted, fighting, reboarding + protected vector m_Contact; + protected vector m_Forward; + protected vector m_Left; + protected float m_LastContact = -1; + protected float m_NextOrders; + protected float m_BoardDeadline; + protected bool m_TruckWithdrawn; + protected float m_NextDismount; + protected int m_DismountAttempts; + protected bool m_Stopped; + void ERR_SupplyConvoyTactics(ERR_GameMode mode, ERR_SupplyConvoyTask task) + { + m_Mode = mode; m_Task = task; + foreach (ERR_ConvoyVehicle vehicle : task.Vehicles) + { + ERR_SupplyTeam order = new ERR_SupplyTeam(); order.Group = vehicle.Group; + m_Support.Insert(order); + foreach (IEntity member : vehicle.Members) ERR_ConvoyMountedCrew.Hold(member, vehicle.Entity); + } + } + int State() { return m_State; } + static AIWaypoint Move(vector position, float radius = 20) + { + AIWaypoint waypoint = AIWaypoint.Cast(ERR_Actors.Spawn(ERR_Resources.MoveWaypoint(), position)); + if (waypoint) waypoint.SetCompletionRadius(radius); + return waypoint; + } + static AIWaypoint Board(Vehicle truck, bool enter) + { + if (!truck) return null; + ResourceName prefab = "{C40316EE26846CAB}Prefabs/AI/Waypoints/AIWaypoint_GetOut.et"; + if (enter) prefab = "{712F4795CF8B91C7}Prefabs/AI/Waypoints/AIWaypoint_GetIn.et"; + SCR_BoardingWaypoint waypoint = SCR_BoardingWaypoint.Cast(ERR_Actors.Spawn(prefab, truck.GetOrigin())); + if (!waypoint) return null; + waypoint.SetAllowance(false, false, true); + // Native defaults may complete when only the leader has left/boarded. + waypoint.SetCompletionType(EAIWaypointCompletionType.All); + // The waypoint approach applies to the whole team; leave space around the truck. + waypoint.SetCompletionRadius(100); + SCR_BoardingEntityWaypoint specific = SCR_BoardingEntityWaypoint.Cast(waypoint); + if (specific) specific.SetEntity(truck); + return waypoint; + } + protected bool Usable(int index) + { + return index >= 0 && index < m_Task.Vehicles.Count() && !m_Task.Vehicles[index].Released && m_Task.Vehicles[index].CrewValid(m_Mode); + } + protected bool InfantryAboard(bool required) + { + foreach (ERR_SupplyTeam team : m_Task.Teams) + if (!team.Released && !team.Aboard(m_Task.Vehicles[2].Entity, required)) return false; + return true; + } + protected float DistanceToConvoy(vector position) + { + float distance = 1e20; + foreach (ERR_ConvoyVehicle vehicle : m_Task.Vehicles) + if (!vehicle.Released && vehicle.Entity) distance = Math.Min(distance, vector.DistanceXZ(vehicle.Entity.GetOrigin(), position)); + return distance; + } + protected bool Observe(SCR_AIGroup group, out vector position, inout float nearest) + { + if (!group || !group.GetGroupUtilityComponent()) return false; + SCR_AIGroupPerception perception = group.GetGroupUtilityComponent().m_Perception; + PerceptionManager manager = GetGame().GetPerceptionManager(); + if (!perception || !manager) return false; + bool found; + foreach (SCR_AITargetInfo target : perception.m_aTargets) + { + if (!target || !target.m_Entity || !target.m_Faction || !group.GetFaction().IsFactionEnemy(target.m_Faction)) continue; + float age = manager.GetTime() - target.m_fTimestamp; + if (target.m_eCategory != EAITargetInfoCategory.IDENTIFIED || age < 0 || age > 5) continue; + float distance = DistanceToConvoy(target.m_vWorldPos); + if (distance > nearest || !group.GetGroupUtilityComponent().IsPositionAllowed(target.m_vWorldPos)) continue; + position = target.m_vWorldPos; nearest = distance; found = true; + } + return found; + } + // Only production native observations or a delivered HQ snapshot may call this. + void Report(vector position, float observed, float now) + { + if (m_Stopped || !ERR_ForceRules.Finite(now) || !ERR_ForceRules.Finite(observed) || !ERR_ForceRules.FiniteVector(position) || observed < 0 || observed > now || now - observed > 60000 || observed < m_LastContact) return; + m_LastContact = observed; + if (m_State != 1) Start(position, now); + else if (vector.DistanceXZ(position, m_Contact) > 40 && now >= m_NextOrders) { m_Contact = position; Orders(false, now); } + } + protected bool FootPosition(ERR_SupplyTeam team, vector desired, out vector position) + { + if (!team.Group || !team.Group.GetGroupUtilityComponent()) return false; + for (int i = 0; i < 8; i++) + { + vector point = desired; + if (i > 0) point += Vector(Math.RandomFloat(-12, 12), 0, Math.RandomFloat(-12, 12)); + point = ERR_Actors.Ground(point); + if (!ChimeraWorldUtils.TryGetWaterSurfaceSimple(GetGame().GetWorld(), point) && team.Group.GetGroupUtilityComponent().IsPositionAllowed(point) && SCR_WorldTools.TraceCilinderUtil(point + "0 1 0", 1, 2)) { position = point; return true; } + } + return false; + } + protected void Flank(int index, bool dismount) + { + ERR_SupplyTeam team = m_Task.Teams[index]; + if (team.Released || !team.Living()) return; + // Preserve an in-progress native all-member dismount across contact refreshes. + if (!team.Aboard(m_Task.Vehicles[2].Entity, false) && SCR_BoardingWaypoint.Cast(team.Group.GetCurrentWaypoint())) return; + team.Clear(); team.OrderedContact = m_Contact; + if (dismount && !team.Aboard(m_Task.Vehicles[2].Entity, false)) team.Add(Board(m_Task.Vehicles[2].Entity, false)); + float side = 1; if (index == 1) side = -1; + vector approach, sector; + if (!FootPosition(team, m_Contact - m_Forward * 80 + m_Left * (110 * side), approach) || !FootPosition(team, m_Contact + m_Left * (70 * side), sector)) return; + team.Add(Move(approach, 15)); + AIWaypoint search = AIWaypoint.Cast(ERR_Actors.Spawn(ERR_Resources.SearchWaypoint(), sector)); + if (search) search.SetCompletionRadius(30); + team.Add(search); + } + protected bool SupportPosition(int index, vector desired, out vector position) + { + ERR_ConvoyVehicle vehicle = m_Task.Vehicles[index]; + SCR_AIGroupUtilityComponent utility = vehicle.Group.GetGroupUtilityComponent(); + if (!utility) return false; + vector road; + if (ERR_SupplyConvoySystem.Approach(desired, road, 70) && vector.Dot(road - m_Contact, m_Forward) <= -100 && utility.IsPositionAllowed(road)) { position = road; return true; } + if (index == 1 || index == 2) return false; + // Original armed escorts can seek a nearby open firing position off the road. + ERR_ConvoyPlacement placement = new ERR_ConvoyPlacement(); + for (int attempt = 0; attempt < 8; attempt++) + { + vector candidate = desired; + if (attempt > 0) candidate += Vector(Math.RandomFloat(-15, 15), 0, Math.RandomFloat(-15, 15)); + candidate = ERR_Actors.Ground(candidate); + if (vector.Dot(candidate - m_Contact, m_Forward) > -100 || !utility.IsPositionAllowed(candidate)) continue; + if (placement.Clear(candidate, ERR_ForceRules.Heading(candidate, m_Contact, 0))) { position = candidate; return true; } + } + return false; + } + protected void Support(int index, bool holdTruck) + { + ERR_SupplyTeam orders = m_Support[index]; orders.Clear(); + if (!Usable(index)) return; + ERR_ConvoyVehicle vehicle = m_Task.Vehicles[index]; + // An idle mounted driver stops without a Defend order asking the crew to exit. + if (index == 2 && holdTruck) return; + float rear = 180, side; + if (index == 0) side = 150; + if (index == 3) side = -150; + if (index == 5) rear = 250; + if (index == 1) { rear = 350; side = 40; } + if (index == 2) { rear = 310; side = -40; } + vector support = vehicle.Entity.GetOrigin(); + vector desired = m_Contact - m_Forward * rear + m_Left * side; + vector chosen; + if (SupportPosition(index, desired, chosen)) support = chosen; + if (vector.DistanceXZ(vehicle.Entity.GetOrigin(), support) > 20) orders.Add(Move(support)); + if (index == 1 || index == 2) return; + AIWaypoint defend = AIWaypoint.Cast(ERR_Actors.Spawn(ERR_Resources.DefendWaypoint(), support)); + if (defend) defend.SetCompletionRadius(20); + orders.Add(defend); + } + protected void Clear() + { + foreach (ERR_SupplyTeam orders : m_Support) orders.Clear(); + foreach (ERR_SupplyTeam team : m_Task.Teams) team.Clear(); + } + protected void Orders(bool dismount, float now) + { + for (int i = 0; i < m_Task.Vehicles.Count(); i++) Support(i, !m_TruckWithdrawn); + for (int i = 0; i < m_Task.Teams.Count(); i++) Flank(i, dismount); + m_NextOrders = now + 30000; + } + protected void Start(vector contact, float now) + { + Clear(); m_State = 1; m_Contact = contact; m_TruckWithdrawn = false; + vector origin; + foreach (ERR_ConvoyVehicle vehicle : m_Task.Vehicles) + { + vehicle.ClearOrder(); + if (!vehicle.Released) vehicle.Combat.Held = true; + if (!vehicle.Released) origin = vehicle.Entity.GetOrigin(); + } + m_Forward = contact - origin; m_Forward[1] = 0; + if (m_Forward.Length() < 1) m_Forward = "0 0 1"; + m_Forward.Normalize(); m_Left = Vector(-m_Forward[2], 0, m_Forward[0]); + Orders(true, now); + m_DismountAttempts = 0; m_NextDismount = now + 10000; + ERR_HQ.Event("CONVOY COMBAT", m_Task.Receipt.SourceId + ": infantry flank left/right; escorts cover; troop truck holds for dismount"); + } + protected void Finish(float now) + { + Clear(); m_State = 0; + foreach (ERR_ConvoyVehicle vehicle : m_Task.Vehicles) + { + vehicle.Combat.Held = false; + // Combat time does not consume the driving deadline. + vehicle.LegDeadline = now + 600000; + } + m_Task.TravelDeadline = now + 600000; + ERR_HQ.Event("CONVOY REGROUP", m_Task.Receipt.SourceId + ": surviving convoy resumes; no replacements"); + } + bool Tick(float now) + { + if (m_Stopped) return false; + for (int released = 0; released < m_Task.Vehicles.Count(); released++) + if (m_Task.Vehicles[released].Released) m_Support[released].Clear(); + foreach (ERR_SupplyTeam infantryTeam : m_Task.Teams) + { + if (infantryTeam.Released) continue; + bool foreign = !infantryTeam.Group || infantryTeam.Group.GetFaction() != m_Mode.EnemyFaction(); + foreach (IEntity member : infantryTeam.Members) + if (ERR_Actors.Alive(member) && ERR_Actors.Group(member) != infantryTeam.Group) foreign = true; + if (foreign || !infantryTeam.Living()) infantryTeam.Release(m_Mode); + } + vector observed; float nearest = 400; bool found; + foreach (ERR_ConvoyVehicle vehicle : m_Task.Vehicles) + if (!vehicle.Released && Observe(vehicle.Group, observed, nearest)) found = true; + foreach (ERR_SupplyTeam team : m_Task.Teams) + if (!team.Released && Observe(team.Group, observed, nearest)) found = true; + if (found) Report(observed, now, now); + if (m_State == 1) + { + if (!m_TruckWithdrawn && InfantryAboard(false)) { m_TruckWithdrawn = true; Support(2, false); } + // Native exit attempts can fail while the truck brakes or a door is busy. + // Retry only still-mounted teams, never teleport actors or reset quiet time. + if (!m_TruckWithdrawn && Usable(2) && now >= m_NextDismount && m_DismountAttempts < 6) + { + m_DismountAttempts++; m_NextDismount = now + 10000; + for (int retry = 0; retry < m_Task.Teams.Count(); retry++) + { + ERR_SupplyTeam delayed = m_Task.Teams[retry]; + if (delayed.Released || delayed.Aboard(m_Task.Vehicles[2].Entity, false)) continue; + delayed.Clear(); Flank(retry, true); + } + } + if (found && now >= m_NextOrders) Orders(!InfantryAboard(false), now); + if (now - m_LastContact >= 60000) + { + Clear(); + if (!Usable(2)) { foreach (ERR_SupplyTeam lost : m_Task.Teams) lost.Release(m_Mode); Finish(now); return false; } + for (int i = 0; i < m_Task.Vehicles.Count(); i++) Support(i, true); + foreach (ERR_SupplyTeam boarding : m_Task.Teams) + if (!boarding.Released && boarding.Living()) boarding.Add(Board(m_Task.Vehicles[2].Entity, true)); + m_State = 2; m_BoardDeadline = now + 120000; + ERR_HQ.Event("CONVOY BOARDING", m_Task.Receipt.SourceId + ": both teams return under escort cover"); + } + } + if (m_State == 2 && (!Usable(2) || InfantryAboard(true) || now >= m_BoardDeadline)) + { + foreach (ERR_SupplyTeam stranded : m_Task.Teams) + if (!stranded.Aboard(m_Task.Vehicles[2].Entity, true)) stranded.Release(m_Mode); + Finish(now); + } + return m_State != 0; + } + void Stop() { if (m_Stopped) return; m_Stopped = true; Clear(); } +} diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_SupportScenario.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_SupportScenario.c index 1cb5412..8105d3a 100644 --- a/addons/core/Scripts/Game/ERR/10_AI/ERR_SupportScenario.c +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_SupportScenario.c @@ -1,5 +1,11 @@ modded class ERR_ScenarioComponent { + protected override ERR_PrepareResult PrepareAdditionalPopulation() + { + ERR_HQ hq = ERR_HQ.Get(); + if (!hq) return ERR_PrepareResult.FAILED; + return hq.Scouts().Prepare(m_RuntimeDefinition); + } protected override bool PrepareAdditionalForces() { if (!super.PrepareAdditionalForces()) return false; diff --git a/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelDiscoveryFeedback.c b/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelDiscoveryFeedback.c index cdaef14..483f03c 100644 --- a/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelDiscoveryFeedback.c +++ b/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelDiscoveryFeedback.c @@ -36,22 +36,16 @@ modded class ERR_GameMode protected void ERR_FlushDiscoveryFeedback(float now) { if (!Replication.IsServer() || m_ERRIntelFeedbackStopped || !Active() || m_ERRIntelPending.IsEmpty() || now < m_ERRIntelMessageAt) return; - int identified; - int rough; - string label; + string message; foreach (ERR_LocationComponent location, int knowledge : m_ERRIntelPending) { if (!location) continue; - if (knowledge == 2) - { - identified++; - label = location.Label(); - } - else rough++; + string entry = ERR_IntelDiscoveryText.Message(knowledge == 2, knowledge == 1, ERR_IntelDiscoveryText.Type(location.Kind(), location.Id())); + if (!message.IsEmpty()) message += "\n"; + message += entry; } m_ERRIntelPending.Clear(); m_ERRIntelMessageAt = now + 5000; - string message = ERR_IntelDiscoveryText.Message(identified, rough, label); if (message.IsEmpty()) return; // The listen host and remote recipients share the same per-round sequence. // Local delivery is explicit and cannot duplicate a transport callback. @@ -66,6 +60,15 @@ modded class ERR_GameMode m_ERRIntelReceivedSequence = sequence; SCR_ChatComponent.RadioProtocolMessage(message); } + void ERR_IntelExhausted(bool duplicate = false) + { + if (!Replication.IsServer() || m_ERRIntelFeedbackStopped || !Active()) return; + string message = "Every known location has already been identified. This intel doesn't help us."; + if (duplicate) message = "This document concerns a location we have already identified."; + m_ERRIntelMessageSequence++; + ERR_ReceiveDiscoveryFeedback(m_ERRIntelMessageSequence, message); + Rpc(ERR_ReceiveDiscoveryFeedback, m_ERRIntelMessageSequence, message); + } protected void ERR_StopDiscoveryFeedback() { m_ERRIntelFeedbackStopped = true; @@ -79,15 +82,22 @@ modded class ERR_GameMode class ERR_IntelDiscoveryText { + static string Type(int kind, string id) + { + if (kind == ERR_LocationKind.RADIO) return "radio station"; + if (kind == ERR_LocationKind.OUTPOST) return "outpost"; + if (kind == ERR_LocationKind.MORTAR) return "mortar site"; + if (id.Contains("medical")) return "medical stash"; + if (kind == ERR_LocationKind.DEPOT) return "supply cache"; + return "location"; + } + // Exact wording from the owner's original EI_IntelService. New site types + // supply their own noun; unknown clues never reveal the noun or site name. static string Message(int identified, int rough, string label) { if (identified + rough == 0) return ""; - if (identified == 0 && rough == 1) return "A new 500 m search area is marked on your field map. Recover another folder to identify the location."; - if (identified == 1 && rough == 0) - { - if (label.IsEmpty()) label = "A location"; - return label + " identified. Check your field map."; - } - return string.Format("Field map updated: %1 identified locations and %2 search areas. Open a carried map to review them.", identified, rough); + if (identified == 0) return "New location marked. Type unknown."; + if (label.IsEmpty()) label = "location"; + return "Hey! A " + label + " was identified in the intel!"; } } diff --git a/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelEvidence.c b/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelEvidence.c new file mode 100644 index 0000000..d4e80d1 --- /dev/null +++ b/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelEvidence.c @@ -0,0 +1,197 @@ +// Issued document identities and their sealed contents. This is local logistics +// bookkeeping, not HQ knowledge of player inventories or map discoveries. +class ERR_IssuedIntel +{ + IEntity Folder; + string SiteId; +} +class ERR_BodyEvidence +{ + IEntity Actor; + string SourceId; + ref array Issued = {}; + bool Searched; + bool Reported; +} +class ERR_IntelEvidence +{ + protected ref array m_Roster = {}; + protected bool m_Stopped; + protected int m_Cursor; + void Retire(IEntity folder) { foreach (ERR_BodyEvidence record : m_Roster) for (int i = record.Issued.Count() - 1; i >= 0; i--) if (record.Issued[i].Folder == folder) record.Issued.Remove(i); + } + ERR_BodyEvidence Find(IEntity actor) + { + foreach (ERR_BodyEvidence record : m_Roster) { if (record.Actor == actor) return record; + } + return null; + } + void Register(SCR_AIGroup group) + { + ERR_GameMode mode = ERR_GameMode.Get(); + if (m_Stopped || !mode || !Replication.IsServer() || !group || group.GetFaction() != mode.EnemyFaction()) return; + ERR_ForceRecord force = mode.Forces().FindGroup(group); + if (!force) return; + array agents = {}; + group.GetAgents(agents); + foreach (AIAgent agent : agents) + { + if (!agent || !agent.GetControlledEntity() || Find(agent.GetControlledEntity()) || m_Roster.Count() >= 4096) continue; + ERR_BodyEvidence record = new ERR_BodyEvidence(); + record.Actor = agent.GetControlledEntity(); + record.SourceId = force.SourceId; + m_Roster.Insert(record); + SCR_GarbageSystem garbage = SCR_GarbageSystem.GetByEntityWorld(record.Actor); + if (garbage) garbage.UpdateBlacklist(record.Actor, true); + } + } + void Capture(IEntity actor) + { + ERR_BodyEvidence record = Find(actor); + if (!record || record.Searched || !ERR_Actors.Alive(actor) || ERR_Actors.Player(actor)) return; + InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(actor.FindComponent(InventoryStorageManagerComponent)); + if (!inventory) return; + array folders = {}; + ERR_DiscoveryService.Folders(inventory, folders); + array locations = {}; + ERR_GameMode.Get().Locations(locations); + array eligible = {}; + foreach (ERR_LocationComponent location : locations) + if (location && location.Kind() != ERR_LocationKind.PRISON && location.Kind() != ERR_LocationKind.EXTRACTION) eligible.Insert(location); + if (eligible.IsEmpty()) return; + foreach (IEntity folder : folders) + { + bool known; + foreach (ERR_IssuedIntel issued : record.Issued) if (issued.Folder == folder) known = true; + if (known || record.Issued.Count() >= 16) continue; + ERR_IssuedIntel item = new ERR_IssuedIntel(); + item.Folder = folder; + ERR_DocumentComponent document = ERR_DocumentComponent.Cast(folder.FindComponent(ERR_DocumentComponent)); + if (document) item.SiteId = document.TargetId(); + else item.SiteId = eligible.GetRandomElement().Id(); + record.Issued.Insert(item); + } + } + string Target(IEntity folder) + { + foreach (ERR_BodyEvidence record : m_Roster) + foreach (ERR_IssuedIntel issued : record.Issued) if (issued.Folder == folder) return issued.SiteId; + return ""; + } + void Tick(float now) + { + if (m_Stopped) return; + // Preserve only the mission-owned cohort. Transferred/player-controlled actors + // are released from retention instead of becoming forensic targets. + for (int budget = 0; budget < Math.Min(16, m_Roster.Count()); budget++) + { + if (m_Cursor >= m_Roster.Count()) m_Cursor = 0; + ERR_BodyEvidence record = m_Roster[m_Cursor++]; + if (!record.Actor || record.Reported) continue; + if (ERR_Actors.Player(record.Actor) || SCR_FactionManager.SGetFaction(record.Actor) != ERR_GameMode.Get().EnemyFaction()) + { record.Reported = true; + record.Searched = true; + Release(record); + continue; + } + if (ERR_Actors.Alive(record.Actor)) Capture(record.Actor); + } + } + bool Inspect(IEntity body, IEntity observer, out array missing) + { + missing.Clear(); + if (!Replication.IsServer() || m_Stopped || !ERR_GameMode.Get() || !ERR_GameMode.Get().Active()) return false; + ERR_BodyEvidence record = Find(body); + if (!record || record.Searched || ERR_Actors.Alive(body) || !ERR_Actors.CanFight(observer) || ERR_Actors.Player(observer) || CompartmentAccessComponent.GetVehicleIn(observer)) return false; + if (vector.Distance(observer.GetOrigin(), body.GetOrigin()) > 3) return false; + TraceParam trace = new TraceParam(); + trace.Start = observer.GetOrigin() + "0 1.5 0"; + trace.End = body.GetOrigin() + "0 0.3 0"; + trace.Exclude = observer; + trace.Flags = TraceFlags.ENTS | TraceFlags.WORLD; + if (GetGame().GetWorld().TraceMove(trace, null) < 1 && trace.TraceEnt != body) return false; + InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(body.FindComponent(InventoryStorageManagerComponent)); + if (!inventory) return false; + array folders = {}; + ERR_DiscoveryService.Folders(inventory, folders); + foreach (ERR_IssuedIntel issued : record.Issued) + if (!folders.Contains(issued.Folder) && !missing.Contains(issued.SiteId)) missing.Insert(issued.SiteId); + record.Searched = true; + return true; + } + void Release(ERR_BodyEvidence record) + { + if (!record || !record.Actor) return; + SCR_GarbageSystem garbage = SCR_GarbageSystem.GetByEntityWorld(record.Actor); + if (garbage) { garbage.UpdateBlacklist(record.Actor, false); + if (!ERR_Actors.Alive(record.Actor)) garbage.Insert(record.Actor, 300); + } + } + // Searching alone does not authorize cleanup: the missing-document report + // must first reach HQ. Duplicate delivery never renews the cleanup timer. + void Delivered(IEntity body) + { + if (!Replication.IsServer() || m_Stopped) return; + ERR_BodyEvidence record = Find(body); + if (!record || !record.Searched || record.Reported) return; + record.Reported = true; + Release(record); + } + bool Retained(IEntity actor) { ERR_BodyEvidence record = Find(actor); + return !m_Stopped && record && !record.Reported; + } + bool RetainedWithin(IEntity entity) + { + if (m_Stopped || !entity) return false; + foreach (ERR_BodyEvidence record : m_Roster) + { + if (!record.Actor || record.Reported || ERR_Actors.Alive(record.Actor)) continue; + IEntity parent = record.Actor; + for (int depth = 0; parent && depth < 32; depth++) + { + if (parent == entity) return true; + parent = parent.GetParent(); + } + } + return false; + } + void Stop() { m_Stopped = true; + foreach (ERR_BodyEvidence record : m_Roster) Release(record); + m_Roster.Clear(); + } +} +modded class ERR_GameMode +{ + protected ref ERR_IntelEvidence m_Evidence = new ERR_IntelEvidence(); + ERR_IntelEvidence Evidence() { return m_Evidence; + } + protected override void EOnInit(IEntity owner) + { + super.EOnInit(owner); + if (SCR_Global.IsEditMode() || !Replication.IsServer()) return; + OnGroup().Insert(m_Evidence.Register); + OnTick().Insert(m_Evidence.Tick); + OnStop().Insert(m_Evidence.Stop); + } +} + +// Native vehicle garbage collection must not delete a retained corpse through +// its parent hierarchy (for example a dead occupant in a wreck). +modded class SCR_GarbageSystem +{ + protected bool ERR_RetainedEvidence(IEntity entity) + { + ERR_GameMode mode = ERR_GameMode.Get(); + return Replication.IsServer() && mode && mode.Evidence() && mode.Evidence().RetainedWithin(entity); + } + override protected float OnInsertRequested(IEntity entity, float lifetime) + { + if (ERR_RetainedEvidence(entity)) return 0; + return super.OnInsertRequested(entity, lifetime); + } + override protected bool OnBeforeDelete(IEntity entity) + { + if (ERR_RetainedEvidence(entity)) return false; + return super.OnBeforeDelete(entity); + } +} diff --git a/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelReroll.c b/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelReroll.c index 57e6c5d..697d83a 100644 --- a/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelReroll.c +++ b/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelReroll.c @@ -127,6 +127,7 @@ class ERR_IntelReroll // the existing phase budget without spending or owning the folder. if (!inventory.TryRemoveItemFromInventory(folder)) { entry.WaitingFor = "removal-refused"; return; } m_Mode.Discovery().MarkSpent(folder); + m_Mode.Evidence().Retire(folder); m_Mode.Own(folder); entry.Removing = folder; entry.WaitingFor = "native-removal"; diff --git a/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelService.c b/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelService.c index f429cdd..c2cbb09 100644 --- a/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelService.c +++ b/addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelService.c @@ -41,7 +41,7 @@ class ERR_IntelService IEntity actor = member.GetControlledEntity(); if (!ERR_Actors.Alive(actor) || ERR_Actors.Player(actor) || m_Rolled.Contains(actor)) continue; m_Rolled.Insert(actor); - if (Math.RandomInt(0, 100) >= m_Mode.Settings().Get("aiIntelChancePercent")) continue; + if (Math.RandomInt(0, 100) >= m_Mode.Settings().Runtime("aiIntelChancePercent")) continue; if (m_Requests.Count() >= 256) continue; ERR_IntelRequest request = new ERR_IntelRequest(); request.Actor = actor; @@ -68,6 +68,7 @@ class ERR_IntelService if (inventory) ERR_DiscoveryService.Folders(inventory, folders); if (request.Accepted && request.Operation && request.Operation.Finished) { + m_Mode.Evidence().Capture(request.Actor); m_Requests.Remove(i); continue; } if (!request.Accepted && !folders.IsEmpty()) { m_Requests.Remove(i); continue; } @@ -92,7 +93,7 @@ class ERR_IntelService bool BeginReroll() { if (!Replication.IsServer() || m_Stopped || !m_Mode || !m_Mode.Active() || !m_Mode.Discovery() || (m_Reroll && m_Reroll.Running())) return false; - m_Reroll = new ERR_IntelReroll(m_Mode, this, m_Mode.Settings().Get("aiIntelChancePercent")); + m_Reroll = new ERR_IntelReroll(m_Mode, this, m_Mode.Settings().Runtime("aiIntelChancePercent")); set cohort = new set(); foreach (IEntity actor : m_Rolled) { diff --git a/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c b/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c index 1772dbf..965ee61 100644 --- a/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c +++ b/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSmoke.c @@ -78,7 +78,7 @@ modded class ERR_GameMode m_ERRTestLocalHandoff = outcome == "hq-local-handoff"; m_ERRTestHQBody = outcome == "hq-body"; m_ERRTestInfantryTransfer = outcome == "infantry-transfer"; - m_ERRTestConvoy = outcome == "convoy"; + m_ERRTestConvoy = outcome == "convoy" || outcome == "supply-convoys"; m_ERRTestMortar = outcome == "mortar-inventory"; m_ERRTestMapOwnership = outcome == "map-ownership"; m_ERRTestAircraftField = outcome == "aircraft-field"; @@ -96,6 +96,7 @@ modded class ERR_GameMode m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 150000; if (m_ERRTestLocalHandoff) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 240000; if (m_ERRTestConvoy) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 540000; + if (outcome == "supply-convoys") m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 840000; if (ERR_NativeConvoyCoverProbe.Enabled()) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 840000; if (m_ERRTestHQMemory) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 360000; if (m_ERRTestInfantryTransfer) m_ERRSmokeDeadline = GetWorld().GetWorldTime() + 300000; @@ -542,6 +543,7 @@ modded class ERR_GameMode if (m_ERRTestMortarFire) { DamageManagerComponent.Cast(m_ERRSmokePlayer.FindComponent(DamageManagerComponent)).EnableDamageHandling(false); + if (!ERR_Check(UnlockPrison(m_ERRSmokePlayer), "mortar firing fixture opens prison before waiting for support AI")) return; m_ERRMortarFire = new ERR_NativeMortarFiringProbe(this); m_ERRSmokeStep = 150; return; @@ -580,7 +582,13 @@ modded class ERR_GameMode if (m_ERRTestConvoy) { DamageManagerComponent.Cast(m_ERRSmokePlayer.FindComponent(DamageManagerComponent)).EnableDamageHandling(false); - m_ERRConvoyProbe = new ERR_NativeConvoyProbe(this); + string convoyOutcome; System.GetCLIParam("errSmokeOutcome", convoyOutcome); + if (convoyOutcome == "supply-convoys") + { + if (!ERR_Check(UnlockPrison(m_ERRSmokePlayer), "supply fixture unlocks prison to start normal mission AI")) return; + m_ERRConvoyProbe = new ERR_NativeSupplyConvoyProbe(this); + } + else m_ERRConvoyProbe = new ERR_NativeConvoyProbe(this); m_ERRSmokeStep = 106; return; } diff --git a/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSupplyConvoyProbe.c b/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSupplyConvoyProbe.c new file mode 100644 index 0000000..925a791 --- /dev/null +++ b/addons/core/Scripts/Game/ERR/40_Chat/ERR_NativeSupplyConvoyProbe.c @@ -0,0 +1,156 @@ +#ifdef WORKBENCH +// Explicit opt-in fixture. Startup, seating, cargo and driving remain production-owned. +// The final phase injects one clearly labelled contact to exercise native dismount/reboard. +class ERR_NativeSupplyConvoyProbe : ERR_NativeConvoyProbe +{ + protected ref array m_StartPositions = {}; + protected ref array m_Moved = {}; + protected bool m_AllMoved; + protected float m_Began = -1; + protected float m_PhaseBegan; + protected int m_Phase; + protected ref ERR_SupplyConvoyTask m_CombatTask; + protected bool m_SawDismount; + protected bool m_SawBoarding; + protected int m_TestLegs; + protected vector m_RouteResumePosition; + protected int ObserveMotion(ERR_HQ hq) + { + if (m_StartPositions.Count() != 18) return 0; + int cursor, moved; + for (int index = 0; index < 3; index++) + { + foreach (ERR_ConvoyVehicle vehicle : hq.Convoys().At(index).Vehicles) + { + if (vector.DistanceXZ(vehicle.Entity.GetOrigin(), m_StartPositions[cursor]) >= 20) m_Moved[cursor] = true; + if (m_Moved[cursor]) moved++; + cursor++; + } + } + if (moved == 18 && !m_AllMoved) + { + m_AllMoved = true; + Print("ERR SUPPLY PASS: all eighteen original vehicles drove at least twenty metres from their recorded spawn positions through native AI"); + } + return moved; + } + override int Tick(ERR_HQ hq, float now) + { + if (!hq || !hq.SupplyConvoys()) return -1; + if (m_Began < 0) m_Began = now; + if (now - m_Began > 720000) { Print("ERR SUPPLY FAIL: native convoy fixture deadline"); return -1; } + int moved = ObserveMotion(hq); + if (now >= m_NextLog) + { + PrintFormat("ERR SUPPLY MOTION: %1/18 original vehicles moved at least20m", moved); + PrintFormat("ERR SUPPLY STATE: phase=%1 elapsed=%2 %3", m_Phase, now - m_Began, hq.ConvoyStatus()); + for (int logIndex = 0; logIndex < hq.Convoys().Count(); logIndex++) + { + ERR_SupplyConvoyTask logged = ERR_SupplyConvoyTask.Cast(hq.Convoys().At(logIndex)); + int state = -1; if (logged.Tactics) state = logged.Tactics.State(); + PrintFormat("ERR SUPPLY TASK: index=%1 ready=%2 stopped=%3 reason=%4 teams=%5 cargo=%6 legs=%7 combat=%8", logIndex, logged.Ready, logged.Stopped, logged.Reason, logged.Teams.Count(), logged.Cargo.Count(), logged.Legs, state); + } + if (m_CombatTask) + { + ERR_ConvoyVehicle truck = m_CombatTask.Vehicles[2]; + SCR_VehicleDamageManagerComponent health = SCR_VehicleDamageManagerComponent.Cast(truck.Entity.FindComponent(SCR_VehicleDamageManagerComponent)); + PrintFormat("ERR SUPPLY TRUCK: released=%1 driverAlive=%2 driverGroup=%3 driverAboard=%4 health=%5 retained=%6 position=%7", truck.Released, ERR_Actors.CanFight(truck.Driver), ERR_Actors.Group(truck.Driver) == truck.Group, CompartmentAccessComponent.GetVehicleIn(truck.Driver) == truck.Entity, health.GetHealthScaled(), ERR_ConvoyMountedCrew.Retain(truck.Driver, truck.Entity), truck.Entity.GetOrigin()); + foreach (ERR_SupplyTeam diagnostic : m_CombatTask.Teams) + { + int aboard; + foreach (IEntity passenger : diagnostic.Members) if (CompartmentAccessComponent.GetVehicleIn(passenger) == truck.Entity) aboard++; + PrintFormat("ERR SUPPLY INFANTRY: aboard=%1 members=%2 released=%3 groupPosition=%4 orders=%5", aboard, diagnostic.Members.Count(), diagnostic.Released, diagnostic.Group.GetOrigin(), diagnostic.Orders.Count()); + foreach (IEntity remaining : diagnostic.Members) + { + AIControlComponent control = AIControlComponent.Cast(remaining.FindComponent(AIControlComponent)); + SCR_ChimeraAIAgent agent = SCR_ChimeraAIAgent.Cast(control.GetControlAIAgent()); + CompartmentAccessComponent access = CompartmentAccessComponent.Cast(remaining.FindComponent(CompartmentAccessComponent)); + PrintFormat("ERR SUPPLY SEAT: name=%1 fit=%2 active=%3 canExit=%4 exiting=%5 action=%6 waypoint=%7", CompartmentAccessComponent.GetVehicleIn(remaining) == truck.Entity, ERR_Actors.CanFight(remaining), agent.IsAIActivated(), access.CanGetOutVehicle(), access.IsGettingOut(), agent.m_UtilityComponent.GetCurrentAction(), diagnostic.Group.GetCurrentWaypoint()); + } + } + } + m_NextLog = now + 10000; + } + if (m_Phase == 0) + { + if (hq.SupplyConvoys().Target() != 3) { Print("ERR SUPPLY FAIL: fixture requires default three convoys"); return -1; } + if (hq.Convoys().Count() != 3) return 0; + for (int i = 0; i < 3; i++) + { + ERR_SupplyConvoyTask task = ERR_SupplyConvoyTask.Cast(hq.Convoys().At(i)); + if (!task || task.Stopped) return -1; + if (!task.Ready || !task.MagazinesIssued) return 0; + foreach (ERR_ConvoyCargoCallback pending : task.Cargo) if (!pending.Finished) return 0; + if (task.Vehicles.Count() != 6 || task.Teams.Count() != 2 || task.Receipt.OutstandingBodies != 0 || task.Receipt.OutstandingGroups != 0) return -1; + foreach (ERR_SupplyTeam team : task.Teams) + if (!team.Registered || team.Group == task.Vehicles[2].Group || team.Members.Count() != 7) return -1; + if (task.Teams[0].Group == task.Teams[1].Group) return -1; + int successful; + foreach (ERR_ConvoyCargoCallback load : task.Cargo) if (load.Succeeded) successful++; + if (successful < 14) { Print("ERR SUPPLY FAIL: weapon and ammunition storage operations missing"); return -1; } + InventoryStorageManagerComponent inventory = InventoryStorageManagerComponent.Cast(task.Vehicles[1].Entity.FindComponent(InventoryStorageManagerComponent)); + array items = {}; ERR_Inventory.Items(inventory, items); + foreach (ERR_ConvoyCargoCallback inserted : task.Cargo) + { + if (!inserted.Succeeded) continue; + bool matched; + for (int itemIndex = 0; itemIndex < items.Count(); itemIndex++) + { + IEntity item = items[itemIndex]; + if (!item || !item.GetPrefabData() || item.GetPrefabData().GetPrefabName() != inserted.Prefab) continue; + items.Remove(itemIndex); matched = true; break; + } + if (!matched) { Print("ERR SUPPLY FAIL: successful cargo callback lacks its physical inventory item"); return -1; } + } + + } + for (int convoy = 0; convoy < 3; convoy++) + { + ERR_SupplyConvoyTask original = ERR_SupplyConvoyTask.Cast(hq.Convoys().At(convoy)); + if (original.Starts.Count() != 6) return -1; + foreach (vector start : original.Starts) { m_StartPositions.Insert(start); m_Moved.Insert(false); } + } + Print("ERR SUPPLY PASS: production auto-started three six-vehicle convoys, exact ledger admission, two separate seated teams each, finite native cargo"); + m_Phase = 1; m_PhaseBegan = now; + } + if (m_Phase == 1) + { + if (!m_AllMoved && now - m_PhaseBegan < 45000) return 0; + m_CombatTask = ERR_SupplyConvoyTask.Cast(hq.Convoys().At(0)); + vector contact = m_CombatTask.Vehicles[2].Entity.GetOrigin() + "0 0 200"; + m_CombatTask.Tactics.Report(contact, now, now); + Print("ERR SUPPLY FIXTURE: injected one contact for native dismount/reboard validation; this phase does not prove perception"); + m_Phase = 2; m_PhaseBegan = now; + } + if (m_Phase == 2) + { + if (m_CombatTask.Stopped) return -1; + bool dismounted = true; + foreach (ERR_SupplyTeam foot : m_CombatTask.Teams) + if (!foot.Aboard(m_CombatTask.Vehicles[2].Entity, false)) dismounted = false; + if (dismounted && !m_SawDismount) { m_SawDismount = true; Print("ERR SUPPLY PASS: both original infantry teams physically dismounted"); } + if (m_CombatTask.Tactics.State() == 2) m_SawBoarding = true; + if (now - m_PhaseBegan > 60000 && m_CombatTask.Tactics.State() == 0) + { + if (!m_SawDismount || !m_SawBoarding) return -1; + foreach (ERR_SupplyTeam boarded : m_CombatTask.Teams) + if (boarded.Released || !boarded.Aboard(m_CombatTask.Vehicles[2].Entity, true)) return -1; + Print("ERR SUPPLY PASS: both original teams reboarded and production travel resumed after quiet interval"); + m_TestLegs = m_CombatTask.Legs; m_RouteResumePosition = m_CombatTask.Vehicles[2].Entity.GetOrigin(); + m_CombatTask.TravelDeadline = now; m_CombatTask.Waiting = false; + Print("ERR SUPPLY FIXTURE: expire this trip's travel deadline to exercise the real pause and next base leg without a ten-minute test delay"); + m_Phase = 3; + } + } + if (m_Phase == 3 && m_CombatTask.Legs > m_TestLegs && vector.DistanceXZ(m_CombatTask.Vehicles[2].Entity.GetOrigin(), m_RouteResumePosition) >= 20) + { + if (m_CombatTask.Stopped || m_CombatTask.Vehicles[2].Released || m_CombatTask.Bases.Count() < 2) return -1; + Print("ERR SUPPLY PASS: original truck drives a new native base leg after the production pause; no replacement convoy"); + m_Phase = 4; + } + if (m_Phase == 4 && m_AllMoved) return 1; + return 0; + } + override void Stop() {} +} +#endif diff --git a/addons/core/UI/layouts/ERR/AdminMenu.layout b/addons/core/UI/layouts/ERR/AdminMenu.layout index 391c41b..b7949ed 100644 --- a/addons/core/UI/layouts/ERR/AdminMenu.layout +++ b/addons/core/UI/layouts/ERR/AdminMenu.layout @@ -20,497 +20,510 @@ FrameWidgetClass { } Color 0.035 0.05 0.065 0.98 } - TextWidgetClass { - Name "Title" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 24 OffsetTop 24 SizeX 790 OffsetRight -818 SizeY 44 OffsetBottom -68 - } - Color 0.9 0.92 0.94 1 Text "Mission settings" "Font Size" 34 "Min Font Size" 34 Wrap 1 FontProperties FontProperties { - Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" - } - } - ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { - Name "Close" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 844 OffsetLeft 844 PositionY 24 OffsetTop 24 SizeX 120 OffsetRight -964 SizeY 42 OffsetBottom -66 - } - components { - SCR_ButtonTextComponent "{5548F0143AE99095}" { - m_sText "Close" - } - } - } - TextWidgetClass { - Name "Connection" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 78 OffsetTop 78 SizeX 936 OffsetRight -964 SizeY 28 OffsetBottom -106 - } - Color 0.9 0.92 0.94 1 Text "Requesting administrator access..." "Font Size" 18 "Min Font Size" 18 Wrap 1 FontProperties FontProperties { - Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" - } - } - FrameWidgetClass { - Name "SettingsPage" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 0 OffsetLeft 0 PositionY 0 OffsetTop 0 SizeX 1000 OffsetRight -1000 SizeY 760 OffsetBottom -760 - } - { - TextWidgetClass { - Name "SettingsHelp" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 110 OffsetTop 110 SizeX 936 OffsetRight -964 SizeY 28 OffsetBottom -138 - } - Color 0.9 0.92 0.94 1 Text "Changes are saved on the server. Clock, date and weather apply next round." "Font Size" 18 "Min Font Size" 18 Wrap 1 FontProperties FontProperties { - Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" - } - } - TextWidgetClass { - Name "Label_radioDefenceSeconds" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 152 OffsetTop 152 SizeX 350 OffsetRight -378 SizeY 27 OffsetBottom -179 - } +FrameWidgetClass { Name "SettingsPage" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 0 OffsetLeft 0 PositionY 160 OffsetTop 160 SizeX 1000 OffsetRight -1000 SizeY 486 OffsetBottom -646 } { +TextWidgetClass { + Name "SettingsHelp" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 6 OffsetTop 6 SizeX 936 OffsetRight -964 SizeY 50 OffsetBottom -56 } + Color 0.9 0.92 0.94 1 Text "Mission objectives and traffic. Choose a value or Random, then Apply." "Font Size" 19 "Min Font Size" 19 Wrap 1 + FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } +} +TextWidgetClass { + Name "Label_radioDefenceSeconds" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 80 OffsetTop 80 SizeX 368 OffsetRight -396 SizeY 28 OffsetBottom -108 } Color 0.9 0.92 0.94 1 Text "Radio defence (30-1800 seconds)" "Font Size" 20 "Min Font Size" 20 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } } - TextWidgetClass { - Name "Saved_radioDefenceSeconds" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 180 OffsetTop 180 SizeX 350 OffsetRight -378 SizeY 22 OffsetBottom -202 - } +TextWidgetClass { + Name "Saved_radioDefenceSeconds" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 112 OffsetTop 112 SizeX 936 OffsetRight -964 SizeY 24 OffsetBottom -136 } Color 0.9 0.92 0.94 1 Text "Waiting for saved value" "Font Size" 16 "Min Font Size" 16 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } } - ButtonWidgetClass : "{0022F0B45ADBC5AC}UI/layouts/WidgetLibrary/EditBox/WLib_EditBox.layout" { - Name "radioDefenceSeconds" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 386 OffsetLeft 386 PositionY 152 OffsetTop 152 SizeX 260 OffsetRight -646 SizeY 42 OffsetBottom -194 - } +ButtonWidgetClass : "{DA43C77A0D1E59F8}UI/layouts/ERR/AdminValue.layout" { + Name "radioDefenceSeconds" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 408 OffsetLeft 408 PositionY 80 OffsetTop 80 SizeX 240 OffsetRight -648 SizeY 42 OffsetBottom -122 } components { SCR_EditBoxComponent "{547290FFBD5B33E9}" { m_sLabel "" } } } - ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { - Name "Apply_radioDefenceSeconds" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 664 OffsetLeft 664 PositionY 152 OffsetTop 152 SizeX 150 OffsetRight -814 SizeY 42 OffsetBottom -194 - } +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "Apply_radioDefenceSeconds" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 660 OffsetLeft 660 PositionY 80 OffsetTop 80 SizeX 112 OffsetRight -772 SizeY 42 OffsetBottom -122 } components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "Apply" } } } - TextWidgetClass { - Name "Label_aiIntelChancePercent" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 210 OffsetTop 210 SizeX 350 OffsetRight -378 SizeY 27 OffsetBottom -237 +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "Random_radioDefenceSeconds" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 784 OffsetLeft 784 PositionY 80 OffsetTop 80 SizeX 180 OffsetRight -964 SizeY 42 OffsetBottom -122 } + components { + SCR_ButtonTextComponent "{5548F0143AE99095}" { + m_sText "Random" + } } - Color 0.9 0.92 0.94 1 Text "AI carrying intel (0-100%)" "Font Size" 20 "Min Font Size" 20 Wrap 1 FontProperties FontProperties { + } +TextWidgetClass { + Name "Label_convoyCount" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 168 OffsetTop 168 SizeX 368 OffsetRight -396 SizeY 28 OffsetBottom -196 } + Color 0.9 0.92 0.94 1 Text "Convoys next round (0-20)" "Font Size" 20 "Min Font Size" 20 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } } - TextWidgetClass { - Name "Saved_aiIntelChancePercent" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 238 OffsetTop 238 SizeX 350 OffsetRight -378 SizeY 22 OffsetBottom -260 - } +TextWidgetClass { + Name "Saved_convoyCount" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 200 OffsetTop 200 SizeX 936 OffsetRight -964 SizeY 24 OffsetBottom -224 } Color 0.9 0.92 0.94 1 Text "Waiting for saved value" "Font Size" 16 "Min Font Size" 16 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } } - ButtonWidgetClass : "{0022F0B45ADBC5AC}UI/layouts/WidgetLibrary/EditBox/WLib_EditBox.layout" { - Name "aiIntelChancePercent" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 386 OffsetLeft 386 PositionY 210 OffsetTop 210 SizeX 260 OffsetRight -646 SizeY 42 OffsetBottom -252 - } +ButtonWidgetClass : "{DA43C77A0D1E59F8}UI/layouts/ERR/AdminValue.layout" { + Name "convoyCount" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 408 OffsetLeft 408 PositionY 168 OffsetTop 168 SizeX 240 OffsetRight -648 SizeY 42 OffsetBottom -210 } components { SCR_EditBoxComponent "{547290FFBD5B33E9}" { m_sLabel "" } } } - ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { - Name "Apply_aiIntelChancePercent" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 664 OffsetLeft 664 PositionY 210 OffsetTop 210 SizeX 150 OffsetRight -814 SizeY 42 OffsetBottom -252 - } +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "Apply_convoyCount" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 660 OffsetLeft 660 PositionY 168 OffsetTop 168 SizeX 112 OffsetRight -772 SizeY 42 OffsetBottom -210 } components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "Apply" } } } - TextWidgetClass { - Name "Label_intelRevealChancePercent" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 268 OffsetTop 268 SizeX 350 OffsetRight -378 SizeY 27 OffsetBottom -295 +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "Random_convoyCount" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 784 OffsetLeft 784 PositionY 168 OffsetTop 168 SizeX 180 OffsetRight -964 SizeY 42 OffsetBottom -210 } + components { + SCR_ButtonTextComponent "{5548F0143AE99095}" { + m_sText "Random" + } } - Color 0.9 0.92 0.94 1 Text "First-document exact reveal (0-100%)" "Font Size" 20 "Min Font Size" 20 Wrap 1 FontProperties FontProperties { + } +TextWidgetClass { + Name "MissionHelp" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 272 OffsetTop 272 SizeX 936 OffsetRight -964 SizeY 60 OffsetBottom -332 } + Color 0.9 0.92 0.94 1 Text "Convoy count applies next round. Use the other pages above for world, intel and HQ settings." "Font Size" 19 "Min Font Size" 19 Wrap 1 + FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } +} +} } +FrameWidgetClass { Name "HQPage" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 0 OffsetLeft 0 PositionY 160 OffsetTop 160 SizeX 1000 OffsetRight -1000 SizeY 486 OffsetBottom -646 } { +TextWidgetClass { + Name "HQHelp" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 6 OffsetTop 6 SizeX 936 OffsetRight -964 SizeY 50 OffsetBottom -56 } + Color 0.9 0.92 0.94 1 Text "Control how often HQ receives reports and how it assigns ground support." "Font Size" 19 "Min Font Size" 19 Wrap 1 + FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } +} +TextWidgetClass { + Name "Label_reportIntervalSeconds" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 80 OffsetTop 80 SizeX 368 OffsetRight -396 SizeY 28 OffsetBottom -108 } + Color 0.9 0.92 0.94 1 Text "Report interval (5-60 seconds)" "Font Size" 20 "Min Font Size" 20 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } } - TextWidgetClass { - Name "Saved_intelRevealChancePercent" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 296 OffsetTop 296 SizeX 350 OffsetRight -378 SizeY 22 OffsetBottom -318 - } +TextWidgetClass { + Name "Saved_reportIntervalSeconds" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 112 OffsetTop 112 SizeX 936 OffsetRight -964 SizeY 24 OffsetBottom -136 } Color 0.9 0.92 0.94 1 Text "Waiting for saved value" "Font Size" 16 "Min Font Size" 16 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } } - ButtonWidgetClass : "{0022F0B45ADBC5AC}UI/layouts/WidgetLibrary/EditBox/WLib_EditBox.layout" { - Name "intelRevealChancePercent" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 386 OffsetLeft 386 PositionY 268 OffsetTop 268 SizeX 260 OffsetRight -646 SizeY 42 OffsetBottom -310 - } +ButtonWidgetClass : "{DA43C77A0D1E59F8}UI/layouts/ERR/AdminValue.layout" { + Name "reportIntervalSeconds" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 408 OffsetLeft 408 PositionY 80 OffsetTop 80 SizeX 240 OffsetRight -648 SizeY 42 OffsetBottom -122 } components { SCR_EditBoxComponent "{547290FFBD5B33E9}" { m_sLabel "" } } } - ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { - Name "Apply_intelRevealChancePercent" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 664 OffsetLeft 664 PositionY 268 OffsetTop 268 SizeX 150 OffsetRight -814 SizeY 42 OffsetBottom -310 - } +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "Apply_reportIntervalSeconds" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 660 OffsetLeft 660 PositionY 80 OffsetTop 80 SizeX 112 OffsetRight -772 SizeY 42 OffsetBottom -122 } components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "Apply" } } } - TextWidgetClass { - Name "Label_startTimeMinutes" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 326 OffsetTop 326 SizeX 350 OffsetRight -378 SizeY 27 OffsetBottom -353 +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "Random_reportIntervalSeconds" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 784 OffsetLeft 784 PositionY 80 OffsetTop 80 SizeX 180 OffsetRight -964 SizeY 42 OffsetBottom -122 } + components { + SCR_ButtonTextComponent "{5548F0143AE99095}" { + m_sText "Random" + } } + } +TextWidgetClass { + Name "Label_supportSquadLimit" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 168 OffsetTop 168 SizeX 368 OffsetRight -396 SizeY 28 OffsetBottom -196 } + Color 0.9 0.92 0.94 1 Text "Support squad limit (0-8)" "Font Size" 20 "Min Font Size" 20 Wrap 1 FontProperties FontProperties { + Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" + } + } +TextWidgetClass { + Name "Saved_supportSquadLimit" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 200 OffsetTop 200 SizeX 936 OffsetRight -964 SizeY 24 OffsetBottom -224 } + Color 0.9 0.92 0.94 1 Text "Waiting for saved value" "Font Size" 16 "Min Font Size" 16 Wrap 1 FontProperties FontProperties { + Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" + } + } +ButtonWidgetClass : "{DA43C77A0D1E59F8}UI/layouts/ERR/AdminValue.layout" { + Name "supportSquadLimit" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 408 OffsetLeft 408 PositionY 168 OffsetTop 168 SizeX 240 OffsetRight -648 SizeY 42 OffsetBottom -210 } + components { + SCR_EditBoxComponent "{547290FFBD5B33E9}" { + m_sLabel "" + } + } + } +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "Apply_supportSquadLimit" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 660 OffsetLeft 660 PositionY 168 OffsetTop 168 SizeX 112 OffsetRight -772 SizeY 42 OffsetBottom -210 } + components { + SCR_ButtonTextComponent "{5548F0143AE99095}" { + m_sText "Apply" + } + } + } +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "Random_supportSquadLimit" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 784 OffsetLeft 784 PositionY 168 OffsetTop 168 SizeX 180 OffsetRight -964 SizeY 42 OffsetBottom -210 } + components { + SCR_ButtonTextComponent "{5548F0143AE99095}" { + m_sText "Random" + } + } + } +TextWidgetClass { + Name "Label_responseRadiusMetres" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 256 OffsetTop 256 SizeX 368 OffsetRight -396 SizeY 28 OffsetBottom -284 } + Color 0.9 0.92 0.94 1 Text "Response radius (500-5000 metres)" "Font Size" 20 "Min Font Size" 20 Wrap 1 FontProperties FontProperties { + Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" + } + } +TextWidgetClass { + Name "Saved_responseRadiusMetres" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 288 OffsetTop 288 SizeX 936 OffsetRight -964 SizeY 24 OffsetBottom -312 } + Color 0.9 0.92 0.94 1 Text "Waiting for saved value" "Font Size" 16 "Min Font Size" 16 Wrap 1 FontProperties FontProperties { + Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" + } + } +ButtonWidgetClass : "{DA43C77A0D1E59F8}UI/layouts/ERR/AdminValue.layout" { + Name "responseRadiusMetres" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 408 OffsetLeft 408 PositionY 256 OffsetTop 256 SizeX 240 OffsetRight -648 SizeY 42 OffsetBottom -298 } + components { + SCR_EditBoxComponent "{547290FFBD5B33E9}" { + m_sLabel "" + } + } + } +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "Apply_responseRadiusMetres" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 660 OffsetLeft 660 PositionY 256 OffsetTop 256 SizeX 112 OffsetRight -772 SizeY 42 OffsetBottom -298 } + components { + SCR_ButtonTextComponent "{5548F0143AE99095}" { + m_sText "Apply" + } + } + } +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "Random_responseRadiusMetres" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 784 OffsetLeft 784 PositionY 256 OffsetTop 256 SizeX 180 OffsetRight -964 SizeY 42 OffsetBottom -298 } + components { + SCR_ButtonTextComponent "{5548F0143AE99095}" { + m_sText "Random" + } + } + } +} } +FrameWidgetClass { Name "WorldPage" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 0 OffsetLeft 0 PositionY 160 OffsetTop 160 SizeX 1000 OffsetRight -1000 SizeY 486 OffsetBottom -646 } { +TextWidgetClass { + Name "WorldHelp" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 6 OffsetTop 6 SizeX 936 OffsetRight -964 SizeY 50 OffsetBottom -56 } + Color 0.9 0.92 0.94 1 Text "Clock, date and weather apply next round. Random day chooses a daylight start time." "Font Size" 19 "Min Font Size" 19 Wrap 1 + FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } +} +TextWidgetClass { + Name "Label_startTimeMinutes" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 70 OffsetTop 70 SizeX 368 OffsetRight -396 SizeY 28 OffsetBottom -98 } Color 0.9 0.92 0.94 1 Text "Next-round start time (HH:MM)" "Font Size" 20 "Min Font Size" 20 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } } - TextWidgetClass { - Name "Saved_startTimeMinutes" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 354 OffsetTop 354 SizeX 350 OffsetRight -378 SizeY 22 OffsetBottom -376 - } +TextWidgetClass { + Name "Saved_startTimeMinutes" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 102 OffsetTop 102 SizeX 936 OffsetRight -964 SizeY 24 OffsetBottom -126 } Color 0.9 0.92 0.94 1 Text "Waiting for saved value" "Font Size" 16 "Min Font Size" 16 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } } - ButtonWidgetClass : "{0022F0B45ADBC5AC}UI/layouts/WidgetLibrary/EditBox/WLib_EditBox.layout" { - Name "startTimeMinutes" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 386 OffsetLeft 386 PositionY 326 OffsetTop 326 SizeX 260 OffsetRight -646 SizeY 42 OffsetBottom -368 - } +ButtonWidgetClass : "{DA43C77A0D1E59F8}UI/layouts/ERR/AdminValue.layout" { + Name "startTimeMinutes" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 408 OffsetLeft 408 PositionY 70 OffsetTop 70 SizeX 240 OffsetRight -648 SizeY 42 OffsetBottom -112 } components { SCR_EditBoxComponent "{547290FFBD5B33E9}" { m_sLabel "" } } } - ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { - Name "Apply_startTimeMinutes" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 664 OffsetLeft 664 PositionY 326 OffsetTop 326 SizeX 150 OffsetRight -814 SizeY 42 OffsetBottom -368 - } +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "Apply_startTimeMinutes" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 660 OffsetLeft 660 PositionY 70 OffsetTop 70 SizeX 112 OffsetRight -772 SizeY 42 OffsetBottom -112 } components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "Apply" } } } - TextWidgetClass { - Name "Label_timeMultiplier" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 384 OffsetTop 384 SizeX 350 OffsetRight -378 SizeY 27 OffsetBottom -411 +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "Random_startTimeMinutes" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 784 OffsetLeft 784 PositionY 70 OffsetTop 70 SizeX 180 OffsetRight -964 SizeY 42 OffsetBottom -112 } + components { + SCR_ButtonTextComponent "{5548F0143AE99095}" { + m_sText "Random" + } } + } +TextWidgetClass { + Name "Label_timeMultiplier" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 154 OffsetTop 154 SizeX 368 OffsetRight -396 SizeY 28 OffsetBottom -182 } Color 0.9 0.92 0.94 1 Text "Next-round time speed (1-24x)" "Font Size" 20 "Min Font Size" 20 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } } - TextWidgetClass { - Name "Saved_timeMultiplier" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 412 OffsetTop 412 SizeX 350 OffsetRight -378 SizeY 22 OffsetBottom -434 - } +TextWidgetClass { + Name "Saved_timeMultiplier" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 186 OffsetTop 186 SizeX 936 OffsetRight -964 SizeY 24 OffsetBottom -210 } Color 0.9 0.92 0.94 1 Text "Waiting for saved value" "Font Size" 16 "Min Font Size" 16 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } } - ButtonWidgetClass : "{0022F0B45ADBC5AC}UI/layouts/WidgetLibrary/EditBox/WLib_EditBox.layout" { - Name "timeMultiplier" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 386 OffsetLeft 386 PositionY 384 OffsetTop 384 SizeX 260 OffsetRight -646 SizeY 42 OffsetBottom -426 - } +ButtonWidgetClass : "{DA43C77A0D1E59F8}UI/layouts/ERR/AdminValue.layout" { + Name "timeMultiplier" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 408 OffsetLeft 408 PositionY 154 OffsetTop 154 SizeX 240 OffsetRight -648 SizeY 42 OffsetBottom -196 } components { SCR_EditBoxComponent "{547290FFBD5B33E9}" { m_sLabel "" } } } - ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { - Name "Apply_timeMultiplier" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 664 OffsetLeft 664 PositionY 384 OffsetTop 384 SizeX 150 OffsetRight -814 SizeY 42 OffsetBottom -426 - } +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "Apply_timeMultiplier" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 660 OffsetLeft 660 PositionY 154 OffsetTop 154 SizeX 112 OffsetRight -772 SizeY 42 OffsetBottom -196 } components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "Apply" } } } - TextWidgetClass { - Name "Label_startDateCode" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 442 OffsetTop 442 SizeX 350 OffsetRight -378 SizeY 27 OffsetBottom -469 +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "Random_timeMultiplier" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 784 OffsetLeft 784 PositionY 154 OffsetTop 154 SizeX 180 OffsetRight -964 SizeY 42 OffsetBottom -196 } + components { + SCR_ButtonTextComponent "{5548F0143AE99095}" { + m_sText "Random" + } } + } +TextWidgetClass { + Name "Label_startDateCode" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 238 OffsetTop 238 SizeX 368 OffsetRight -396 SizeY 28 OffsetBottom -266 } Color 0.9 0.92 0.94 1 Text "Start date (YYYY-MM-DD or authored)" "Font Size" 20 "Min Font Size" 20 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } } - TextWidgetClass { - Name "Saved_startDateCode" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 470 OffsetTop 470 SizeX 350 OffsetRight -378 SizeY 22 OffsetBottom -492 - } +TextWidgetClass { + Name "Saved_startDateCode" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 270 OffsetTop 270 SizeX 936 OffsetRight -964 SizeY 24 OffsetBottom -294 } Color 0.9 0.92 0.94 1 Text "Waiting for saved value" "Font Size" 16 "Min Font Size" 16 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } } - ButtonWidgetClass : "{0022F0B45ADBC5AC}UI/layouts/WidgetLibrary/EditBox/WLib_EditBox.layout" { - Name "startDateCode" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 386 OffsetLeft 386 PositionY 442 OffsetTop 442 SizeX 260 OffsetRight -646 SizeY 42 OffsetBottom -484 - } +ButtonWidgetClass : "{DA43C77A0D1E59F8}UI/layouts/ERR/AdminValue.layout" { + Name "startDateCode" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 408 OffsetLeft 408 PositionY 238 OffsetTop 238 SizeX 240 OffsetRight -648 SizeY 42 OffsetBottom -280 } components { SCR_EditBoxComponent "{547290FFBD5B33E9}" { m_sLabel "" } } } - ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { - Name "Apply_startDateCode" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 664 OffsetLeft 664 PositionY 442 OffsetTop 442 SizeX 150 OffsetRight -814 SizeY 42 OffsetBottom -484 - } +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "Apply_startDateCode" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 660 OffsetLeft 660 PositionY 238 OffsetTop 238 SizeX 112 OffsetRight -772 SizeY 42 OffsetBottom -280 } components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "Apply" } } } - TextWidgetClass { - Name "Label_weatherProfile" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 500 OffsetTop 500 SizeX 350 OffsetRight -378 SizeY 27 OffsetBottom -527 +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "Random_startDateCode" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 784 OffsetLeft 784 PositionY 238 OffsetTop 238 SizeX 180 OffsetRight -964 SizeY 42 OffsetBottom -280 } + components { + SCR_ButtonTextComponent "{5548F0143AE99095}" { + m_sText "Random" + } } + } +TextWidgetClass { + Name "Label_weatherProfile" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 322 OffsetTop 322 SizeX 368 OffsetRight -396 SizeY 28 OffsetBottom -350 } Color 0.9 0.92 0.94 1 Text "Weather (authored / clear / overcast / rain)" "Font Size" 20 "Min Font Size" 20 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } } - TextWidgetClass { - Name "Saved_weatherProfile" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 528 OffsetTop 528 SizeX 350 OffsetRight -378 SizeY 22 OffsetBottom -550 - } +TextWidgetClass { + Name "Saved_weatherProfile" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 354 OffsetTop 354 SizeX 936 OffsetRight -964 SizeY 24 OffsetBottom -378 } Color 0.9 0.92 0.94 1 Text "Waiting for saved value" "Font Size" 16 "Min Font Size" 16 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } } - ButtonWidgetClass : "{0022F0B45ADBC5AC}UI/layouts/WidgetLibrary/EditBox/WLib_EditBox.layout" { - Name "weatherProfile" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 386 OffsetLeft 386 PositionY 500 OffsetTop 500 SizeX 260 OffsetRight -646 SizeY 42 OffsetBottom -542 - } +ButtonWidgetClass : "{DA43C77A0D1E59F8}UI/layouts/ERR/AdminValue.layout" { + Name "weatherProfile" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 408 OffsetLeft 408 PositionY 322 OffsetTop 322 SizeX 240 OffsetRight -648 SizeY 42 OffsetBottom -364 } components { SCR_EditBoxComponent "{547290FFBD5B33E9}" { m_sLabel "" } } } - ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { - Name "Apply_weatherProfile" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 664 OffsetLeft 664 PositionY 500 OffsetTop 500 SizeX 150 OffsetRight -814 SizeY 42 OffsetBottom -542 - } +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "Apply_weatherProfile" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 660 OffsetLeft 660 PositionY 322 OffsetTop 322 SizeX 112 OffsetRight -772 SizeY 42 OffsetBottom -364 } components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "Apply" } } } - ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { - Name "IntelSummary" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 575 OffsetTop 575 SizeX 200 OffsetRight -228 SizeY 42 OffsetBottom -617 +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "Random_weatherProfile" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 784 OffsetLeft 784 PositionY 322 OffsetTop 322 SizeX 180 OffsetRight -964 SizeY 42 OffsetBottom -364 } + components { + SCR_ButtonTextComponent "{5548F0143AE99095}" { + m_sText "Random" + } } + } +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "RandomDay_startTimeMinutes" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 784 OffsetLeft 784 PositionY 112 OffsetTop 112 SizeX 180 OffsetRight -964 SizeY 32 OffsetBottom -144 } + components { + SCR_ButtonTextComponent "{5548F0143AE99095}" { + m_sText "Random day" + } + } + } +} } +FrameWidgetClass { Name "IntelPage" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 0 OffsetLeft 0 PositionY 160 OffsetTop 160 SizeX 1000 OffsetRight -1000 SizeY 486 OffsetBottom -646 } { +TextWidgetClass { + Name "IntelHelp" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 6 OffsetTop 6 SizeX 936 OffsetRight -964 SizeY 50 OffsetBottom -56 } + Color 0.9 0.92 0.94 1 Text "Set document frequency and how much each discovery reveals." "Font Size" 19 "Min Font Size" 19 Wrap 1 + FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } +} +TextWidgetClass { + Name "Label_aiIntelChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 80 OffsetTop 80 SizeX 368 OffsetRight -396 SizeY 28 OffsetBottom -108 } + Color 0.9 0.92 0.94 1 Text "AI carrying intel (0-100%)" "Font Size" 20 "Min Font Size" 20 Wrap 1 FontProperties FontProperties { + Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" + } + } +TextWidgetClass { + Name "Saved_aiIntelChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 112 OffsetTop 112 SizeX 936 OffsetRight -964 SizeY 24 OffsetBottom -136 } + Color 0.9 0.92 0.94 1 Text "Waiting for saved value" "Font Size" 16 "Min Font Size" 16 Wrap 1 FontProperties FontProperties { + Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" + } + } +ButtonWidgetClass : "{DA43C77A0D1E59F8}UI/layouts/ERR/AdminValue.layout" { + Name "aiIntelChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 408 OffsetLeft 408 PositionY 80 OffsetTop 80 SizeX 240 OffsetRight -648 SizeY 42 OffsetBottom -122 } + components { + SCR_EditBoxComponent "{547290FFBD5B33E9}" { + m_sLabel "" + } + } + } +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "Apply_aiIntelChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 660 OffsetLeft 660 PositionY 80 OffsetTop 80 SizeX 112 OffsetRight -772 SizeY 42 OffsetBottom -122 } + components { + SCR_ButtonTextComponent "{5548F0143AE99095}" { + m_sText "Apply" + } + } + } +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "Random_aiIntelChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 784 OffsetLeft 784 PositionY 80 OffsetTop 80 SizeX 180 OffsetRight -964 SizeY 42 OffsetBottom -122 } + components { + SCR_ButtonTextComponent "{5548F0143AE99095}" { + m_sText "Random" + } + } + } +TextWidgetClass { + Name "Label_intelRevealChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 168 OffsetTop 168 SizeX 368 OffsetRight -396 SizeY 28 OffsetBottom -196 } + Color 0.9 0.92 0.94 1 Text "First-document exact reveal (0-100%)" "Font Size" 20 "Min Font Size" 20 Wrap 1 FontProperties FontProperties { + Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" + } + } +TextWidgetClass { + Name "Saved_intelRevealChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 200 OffsetTop 200 SizeX 936 OffsetRight -964 SizeY 24 OffsetBottom -224 } + Color 0.9 0.92 0.94 1 Text "Waiting for saved value" "Font Size" 16 "Min Font Size" 16 Wrap 1 FontProperties FontProperties { + Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" + } + } +ButtonWidgetClass : "{DA43C77A0D1E59F8}UI/layouts/ERR/AdminValue.layout" { + Name "intelRevealChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 408 OffsetLeft 408 PositionY 168 OffsetTop 168 SizeX 240 OffsetRight -648 SizeY 42 OffsetBottom -210 } + components { + SCR_EditBoxComponent "{547290FFBD5B33E9}" { + m_sLabel "" + } + } + } +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "Apply_intelRevealChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 660 OffsetLeft 660 PositionY 168 OffsetTop 168 SizeX 112 OffsetRight -772 SizeY 42 OffsetBottom -210 } + components { + SCR_ButtonTextComponent "{5548F0143AE99095}" { + m_sText "Apply" + } + } + } +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "Random_intelRevealChancePercent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 784 OffsetLeft 784 PositionY 168 OffsetTop 168 SizeX 180 OffsetRight -964 SizeY 42 OffsetBottom -210 } + components { + SCR_ButtonTextComponent "{5548F0143AE99095}" { + m_sText "Random" + } + } + } +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "IntelSummary" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 276 OffsetTop 276 SizeX 260 OffsetRight -288 SizeY 42 OffsetBottom -318 } components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "Intel summary" } } } - ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { - Name "RerollIntel" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 250 OffsetLeft 250 PositionY 575 OffsetTop 575 SizeX 200 OffsetRight -450 SizeY 42 OffsetBottom -617 - } +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "RerollIntel" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 306 OffsetLeft 306 PositionY 276 OffsetTop 276 SizeX 260 OffsetRight -566 SizeY 42 OffsetBottom -318 } components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "Reroll AI intel" } } } - ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { - Name "OpenHQ" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 714 OffsetLeft 714 PositionY 575 OffsetTop 575 SizeX 250 OffsetRight -964 SizeY 42 OffsetBottom -617 - } - components { - SCR_ButtonTextComponent "{5548F0143AE99095}" { - m_sText "HQ / status" - } - } - } - TextWidgetClass { - Name "RerollHelp" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 625 OffsetTop 625 SizeX 936 OffsetRight -964 SizeY 26 OffsetBottom -651 - } - Color 0.9 0.92 0.94 1 Text "Reroll updates existing AI through the Intel service; recovered intel is preserved." "Font Size" 17 "Min Font Size" 17 Wrap 1 FontProperties FontProperties { - Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" - } - } - } - } - FrameWidgetClass { - Name "HQPage" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 0 OffsetLeft 0 PositionY 0 OffsetTop 0 SizeX 1000 OffsetRight -1000 SizeY 760 OffsetBottom -760 - } - { - TextWidgetClass { - Name "Label_reportIntervalSeconds" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 140 OffsetTop 140 SizeX 350 OffsetRight -378 SizeY 27 OffsetBottom -167 - } - Color 0.9 0.92 0.94 1 Text "Report interval (5-60 seconds)" "Font Size" 20 "Min Font Size" 20 Wrap 1 FontProperties FontProperties { - Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" - } - } - TextWidgetClass { - Name "Saved_reportIntervalSeconds" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 168 OffsetTop 168 SizeX 350 OffsetRight -378 SizeY 22 OffsetBottom -190 - } - Color 0.9 0.92 0.94 1 Text "Waiting for saved value" "Font Size" 16 "Min Font Size" 16 Wrap 1 FontProperties FontProperties { - Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" - } - } - ButtonWidgetClass : "{0022F0B45ADBC5AC}UI/layouts/WidgetLibrary/EditBox/WLib_EditBox.layout" { - Name "reportIntervalSeconds" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 386 OffsetLeft 386 PositionY 140 OffsetTop 140 SizeX 260 OffsetRight -646 SizeY 42 OffsetBottom -182 - } - components { - SCR_EditBoxComponent "{547290FFBD5B33E9}" { - m_sLabel "" - } - } - } - ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { - Name "Apply_reportIntervalSeconds" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 664 OffsetLeft 664 PositionY 140 OffsetTop 140 SizeX 150 OffsetRight -814 SizeY 42 OffsetBottom -182 - } - components { - SCR_ButtonTextComponent "{5548F0143AE99095}" { - m_sText "Apply" - } - } - } - TextWidgetClass { - Name "Label_supportSquadLimit" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 207 OffsetTop 207 SizeX 350 OffsetRight -378 SizeY 27 OffsetBottom -234 - } - Color 0.9 0.92 0.94 1 Text "Support squad limit (0-8)" "Font Size" 20 "Min Font Size" 20 Wrap 1 FontProperties FontProperties { - Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" - } - } - TextWidgetClass { - Name "Saved_supportSquadLimit" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 235 OffsetTop 235 SizeX 350 OffsetRight -378 SizeY 22 OffsetBottom -257 - } - Color 0.9 0.92 0.94 1 Text "Waiting for saved value" "Font Size" 16 "Min Font Size" 16 Wrap 1 FontProperties FontProperties { - Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" - } - } - ButtonWidgetClass : "{0022F0B45ADBC5AC}UI/layouts/WidgetLibrary/EditBox/WLib_EditBox.layout" { - Name "supportSquadLimit" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 386 OffsetLeft 386 PositionY 207 OffsetTop 207 SizeX 260 OffsetRight -646 SizeY 42 OffsetBottom -249 - } - components { - SCR_EditBoxComponent "{547290FFBD5B33E9}" { - m_sLabel "" - } - } - } - ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { - Name "Apply_supportSquadLimit" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 664 OffsetLeft 664 PositionY 207 OffsetTop 207 SizeX 150 OffsetRight -814 SizeY 42 OffsetBottom -249 - } - components { - SCR_ButtonTextComponent "{5548F0143AE99095}" { - m_sText "Apply" - } - } - } - TextWidgetClass { - Name "Label_responseRadiusMetres" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 274 OffsetTop 274 SizeX 350 OffsetRight -378 SizeY 27 OffsetBottom -301 - } - Color 0.9 0.92 0.94 1 Text "Response radius (500-5000 metres)" "Font Size" 20 "Min Font Size" 20 Wrap 1 FontProperties FontProperties { - Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" - } - } - TextWidgetClass { - Name "Saved_responseRadiusMetres" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 302 OffsetTop 302 SizeX 350 OffsetRight -378 SizeY 22 OffsetBottom -324 - } - Color 0.9 0.92 0.94 1 Text "Waiting for saved value" "Font Size" 16 "Min Font Size" 16 Wrap 1 FontProperties FontProperties { - Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" - } - } - ButtonWidgetClass : "{0022F0B45ADBC5AC}UI/layouts/WidgetLibrary/EditBox/WLib_EditBox.layout" { - Name "responseRadiusMetres" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 386 OffsetLeft 386 PositionY 274 OffsetTop 274 SizeX 260 OffsetRight -646 SizeY 42 OffsetBottom -316 - } - components { - SCR_EditBoxComponent "{547290FFBD5B33E9}" { - m_sLabel "" - } - } - } - ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { - Name "Apply_responseRadiusMetres" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 664 OffsetLeft 664 PositionY 274 OffsetTop 274 SizeX 150 OffsetRight -814 SizeY 42 OffsetBottom -316 - } - components { - SCR_ButtonTextComponent "{5548F0143AE99095}" { - m_sText "Apply" - } - } - } - TextWidgetClass { - Name "Status" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 350 OffsetTop 350 SizeX 936 OffsetRight -964 SizeY 210 OffsetBottom -560 - } - Color 0.9 0.92 0.94 1 Text "Waiting for mission status..." "Font Size" 19 "Min Font Size" 19 Wrap 1 FontProperties FontProperties { - Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" - } - } - ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { - Name "BackSettings" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 595 OffsetTop 595 SizeX 250 OffsetRight -278 SizeY 42 OffsetBottom -637 - } - components { - SCR_ButtonTextComponent "{5548F0143AE99095}" { - m_sText "Back to settings" - } - } - } - ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { - Name "OpenJournal" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 714 OffsetLeft 714 PositionY 595 OffsetTop 595 SizeX 250 OffsetRight -964 SizeY 42 OffsetBottom -637 - } - components { - SCR_ButtonTextComponent "{5548F0143AE99095}" { - m_sText "Open live journal" - } - } - } - } - } - FrameWidgetClass { - Name "JournalPage" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 0 OffsetLeft 0 PositionY 0 OffsetTop 0 SizeX 1000 OffsetRight -1000 SizeY 760 OffsetBottom -760 - } - { - TextWidgetClass { - Name "JournalHelp" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 110 OffsetTop 110 SizeX 936 OffsetRight -964 SizeY 30 OffsetBottom -140 - } - Color 0.9 0.92 0.94 1 Text "Radio reports, orders and physical support activity from the mission HQ." "Font Size" 19 "Min Font Size" 19 Wrap 1 FontProperties FontProperties { - Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" - } - } - ScrollLayoutWidgetClass { - Name "JournalScroll" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 150 OffsetTop 150 SizeX 936 OffsetRight -964 SizeY 400 OffsetBottom -550 - } +TextWidgetClass { + Name "IntelRerollHelp" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 336 OffsetTop 336 SizeX 936 OffsetRight -964 SizeY 52 OffsetBottom -388 } + Color 0.9 0.92 0.94 1 Text "Reroll updates existing AI documents. Recovered intel is preserved." "Font Size" 19 "Min Font Size" 19 Wrap 1 + FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } +} +TextWidgetClass { + Name "EvidenceHelp" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 402 OffsetTop 402 SizeX 936 OffsetRight -964 SizeY 60 OffsetBottom -462 } + Color 0.9 0.92 0.94 1 Text "Enemy bodies stay until a recovery team searches them and reports to HQ. Cleanup is then enabled with a five-minute delay." "Font Size" 19 "Min Font Size" 19 Wrap 1 + FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } +} +} } +FrameWidgetClass { Name "FactionsPage" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 0 OffsetLeft 0 PositionY 160 OffsetTop 160 SizeX 1000 OffsetRight -1000 SizeY 486 OffsetBottom -646 } { +TextWidgetClass { + Name "FactionHelp" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 6 OffsetTop 6 SizeX 936 OffsetRight -964 SizeY 50 OffsetBottom -56 } + Color 0.9 0.92 0.94 1 Text "Choose three distinct factions or Random. Saved choices apply next round." "Font Size" 19 "Min Font Size" 19 Wrap 1 + FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } +} +TextWidgetClass { Name "FactionLabel_escapists" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 76 OffsetTop 76 SizeX 280 OffsetRight -308 SizeY 32 OffsetBottom -108 } Color 0.9 0.92 0.94 1 Text "Escapists faction" "Font Size" 22 "Min Font Size" 22 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } } +ButtonWidgetClass : "{4B5AE6E64037FFB4}UI/layouts/WidgetLibrary/ComboBox/WLib_ComboBox.layout" { Name "FactionSelect_escapists" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 320 OffsetLeft 320 PositionY 76 OffsetTop 76 SizeX 644 OffsetRight -964 SizeY 42 OffsetBottom -118 } components { SCR_ComboBoxComponent "{546B1D464BC32853}" { m_bUseLabel 0 m_sLabel "" m_fSizeWithoutLabel 42 } } } +TextWidgetClass { Name "FactionState_escapists" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 124 OffsetTop 124 SizeX 936 OffsetRight -964 SizeY 44 OffsetBottom -168 } Color 0.9 0.92 0.94 1 Text "Waiting for server..." "Font Size" 18 "Min Font Size" 18 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } } +TextWidgetClass { Name "FactionLabel_enemy" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 184 OffsetTop 184 SizeX 280 OffsetRight -308 SizeY 32 OffsetBottom -216 } Color 0.9 0.92 0.94 1 Text "Enemy faction" "Font Size" 22 "Min Font Size" 22 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } } +ButtonWidgetClass : "{4B5AE6E64037FFB4}UI/layouts/WidgetLibrary/ComboBox/WLib_ComboBox.layout" { Name "FactionSelect_enemy" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 320 OffsetLeft 320 PositionY 184 OffsetTop 184 SizeX 644 OffsetRight -964 SizeY 42 OffsetBottom -226 } components { SCR_ComboBoxComponent "{546B1D464BC32853}" { m_bUseLabel 0 m_sLabel "" m_fSizeWithoutLabel 42 } } } +TextWidgetClass { Name "FactionState_enemy" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 232 OffsetTop 232 SizeX 936 OffsetRight -964 SizeY 44 OffsetBottom -276 } Color 0.9 0.92 0.94 1 Text "Waiting for server..." "Font Size" 18 "Min Font Size" 18 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } } +TextWidgetClass { Name "FactionLabel_independent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 292 OffsetTop 292 SizeX 280 OffsetRight -308 SizeY 32 OffsetBottom -324 } Color 0.9 0.92 0.94 1 Text "Independent / FIA faction" "Font Size" 22 "Min Font Size" 22 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } } +ButtonWidgetClass : "{4B5AE6E64037FFB4}UI/layouts/WidgetLibrary/ComboBox/WLib_ComboBox.layout" { Name "FactionSelect_independent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 320 OffsetLeft 320 PositionY 292 OffsetTop 292 SizeX 644 OffsetRight -964 SizeY 42 OffsetBottom -334 } components { SCR_ComboBoxComponent "{546B1D464BC32853}" { m_bUseLabel 0 m_sLabel "" m_fSizeWithoutLabel 42 } } } +TextWidgetClass { Name "FactionState_independent" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 340 OffsetTop 340 SizeX 936 OffsetRight -964 SizeY 44 OffsetBottom -384 } Color 0.9 0.92 0.94 1 Text "Waiting for server..." "Font Size" 18 "Min Font Size" 18 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } } +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { Name "FactionsRandomAll" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 418 OffsetTop 418 SizeX 220 OffsetRight -248 SizeY 42 OffsetBottom -460 } components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "Random all" } } } +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { Name "FactionsApply" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 742 OffsetLeft 742 PositionY 418 OffsetTop 418 SizeX 222 OffsetRight -964 SizeY 42 OffsetBottom -460 } components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "Apply factions" } } } +} } +FrameWidgetClass { Name "ModsPage" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 0 OffsetLeft 0 PositionY 160 OffsetTop 160 SizeX 1000 OffsetRight -1000 SizeY 486 OffsetBottom -646 } { +TextWidgetClass { + Name "ModsHelp" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 6 OffsetTop 6 SizeX 936 OffsetRight -964 SizeY 50 OffsetBottom -56 } + Color 0.9 0.92 0.94 1 Text "Choose content the mission may use. Required Workshop downloads stay installed." "Font Size" 19 "Min Font Size" 19 Wrap 1 + FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } +} +TextWidgetClass { + Name "ModsScope" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 58 OffsetTop 58 SizeX 936 OffsetRight -964 SizeY 46 OffsetBottom -104 } + Color 0.9 0.92 0.94 1 Text "Disabling a pack disables its factions. Saved preferences apply next round." "Font Size" 19 "Min Font Size" 19 Wrap 1 + FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } +} +ScrollLayoutWidgetClass { Name "ModsScroll" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 112 OffsetTop 112 SizeX 936 OffsetRight -964 SizeY 362 OffsetBottom -474 } { +VerticalLayoutWidgetClass { Name "ModList" Slot AlignableSlot { HorizontalAlign 3 VerticalAlign 3 } { } } +} } +} } +FrameWidgetClass { Name "JournalPage" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 0 OffsetLeft 0 PositionY 160 OffsetTop 160 SizeX 1000 OffsetRight -1000 SizeY 486 OffsetBottom -646 } { +TextWidgetClass { + Name "JournalHelp" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 6 OffsetTop 6 SizeX 936 OffsetRight -964 SizeY 50 OffsetBottom -56 } + Color 0.9 0.92 0.94 1 Text "Radio reports, orders and physical support activity from the mission HQ." "Font Size" 19 "Min Font Size" 19 Wrap 1 + FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } +} +ScrollLayoutWidgetClass { + Name "JournalScroll" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 58 OffsetTop 58 SizeX 936 OffsetRight -964 SizeY 320 OffsetBottom -378 } components { SCR_GamepadScrollComponent "{5707100AC31E657E}" { } @@ -533,50 +546,121 @@ FrameWidgetClass { } } } - TextWidgetClass { - Name "JournalState" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 558 OffsetTop 558 SizeX 936 OffsetRight -964 SizeY 34 OffsetBottom -592 - } +TextWidgetClass { + Name "JournalState" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 386 OffsetTop 386 SizeX 936 OffsetRight -964 SizeY 42 OffsetBottom -428 } Color 0.9 0.92 0.94 1 Text "Waiting for the server..." "Font Size" 17 "Min Font Size" 17 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } } - ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { - Name "BackHQ" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 605 OffsetTop 605 SizeX 250 OffsetRight -278 SizeY 42 OffsetBottom -647 - } - components { - SCR_ButtonTextComponent "{5548F0143AE99095}" { - m_sText "Back to HQ" - } - } - } - ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { - Name "PauseJournal" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 365 OffsetLeft 365 PositionY 605 OffsetTop 605 SizeX 250 OffsetRight -615 SizeY 42 OffsetBottom -647 - } +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "PauseJournal" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 438 OffsetTop 438 SizeX 220 OffsetRight -248 SizeY 42 OffsetBottom -480 } components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "Pause live" } } } - ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { - Name "LatestJournal" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 714 OffsetLeft 714 PositionY 605 OffsetTop 605 SizeX 250 OffsetRight -964 SizeY 42 OffsetBottom -647 - } +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "LatestJournal" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 742 OffsetLeft 742 PositionY 438 OffsetTop 438 SizeX 222 OffsetRight -964 SizeY 42 OffsetBottom -480 } components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "Jump to latest" } } } +} } +FrameWidgetClass { Name "StatusPage" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 0 OffsetLeft 0 PositionY 160 OffsetTop 160 SizeX 1000 OffsetRight -1000 SizeY 486 OffsetBottom -646 } { +TextWidgetClass { + Name "StatusHelp" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 6 OffsetTop 6 SizeX 936 OffsetRight -964 SizeY 50 OffsetBottom -56 } + Color 0.9 0.92 0.94 1 Text "Live mission state. Scroll to see all services and support activity." "Font Size" 19 "Min Font Size" 19 Wrap 1 + FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } +} +ScrollLayoutWidgetClass { + Name "StatusScroll" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 58 OffsetTop 58 SizeX 936 OffsetRight -964 SizeY 416 OffsetBottom -474 } + components { + SCR_GamepadScrollComponent "{5707100AC31E657E}" { + } + } + { + VerticalLayoutWidgetClass { + Name "StatusContent" Slot AlignableSlot { + HorizontalAlign 3 VerticalAlign 3 Padding 8 4 14 4 + } + { + TextWidgetClass { + Name "Status" Slot LayoutSlot { + HorizontalAlign 3 Padding 0 0 0 8 SizeMode Fill + } + Clipping Ancestor Color 0.9 0.92 0.94 1 Text "Waiting for mission status..." "Font Size" 18 "Min Font Size" 18 Wrap 1 FontProperties FontProperties { + Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" + } + } + } + } + } + } +} } +TextWidgetClass { + Name "Title" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 20 OffsetTop 20 SizeX 790 OffsetRight -818 SizeY 44 OffsetBottom -64 } + Color 0.9 0.92 0.94 1 Text "Escapists Reintroduced" "Font Size" 32 "Min Font Size" 32 Wrap 1 + FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } +} +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "Close" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 844 OffsetLeft 844 PositionY 24 OffsetTop 24 SizeX 120 OffsetRight -964 SizeY 42 OffsetBottom -66 } + components { + SCR_ButtonTextComponent "{5548F0143AE99095}" { + m_sText "Close" + } } } - TextWidgetClass { - Name "Feedback" Slot FrameWidgetSlot { - Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 668 OffsetTop 668 SizeX 936 OffsetRight -964 SizeY 78 OffsetBottom -746 +TextWidgetClass { + Name "Connection" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 70 OffsetTop 70 SizeX 936 OffsetRight -964 SizeY 28 OffsetBottom -98 } + Color 0.9 0.92 0.94 1 Text "Requesting administrator access..." "Font Size" 18 "Min Font Size" 18 Wrap 1 FontProperties FontProperties { + Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } + } +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "OpenSettings" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 106 OffsetTop 106 SizeX 112 OffsetRight -140 SizeY 42 OffsetBottom -148 } + components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "Mission" } } +} +ImageWidgetClass { Name "Selected_OpenSettings" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 151 OffsetTop 151 SizeX 112 OffsetRight -140 SizeY 3 OffsetBottom -154 } Color 0.9 0.66 0.25 1 } +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "OpenWorld" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 146 OffsetLeft 146 PositionY 106 OffsetTop 106 SizeX 112 OffsetRight -258 SizeY 42 OffsetBottom -148 } + components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "World" } } +} +ImageWidgetClass { Name "Selected_OpenWorld" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 146 OffsetLeft 146 PositionY 151 OffsetTop 151 SizeX 112 OffsetRight -258 SizeY 3 OffsetBottom -154 } Color 0.9 0.66 0.25 1 } +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "OpenFactions" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 264 OffsetLeft 264 PositionY 106 OffsetTop 106 SizeX 112 OffsetRight -376 SizeY 42 OffsetBottom -148 } + components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "Factions" } } +} +ImageWidgetClass { Name "Selected_OpenFactions" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 264 OffsetLeft 264 PositionY 151 OffsetTop 151 SizeX 112 OffsetRight -376 SizeY 3 OffsetBottom -154 } Color 0.9 0.66 0.25 1 } +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "OpenMods" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 382 OffsetLeft 382 PositionY 106 OffsetTop 106 SizeX 112 OffsetRight -494 SizeY 42 OffsetBottom -148 } + components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "Mods" } } +} +ImageWidgetClass { Name "Selected_OpenMods" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 382 OffsetLeft 382 PositionY 151 OffsetTop 151 SizeX 112 OffsetRight -494 SizeY 3 OffsetBottom -154 } Color 0.9 0.66 0.25 1 } +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "OpenHQ" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 500 OffsetLeft 500 PositionY 106 OffsetTop 106 SizeX 112 OffsetRight -612 SizeY 42 OffsetBottom -148 } + components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "HQ" } } +} +ImageWidgetClass { Name "Selected_OpenHQ" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 500 OffsetLeft 500 PositionY 151 OffsetTop 151 SizeX 112 OffsetRight -612 SizeY 3 OffsetBottom -154 } Color 0.9 0.66 0.25 1 } +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "OpenIntel" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 618 OffsetLeft 618 PositionY 106 OffsetTop 106 SizeX 112 OffsetRight -730 SizeY 42 OffsetBottom -148 } + components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "Intel" } } +} +ImageWidgetClass { Name "Selected_OpenIntel" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 618 OffsetLeft 618 PositionY 151 OffsetTop 151 SizeX 112 OffsetRight -730 SizeY 3 OffsetBottom -154 } Color 0.9 0.66 0.25 1 } +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "OpenStatus" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 736 OffsetLeft 736 PositionY 106 OffsetTop 106 SizeX 112 OffsetRight -848 SizeY 42 OffsetBottom -148 } + components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "Status" } } +} +ImageWidgetClass { Name "Selected_OpenStatus" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 736 OffsetLeft 736 PositionY 151 OffsetTop 151 SizeX 112 OffsetRight -848 SizeY 3 OffsetBottom -154 } Color 0.9 0.66 0.25 1 } +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { + Name "OpenJournal" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 854 OffsetLeft 854 PositionY 106 OffsetTop 106 SizeX 112 OffsetRight -966 SizeY 42 OffsetBottom -148 } + components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "Journal" } } +} +ImageWidgetClass { Name "Selected_OpenJournal" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 854 OffsetLeft 854 PositionY 151 OffsetTop 151 SizeX 112 OffsetRight -966 SizeY 3 OffsetBottom -154 } Color 0.9 0.66 0.25 1 } +TextWidgetClass { + Name "Feedback" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 670 OffsetTop 670 SizeX 936 OffsetRight -964 SizeY 70 OffsetBottom -740 } Color 0.9 0.92 0.94 1 Text "" "Font Size" 17 "Min Font Size" 17 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } diff --git a/addons/core/UI/layouts/ERR/AdminValue.layout b/addons/core/UI/layouts/ERR/AdminValue.layout new file mode 100644 index 0000000..3ced327 --- /dev/null +++ b/addons/core/UI/layouts/ERR/AdminValue.layout @@ -0,0 +1,21 @@ +ButtonWidgetClass : "{0022F0B45ADBC5AC}UI/layouts/WidgetLibrary/EditBox/WLib_EditBox.layout" { + Name "AdminValue" + components { + SCR_EditBoxComponent "{547290FFBD5B33E9}" { + m_bUseLabel 0 + m_sLabel "" + m_fSizeWithoutLabel 42 + } + } + { + VerticalLayoutWidgetClass "{5AA4D27F39EB2514}" { + Prefab "{5AA4D27F39EB2514}" + { + SizeLayoutWidgetClass "{5538C205B27B0F5D}" { + Prefab "{5538C205B27B0F5D}" + HeightOverride 42 + } + } + } + } +} diff --git a/addons/core/UI/layouts/ERR/AdminValue.layout.meta b/addons/core/UI/layouts/ERR/AdminValue.layout.meta new file mode 100644 index 0000000..39f2380 --- /dev/null +++ b/addons/core/UI/layouts/ERR/AdminValue.layout.meta @@ -0,0 +1,11 @@ +MetaFileClass { + Name "{DA43C77A0D1E59F8}UI/layouts/ERR/AdminValue.layout" + Configurations { + LayoutResourceClass PC { } + LayoutResourceClass HEADLESS : PC { } + LayoutResourceClass XBOX_ONE : PC { } + LayoutResourceClass XBOX_SERIES : PC { } + LayoutResourceClass PS4 : PC { } + LayoutResourceClass PS5 : PC { } + } +} diff --git a/addons/core/UI/layouts/ERR/ContentRow.layout b/addons/core/UI/layouts/ERR/ContentRow.layout new file mode 100644 index 0000000..45745f1 --- /dev/null +++ b/addons/core/UI/layouts/ERR/ContentRow.layout @@ -0,0 +1,8 @@ +SizeLayoutWidgetClass { Name "ContentRow" Slot LayoutSlot { HorizontalAlign 3 Padding 0 0 0 16 } WidthOverride 900 HeightOverride 160 { +FrameWidgetClass { Name "ContentRowBody" Slot AlignableSlot { HorizontalAlign 3 VerticalAlign 3 } { +TextWidgetClass { Name "PackLabel" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 0 OffsetLeft 0 PositionY 0 OffsetTop 0 SizeX 900 OffsetRight -900 SizeY 32 OffsetBottom -32 } Color 0.9 0.92 0.94 1 Text "Content pack" "Font Size" 26 "Min Font Size" 26 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } } +TextWidgetClass { Name "PackState" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 0 OffsetLeft 0 PositionY 40 OffsetTop 40 SizeX 900 OffsetRight -900 SizeY 30 OffsetBottom -70 } Color 0.9 0.92 0.94 1 Text "Waiting for server settings..." "Font Size" 18 "Min Font Size" 18 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } } +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { Name "Enable" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 0 OffsetLeft 0 PositionY 90 OffsetTop 90 SizeX 180 OffsetRight -180 SizeY 42 OffsetBottom -132 } components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "Enable" } } } +ButtonWidgetClass : "{75C912A1C89BE6C2}UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout" { Name "Disable" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 196 OffsetLeft 196 PositionY 90 OffsetTop 90 SizeX 180 OffsetRight -376 SizeY 42 OffsetBottom -132 } components { SCR_ButtonTextComponent "{5548F0143AE99095}" { m_sText "Disable" } } } +} } +} } diff --git a/addons/core/UI/layouts/ERR/ContentRow.layout.meta b/addons/core/UI/layouts/ERR/ContentRow.layout.meta new file mode 100644 index 0000000..05986d6 --- /dev/null +++ b/addons/core/UI/layouts/ERR/ContentRow.layout.meta @@ -0,0 +1,11 @@ +MetaFileClass { + Name "{F092D45656A8E02B}UI/layouts/ERR/ContentRow.layout" + Configurations { + LayoutResourceClass PC { } + LayoutResourceClass HEADLESS : PC { } + LayoutResourceClass XBOX_ONE : PC { } + LayoutResourceClass XBOX_SERIES : PC { } + LayoutResourceClass PS4 : PC { } + LayoutResourceClass PS5 : PC { } + } +} diff --git a/addons/core/UI/layouts/ERR/PauseModsButton.layout b/addons/core/UI/layouts/ERR/PauseModsButton.layout new file mode 100644 index 0000000..4c31dcb --- /dev/null +++ b/addons/core/UI/layouts/ERR/PauseModsButton.layout @@ -0,0 +1,9 @@ +ButtonWidgetClass : "{9ECCD201BCF07E95}UI/layouts/Menus/PauseMenu/PauseMenuButton.layout" { + Name "ERR_MissionMods" + Slot LayoutSlot { } + components { + SCR_ButtonTextComponent "{5548F0143AE99095}" { + m_sText "Escapists Reintroduced" + } + } +} diff --git a/addons/core/UI/layouts/ERR/PauseModsButton.layout.meta b/addons/core/UI/layouts/ERR/PauseModsButton.layout.meta new file mode 100644 index 0000000..2824897 --- /dev/null +++ b/addons/core/UI/layouts/ERR/PauseModsButton.layout.meta @@ -0,0 +1,11 @@ +MetaFileClass { + Name "{F0351A624C87DE90}UI/layouts/ERR/PauseModsButton.layout" + Configurations { + LayoutResourceClass PC { } + LayoutResourceClass HEADLESS : PC { } + LayoutResourceClass XBOX_ONE : PC { } + LayoutResourceClass XBOX_SERIES : PC { } + LayoutResourceClass PS4 : PC { } + LayoutResourceClass PS5 : PC { } + } +} diff --git a/addons/core/addon.gproj b/addons/core/addon.gproj index 8773a4f..a1c5eff 100644 --- a/addons/core/addon.gproj +++ b/addons/core/addon.gproj @@ -7,6 +7,7 @@ GameProject { "595F2BF2F44836FB" "629B2BA37EFFD577" "5E524E4FEECCA92B" + "65930CB4CD0237B2" } Configurations { GameProjectConfig PC { diff --git a/docs/aggression-ai.md b/docs/aggression-ai.md new file mode 100644 index 0000000..ca4270c --- /dev/null +++ b/docs/aggression-ai.md @@ -0,0 +1,59 @@ +# Identified-body escalation and objective defence + +Implemented 2026-09-23 in the combined Core addon. These are server-owned mission services; clients do not request spawns or supply casualty counts. + +## Aggression and hunter UAZs + +Only a fresh BODY report delivered to HQ identifies a body for aggression. The identity is the immutable formation SourceId plus original roster slot. A status-known death can subsequently be identified once; multiple observers, repeat deliveries and status reports cannot inflate this counter. Missing or silent units do not count. + +`ERR_HQWatchRules.Aggression(bodies)` is `clamp(floor(bodies / 3), 0, 30)`. `Hunters(level)` is `ceil(level / 2)`, capped at 15: + +| Identified bodies | Aggression | Cumulative UAZ allowance | +|---:|---:|---:| +| 0–2 | 0 | 0 | +| 3–8 | 1–2 | 1 | +| 9–14 | 3–4 | 2 | +| 45 | 15 | 8 | +| 87–89 | 29 | 15 | +| 90+ | 30 | 15 | + +The existing confirmed-loss infantry response budget remains independent. The new allowance creates **additional hunter UAZ-PKM vehicles**, separate from supply convoys, each with the selected primary enemy faction's driver and gunner. There are at most 15 deployments per round, not an endless replacement pool. Destroyed, captured or failed vehicles consume their deployment; surviving entities and loot remain physical. Surviving AI crew retain their HQ registration and skill profile when a driving task ends; capture releases the mission binding. The status string distinguishes active vehicles from the cumulative allowance. + +Deployment waits until the prison is unlocked and checks friendly-site road access, terrain, collision, the force-ledger cap and a 400 m player exclusion radius. A blocked candidate is retried after 30 seconds; native crew readiness has a 30-second deadline. Vehicles are registered only with their actual original native agents and seat occupants. Faction selection, inventory, radio fitting and body/intel ownership use existing mission services. + +Without delivered sightings, hunters patrol roads between friendly objectives. With fresh actionable HQ memory, they intercept a road near the last reported/predicted position. Destination selection does not query live player positions. Orders must traverse the existing physical radio network. Loss of communications prevents new orders; it does not magically reveal a player or cancel the last received order. + +## Objective crews + +Radio, supply/medical, extraction and outpost locations have permanent local defence roles. HQ still receives their real reports, but cannot borrow them for searches, couriers, resupply or reinforcement assignments elsewhere. Prison patrols retain their existing release behaviour, and mortar/scout/air-support reservations remain specialized. + +Within 600 m of an objective, existing living guards are reused. If no guards remain, the site can receive one finite 3–5-member relief crew per round, preserving the site's original faction. Spawning is deferred within 200 m of players and requires standable terrain. Complete native expansion is required before admission. Its native Defend waypoint uses the actual terrain-height objective position and a 40 m radius. No recurring refill loop is introduced. + +The mission currently has a **medical supply stash**, not a spawned hospital building. This stash participates in objective defence. New objective sites can use the same service by registering their site kind in `ERR_ObjectiveDefence.Objective`. + +## Skill, accuracy and perception + +Mission-owned hostile military AI use `EAISkill.CYLON` for maximum skill while the native aim-error node uses the `REGULAR` random-error distribution. This avoids CYLON's zero-error shooting. Recognition uses the native alerted factor (2.5) even in safe/suppressed states, preserving equipment factors and the engine's visibility/occlusion checks. This does not create through-wall vision or knowledge of unseen players. + +The authorized original AI code supplied the scoped skill/equipment and detection-hook approach. The separate aim-error reduction is new: no corresponding independent accuracy hook was found in the inspected original. Native `SCR_AIGetAimErrorOffset` and `SCR_AICombatComponent` implementations were used to separate these behaviours. + +Actual enemy-detection events activate local native combat and bring forward the next HQ report; report delivery still obeys radio routing. Primary-enemy units share HQ. Other hostile factions receive the same scoped skill/aim policy but do not leak intelligence to a mutually hostile faction. Specialist scouts and flight crews retain their authored equipment. Captured/ineligible actors are excluded from the profile, and normal teardown restores prior skill and native perception. + +## Audit trail and adjustment + +The complete HQ journal is `$logs:rereintroduced-hq.log` (existing filename retained). Relevant events: + +- `AGGRESSION`: delivered body source/slot, distinct-body count, level and allowance. +- `HUNTER SPAWN`, `READY`, `WAIT`, `ORDER`, `FAILED`, `RELEASE`: why/where each UAZ deployed, base, crew size, radio order and lifecycle. +- `REGISTER`, `SPAWN MEMBER`: group and force identity, faction, prefab, position, members, home and dedicated role. +- `ROLE RESERVED`, `OBJECTIVE DEFENCE`: site assignment, reuse or relief deployment and reassignment restriction. +- `CONTACT LOCAL`: observed position, source group and local role; at most one diagnostic per group per ten seconds. +- `SPAWN PURPOSE`: links body-inspection teams to their reported-body destination. + +`SPAWN GROUP` also appears in the normal script/console log for mission groups, including non-primary factions. Coordinates are world metres. Changes are event-driven or throttled, not a per-frame unit dump. Existing radio, order, status, search and support journal records remain available. + +## Verification + +Production-method policy tests cover body/status deduplication, three-body thresholds, 30/15 caps, reset, authority/capture boundaries, maximum skill binding/restoration, regular aim-error selection and native perception fallback. The native `aggression` fixture exercises actual body intake, a physical UAZ with seated crew, radio delivery and movement, objective reservations, medical-stash reinforcement admission and teardown. This is local native Workbench validation, not a dedicated-server multiplayer or full 15-UAZ performance benchmark. + +Final local run: `/tmp/erri-aggression-native7/logs/logs_2026-09-23_15-01-06`. All 14 native assertions and the completion marker passed: full medical defence at terrain height, seated driver/gunner, real radio delivery, driving over 30 m, bounded deployment and surviving-crew profile after release. Source stayed unchanged during the run. The runner reported a transient empty-argv Wine `enfMain` during cleanup; a subsequent explicit private-prefix idle check passed. Existing external localization/resource messages remain in the native log; this is not a clean-log claim. `python tools/check.py` passed, and the final hunter lifecycle and affected skill/body/registration policy tests passed separately. diff --git a/docs/ai-equipment-migration.md b/docs/ai-equipment-migration.md index 6d7e519..8514f7a 100644 --- a/docs/ai-equipment-migration.md +++ b/docs/ai-equipment-migration.md @@ -1,5 +1,7 @@ # Enemy skill and finite startup equipment migration +Current policy (2026-09-23): [aggression and AI profile](aggression-ai.md) supersedes the historical Expert infantry floor below. All mission hostile military AI now use maximum decision skill with separate regular aim error. + Adapted from independently authored, user-authorized AI code. Original files remain read-only; no original Escapists helpers, protected-derived `EAI_GroupLookup`, patched prefabs or asset bytes are imported. | Owned source | SHA-256 | Reused behavior | diff --git a/docs/ai-feature-migration.json b/docs/ai-feature-migration.json index a5df3ba..6b96d65 100644 --- a/docs/ai-feature-migration.json +++ b/docs/ai-feature-migration.json @@ -8,8 +8,8 @@ "counts": { "features": 39, "statuses": { - "partial": 17, - "missing": 18, + "partial": 21, + "missing": 14, "implemented": 4 }, "scripts": 54, @@ -181,19 +181,23 @@ { "id": "body_discovery", "title": "Visible bodies and confirmed losses", - "status": "missing", + "status": "partial", "original_files": [ "Scripts/Game/EscapistsAI/EAI_HQBodySearch.c", "Scripts/Game/EscapistsAI/EAI_HQWatch.c", "Scripts/Game/EscapistsAI/EAI_HQ.c" ], - "replacement_files": [], + "replacement_files": [ + "addons/core/Scripts/Game/ERR/10_AI/ERR_HQBodyObserver.c", + "addons/core/Scripts/Game/ERR/10_AI/ERR_BodyRecovery.c", + "addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelEvidence.c" + ], "behavior": [ "Death callback registers local evidence;60m view limit/12m close range;15s per-unit scans;12-trace shared budget;16 local discoveries", "radio-only deduplicated confirmations" ], - "remaining": "Independent death hook and bounded physical LOS intake; share evidence identity across status/body/missing-patrol reports. A casualty is not a known hostile position.", - "evidence": "code only", + "remaining": "Dedicated multiplayer, inaccessible bodies, interrupted recovery teams and hostile-faction permutations remain runtime acceptance cases. Missing documents indicate potentially compromised sites, not an enemy sighting.", + "evidence": "Native retained corpse, delivered body report, separately spawned recovery team, physical inspection and missing-document radio uplink passed on 22 September. See docs/hq-air-support.md.", "asset_scope": "vanilla" }, { @@ -293,7 +297,12 @@ "replacement_files": [ "addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftService.c", "addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftFlight.c", - "addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftRouteFlight.c" + "addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftRouteFlight.c", + "addons/core/Scripts/Game/ERR/10_AI/ERR_ReconAirports.c", + "addons/core/Scripts/Game/ERR/10_AI/ERR_AirReconSystem.c", + "addons/core/Scripts/Game/ERR/10_AI/ERR_ReconFlightComponent.c", + "addons/core/Scripts/Game/ERR/10_AI/ERR_ReconCrewLocks.c", + "addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirReconProbe.c" ], "behavior": [ "Incremental airport discovery", @@ -303,19 +312,24 @@ "runway return/landing retry", "player takeover release" ], - "remaining": "Flight mechanisms have isolated short-route evidence; airport search, useful routes, HQ-selected recon launch/orbit/endurance/service operational loop are missing.", - "evidence": "isolated20m flight only; no operational recon", - "asset_scope": "vanilla Mi8 candidate; original recon wrapper must be rebuilt" + "remaining": "Dedicated multiplayer acceptance and player boarding/takeover; faction-specific aircraft catalogs and full endurance/service/rearm cycle. Air assault remains separate.", + "evidence": "Native airfield launch, real player sighting/shadow orbit, physical crew radio delivery to HQ, flight, same-aircraft landing, full loss delay and retained wreck replacement passed in erri-recon-native4. Forced player boarding remained unverified. Final ownership/deletion results and exact limits: docs/search-helicopter.md.", + "asset_scope": "Current vanilla armed Mi8 wrapped with successor flight component and four original native pilot/gunner occupants; no obsolete custom left-gun resource." }, { "id": "air_assault", "title": "HQ-selected air reinforcement cycle", - "status": "missing", + "status": "partial", "original_files": [ "Scripts/Game/EscapistsAI/EAI_AirAssault.c", "Scripts/Game/EscapistsAI/EAI_AirSupportPolicy.c" ], - "replacement_files": [], + "replacement_files": [ + "addons/core/Scripts/Game/ERR/10_AI/ERR_AirAssaultSystem.c", + "addons/core/Scripts/Game/ERR/10_AI/ERR_AirSupportPolicy.c", + "addons/core/Scripts/Game/ERR/10_AI/ERR_AirAssaultLoad.c", + "addons/core/Scripts/Game/ERR/10_AI/ERR_AirfieldSupport.c" + ], "behavior": [ "Up to8 carried troops/two teams", "wait60s for mortar response", @@ -324,38 +338,44 @@ "abort stale/moved/conflicting reports;2min cover", "return/reload/reboard" ], - "remaining": "Build one shared HQ insertion capability with actual passenger reservations and mortar deconfliction; no new independent timer/spawn system.", - "evidence": "missing", - "asset_scope": "optional parachute framework; vanilla landing-and-dismount alternative changes behavior" + "remaining": "Dedicated multiplayer and adversarial remote ownership/packet-loss acceptance remain; current implementation uses four finite attempted loads and HQ memory/ground-strength decisions.", + "evidence": "Production memory/strength policy and cover-target/deadline regressions pass. Controlled native eight-person drop, same-airframe return, service and second eight-person departure passed. See docs/hq-air-support.md for scope.", + "asset_scope": "External Parachute Framework 65930CB4CD0237B2 is required; vanilla Mi-8 and original physical troops." }, { "id": "parachutes", "title": "Physical staggered AI parachute drop", - "status": "missing", + "status": "partial", "original_files": [ "Scripts/Game/EscapistsAI/EAI_AssaultParachute.c", "Scripts/Game/EscapistsAI/EAI_AirAssault.c" ], - "replacement_files": [], + "replacement_files": [ + "addons/core/Scripts/Game/ERR/10_AI/ERR_AssaultParachute.c", + "addons/core/Prefabs/ERR/AssaultParachute.et" + ], "behavior": [ "Moving25m/s flyby at90\u2013180m AGL;>=2s/50m stagger", "native compartment exits;5m/s descent/2m/s flare", "no duplicate soldiers", "released canopies finish after carrier loss" ], - "remaining": "Framework-dependent mechanics cannot enter vanilla-only closure; choose optional asset integration or landing insertion; do not silently claim equivalence.", - "evidence": "missing", + "remaining": "Dedicated-client replication, canopy destruction and late native transfer acceptance remain.", + "evidence": "Eight original actors boarded physical canopies and landed in the 22 September native airborne fixture.", "asset_scope": "Parachute Framework65930CB4CD0237B2" }, { "id": "aircraft_ammo", "title": "Aircraft weapon ammunition and airfield reload", - "status": "missing", + "status": "partial", "original_files": [ "Scripts/Game/EscapistsAI/EAI_AircraftAmmo.c", "Scripts/Game/EscapistsAI/EAI_AirRecon.c" ], - "replacement_files": [], + "replacement_files": [ + "addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftAmmo.c", + "addons/core/Scripts/Game/ERR/10_AI/ERR_AirfieldSupport.c" + ], "behavior": [ "Native mounted-magazine/rocket-barrel accounting", "return at<=25% usable ammunition", @@ -363,8 +383,8 @@ "verified physical passenger boarding/retries", "fixed finite payload per departure" ], - "remaining": "Replace original free service refill/new troops with shared depot cargo/personnel allocation and physically confirmed consumption.", - "evidence": "code only", + "remaining": "Airport service has finite gun-round, rocket-attempt and fuel budgets associated with physical depot entities. Spent rocket-pod runtime and dedicated multiplayer acceptance remain.", + "evidence": "Native same-airframe service consumed mounted-gun rounds and fuel before a second departure. Finite rocket-pod service compiles; spent-pod refill is not separately qualified. See docs/hq-air-support.md.", "asset_scope": "vanilla" }, { @@ -2410,12 +2430,12 @@ "post_audit_updates": [ { "id": "convoys", - "updated_on": "2026-09-20", + "updated_on": "2026-09-21", "status": "partial", - "implementation": "Finite six-vehicle/19-body shared-budget service with one opt-in canonical HQ dispatch, actual native road driving, exact initial seat membership and finite eight-rifle/48-magazine truck cargo. Delivered-report HQ HOLD/RESUME preserves each original crew, route index and owned waypoint; native mounted-combat registration is enabled. Automatic initial startup now defaults enabled, snapshots its saved setting per round, waits for existing admission and makes one bounded canonical attempt. Manual and automatic share the same receipt; no replacement after losses.", - "evidence": "native-2026-09-20-025035-convoy-driving: 181 assertions, all six original vehicles at least20m and lead over100m, duplicate dispatch rejected; zero script/runtime failures. Four external localization errors keep strict qualification failed. Current-source native-2026-09-20-041150-convoy-cover-driving repeats181 assertions after the cover integration; radio command transitions have executable-method tests, not native combat proof. native-2026-09-20-081658-automatic-convoy:93 assertions/one round, automatic six vehicles/19 original seated crew, duplicate dispatch rejected, zero script/runtime failures; four external localization errors remain.", - "remaining": "Direct native HOLD/RESUME and mounted firing; dismount/flank/reboard tactics, delivery/unloading, full-route reliability, multiplayer and FPS qualification. Capacity stays one initial convoy, not predecessor3/20.", - "detail": "docs/convoy-migration.md" + "implementation": "Original default-three, configurable0\u201320 finite six-vehicle convoys. Each has25 bodies/eight ledger groups: eleven mounted crew and two seven-person infantry teams. Bounded separated road startup, friendly-base circuits,45\u201390s rests,250m arrival/10min travel deadline. Native perception and delivered HQ contacts drive dismount/flank/escort cover/truck withdrawal and60s quiet reboarding with120s timeout. Random faction arsenal weapons and compatible finite ammunition, no replacements/refills. Saved count/random choice applies next round. Shared ledger and associated group bookkeeping expanded to256 formations.", + "evidence": "native-2026-09-20-025035-convoy-driving: 181 assertions, all six original vehicles at least20m and lead over100m, duplicate dispatch rejected; zero script/runtime failures. Four external localization errors keep strict qualification failed. Current-source native-2026-09-20-041150-convoy-cover-driving repeats181 assertions after the cover integration; radio command transitions have executable-method tests, not native combat proof. native-2026-09-20-081658-automatic-convoy:93 assertions/one round, automatic six vehicles/19 original seated crew, duplicate dispatch rejected, zero script/runtime failures; four external localization errors remain. Current full supply-convoy implementation: local 2026-09-21 16:50:45 smoke completed,36 common assertions, no script/runtime failures;18 vehicles/75 original soldiers,174 physical cargo inserts,all18 drove20m,both seven-person teams dismounted/reboarded and original truck drove next base leg after native pause. Source fingerprint380aec8a078825b165593fc4445b603f80b5d1ec51360c018d34973d65302b62 unchanged; cleanup confirmed. Controlled contact/travel-deadline inputs explicitly labelled. Nine pre-existing dependency errors prevent strict engine qualification. Details in docs/supply-convoys.md.", + "remaining": "Dedicated multiplayer, maximum-fleet performance and full-island route reliability qualification. Separate infantry ammunition rendezvous still uses the first convoy. Historical 2026-09-20 evidence predates the new circuit and infantry controller; see current validation in docs/supply-convoys.md.", + "detail": "docs/supply-convoys.md" }, { "id": "body_discovery", diff --git a/docs/ai-migration-progress.md b/docs/ai-migration-progress.md index 4992ca8..9970d03 100644 --- a/docs/ai-migration-progress.md +++ b/docs/ai-migration-progress.md @@ -1,5 +1,8 @@ # AI migration progress — 20 September 2026 +Current convoy implementation: [Supply convoys](supply-convoys.md) supersedes the single-convoy stages recorded below. + + The successor now has a persistent HQ belief model, bounded infantry pursuit, radio check-ins, missing-patrol investigations, local body discovery and a Core force ledger. These extend the existing playable mission and finite mortar/courier diff --git a/docs/airfield-extraction-and-map-icons.md b/docs/airfield-extraction-and-map-icons.md new file mode 100644 index 0000000..04d6d13 --- /dev/null +++ b/docs/airfield-extraction-and-map-icons.md @@ -0,0 +1,48 @@ +# Airfield extraction and map icons + +The live Everon scenario no longer creates `everon-supply-2`, its guards, UAZ or +crate. The remaining supply cache and medical stash provide the two reachable +radio-intel sources. Mortar reserve/courier preparation uses the existing eastern +outpost, preserving its finite logistics without creating a replacement site. + +Extraction is authored at 4800.953 / 11487.412 on Everon's airfield. Before +spawning the helicopter, `ERR_AirfieldPlacement` checks nearby physical airfield +anchors, dry terrain, slope and the aircraft/overhead clearance volume. A failed +check fails preparation; there is no fallback into the woods. New islands need +their own authored pad and recognizable airfield anchors. Aircraft damage and +physics remain normal after spawning. + +Exact discoveries use native wrapper images and matching glow images: +helicopter for extraction, radio for radio camps, artillery for mortar sites, +building for outposts, medical for medical supplies, and supplies for other caches. +The prison is now always hidden. Partial clues use a question mark. Icons are +applied after native marker initialization and reapplied when the map opens. +Partial markers use stable 500 m grid centres; all objective markers remain uneditable. + +## Verification — 22 September 2026 + +The full repository check passed during implementation; the mortar-logistics +regression also passed after changing its preparation source. The final Core +Workbench `airfield-markers` fixture passed 12 assertions and completed without +script errors or VM exceptions. It checked the removed site, a settled usable +aircraft on the real pad, rejection of the old forest point and occupied pad, +two reachable intel sources, all six site icon selections, and native map opening. + +Final local session: `/tmp/erri-airfield-markers6/logs/logs_2026-09-22_15-44-19`. +A direct capture of the private Workbench viewport visually confirmed the prison +lock replacing its circle. The other sites were outside that captured viewport; +the fixture checks their icon selections, not visual quality at every map zoom. + +Existing RHS/WCS localization, stock resource-keyword and native map-UI resource +errors remain visible in the strict report. The runner recorded smoke completion +but returned failure because its immediate cleanup check encountered an exiting +`enfMain` process with an empty command line. A subsequent host-visible +`assert_prefix_idle` check confirmed the private prefix was idle. This is local +Workbench validation, not dedicated multiplayer acceptance or a clean strict +engine report. No server deployment or Workshop publication was performed. + +Historical geometry-dependent smoke tests explicitly load `Tests/LegacySites.conf`; +production, `generated-sites`, `opening-tools` and `airfield-markers` use the live +scenario definitions. + +The lock-icon screenshot below is historical; the subsequent [mortar and prison changes](mortar-intel-and-prison-map.md) removed that marker and restored question marks. diff --git a/docs/configuration.md b/docs/configuration.md index df8a997..a7b5bc2 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -17,6 +17,7 @@ Open the normal game chat and enter a command. Core provides: | Command | Access | Effect | | --- | --- | --- | | `/esc status` | Server administrator | Current objective or startup failure cause; adds HQ status when Chat is loaded | +| `/esc killais` | Server administrator | Kill AI characters within 1,000 m of your living character; preserve players and vehicles | | `/esc settings` | Server administrator | Current shared settings and values | | `/esc mission radio show` | Server administrator | Radio defence duration in seconds | | `/esc mission radio set N` | Server administrator | Save a whole-number duration from 30 to 1800 seconds | @@ -41,9 +42,11 @@ Additional AI commands: | `/esc hq stinger show` | Show the saved one-in-N initial equipment chance | | `/esc hq stinger set N` | Set 0 to disable, 1 for every eligible actor, or 2–10000 for one in N; affects actors that have not rolled yet | | `/esc hq convoy show` | Show the finite deployment task, retained vehicles, native cargo insertion results and stop reason | -| `/esc hq convoy start` | Opt into one initial six-vehicle deployment near the authored southern supply site; requires a suitable actual road, physical readiness and room for all 19 crew within the 60-body convoy admission cap | +| `/esc hq convoy start` | Deploy the next unused slot in this round’s configured convoy allowance after physical force admission | +| `/esc convoys show` | Show the saved count and active fleet | +| `/esc convoys set 0..20` / `/esc convoys set random` | Save the next round’s convoy count; default 3; also available on the Mission page | -Convoy deployment is under native verification. It is not automatically enabled at round startup. The same per-round receipt is retained after retries, partial startup and losses; this command never replaces a consumed convoy. Cargo is issued once and insertion failures are reported. Combat dismount/reboarding, complete supply routing and HQ response retasking remain separate migration work. The admission cap is not yet a global presence/materialization service. See [AI progress](ai-migration-progress.md) and [external dependencies](external-addons.md). +Convoys automatically deploy after prison escape by default, travel between friendly military bases, and use the original infantry dismount/flank/reboard behavior. Each has six vehicles, 25 soldiers and finite random faction-arsenal cargo. Startup and losses consume slots permanently. The existing `automaticConvoyEnabled=0` preference remains respected. See [Supply convoys](supply-convoys.md) for configuration, timing and validation limits. The command parser and setting mutations have native service tests. Actual remote RPC ownership, chat usability and pre-spawn presentation still need multiplayer/UI acceptance. @@ -54,3 +57,100 @@ If the faction/catalog setup or authored site preparation fails, the mode retain Waiting for normal site preparation does not consume a player's spawn retry budget. Once ready, actual failed spawn requests are bounded. This does not remove the one-life or identity requirements. Core also provides `/esc mission abandon`: an administrator-only explicit defeat and normal restart for an active round. See [recovery policy](recovery.md). + +## Mission menu + +**Esc → Escapists Reintroduced** opens one administrator menu. Its top navigation +stays visible on every page: + +| Page | Controls | +| --- | --- | +| Mission | Radio defence duration and next-round convoy count | +| World | Start time, Random day, time speed, date and weather | +| Factions | Escapists, enemy and independent faction choices; Random all | +| Mods | Content pack and individual faction switches | +| HQ | Report interval, support squad limit and response radius | +| Intel | Document frequency, exact-reveal chance, summary and reroll | +| Status | Scrollable live mission and service status | +| Journal | Scrollable HQ activity, pause/resume and jump to latest | + +Changing pages preserves drafts and never applies them. Escape returns to Mission; +a second Escape closes the menu (an active text edit consumes Escape first). +Server authorization and capability checks still control every mutation. + +## Optional content + +Use **Esc → Escapists Reintroduced → Mods** for server-admin RHS and individual faction switches. +Selections apply after mission restart, while Workshop dependencies remain loaded. +See [content packs and the modder registry](content-packs.md). + +## Random settings + +Every editable setting on **Mission**, **World**, **HQ** and **Intel** has a +**Random** button. It selects the draft; press **Apply** to save it. You can still +enter a fixed value. The start-time row also offers **Random day**. + +- Random start time: any whole minute from 00:00 through 23:59. +- Random day: a whole minute strictly between the island's sunrise and sunset, + calculated after the selected date is applied. If no daylight interval is + available, preparation fails rather than silently starting at night. +- Random date: any valid date in the world's authored year (1900–2050), including + leap days where applicable. +- Random weather: clear, overcast or rain, with equal probability. +- Other fields: a uniformly selected integer within the range displayed beside + the field, including zero where allowed. Random speed uses 1–24×. + +The server retains the **Random** choice in its profile and selects a fresh value +for each mission instance. Reads and menu polling reuse that value. Applying the +same Random choice again does not reroll it; changing to a fixed value and then +back to Random does. Live settings retain their existing apply timing; clock, +calendar, weather and speed still apply only on the next round. Saved Random +values for live settings also show the resolved number in the menu. + +Text commands accept `random` in place of any of these ten values, for example +`/esc hq squads set random` or `/esc mission weather set random`. Time additionally +accepts `/esc mission time set random day` (or `random-day`). Existing numeric, +clock, date and named-weather values remain supported. Storage uses `-1` for +Random and `-2` exclusively for Random day; these are saved modes, never concrete +values passed to gameplay or the world clock. Existing settings files keep their +fixed choices without migration or an automatic rewrite. + +## Generated camps and map discovery + +Everon generates a fresh clear-terrain prison, radio camp and four mortar sites +each round. Partial intel shows question marks; exact discoveries use site icons. +The prison is never marked. See +[generated sites and debug commands](generated-sites.md) for placement limits, +authoring fields, failure behavior and validation. + +`/esc cheat intel` is an administrator-only command that places six fresh intel folders on clear ground within about 4.3 metres of the current living prisoner. It requires being on foot on terrain with enough nearby space. All six positions are checked first; a spawn failure removes the partial batch. Picking up the folders uses normal intel discovery and the configured reveal chance. + +The initial prison patrol contains 3–5 soldiers, chosen once during preparation from the selected enemy faction roster. An existing RTO is retained. If that roster has no large radio, one soldier is equipped with a physical manpack (US/USAF: AN/PRC-77; otherwise R-107M). Preparation waits for that radio to be present. The guards start at separate random clear positions 12–24 m around the prison and remain frozen until it is unlocked; other site squads keep their configured size. + +## Airfield extraction and site icons + +Everon extraction uses the airfield pad at 4800.953 / 11487.412. Site authors set +`RequireAirfield 1` and `AircraftOffset 0 0 0` on that extraction definition. +Preparation checks airfield anchors, terrain and clearance before creating the +aircraft, and refuses an invalid pad without relocating it elsewhere. + +Identified sites use helicopter, radio, artillery, building, medical and supplies +icons. Partial intel shows a question mark at an approximate position; the prison +remains hidden regardless of discovery. +The western guarded UAZ/crate site is removed; the medical stash provides the +second radio-intel source. See [implementation and validation](airfield-extraction-and-map-icons.md). + +See [mortar intel, original messages and perimeter guards](mortar-intel-and-prison-map.md) for the four-site configuration and validation. + +## Permanent radio security + +Radio sites require a guard squad. HQ permanently reserves that squad for the +radio's 20 m defend area; it cannot be dispatched on searches, reinforcements or +courier work. The generated Everon radio and table sit inside a full-size tent, +with standing room for interaction. See [radio camp security](radio-camp-security.md). + +Everon also sets `ScoutCount 10` in its scenario definition. This creates ten finite hilltop sniper/scout posts with radio-equipped ammunition packs; see [hill scouts](hill-scouts.md) for terrain criteria, loadouts and reporting. Other authored scenarios default to zero. + +Search helicopter: `heliTimerMinutes` defaults to 15 minutes after prison escape +and after aircraft loss. Use `/esc hq heli show`, `/esc hq heli timer set 15`, +or `/esc hq heli return`. See [search-helicopter.md](search-helicopter.md). diff --git a/docs/content-packs.md b/docs/content-packs.md new file mode 100644 index 0000000..5fef6be --- /dev/null +++ b/docs/content-packs.md @@ -0,0 +1,133 @@ +# Mission content packs and factions + +Administrators open **Esc → Escapists Reintroduced → Mods** (also available in `/esc menu`). RHS +and its US Marines, Russian Armed Forces and ION factions default to enabled. +Each faction can be disabled independently. Disabling the parent pack excludes +all its factions and the mission's optional RHS optics, while retaining child +preferences. Enable/disable controls are authenticated on the server; saved +preferences and current effective selections are shown separately. + +Changes apply on mission restart. Preferences live in +`$profile:EscapistsContent.json` on the server; use numeric `0`/`1` values for +`rhs`, `rhs_usmc`, `rhs_afrf`, and `rhs_ion`. Invalid existing files are preserved; +validated backup recovery and verified writes follow the mission settings +pattern. New registry entries use their authored default when absent from an +older file. Workshop dependencies stay installed and loaded. This controls what +the mission selects, not third-party scripts or a player's downloaded mods. + +Open **Mission settings → Factions** to select the **Escapists**, **Enemy**, and +**Independent / FIA** roles. Each dropdown offers Random plus enabled registered +factions (US Army, Soviet Army, FIA, and enabled RHS factions). **Random all** +sets all three drafts to Random; **Apply factions** saves them together. +Explicit choices must differ. Random reserves explicit choices first and fills +the remaining roles without duplicates. A previously selected faction that is +now disabled falls back to another eligible faction at round start. + +Role preferences are separate from pack enablement and live in +`$profile:EscapistsFactions.json`, for example: + +```json +{"escapists":"us","enemy":"ussr","independent":"fia"} +``` + +Each value can instead be `"random"`; RHS IDs are `rhs_usmc`, `rhs_afrf`, and +`rhs_ion`. The equivalent authenticated command is +`/esc factions set us ussr fia`. Saved choices and the current resolved factions +are displayed separately. Changes require mission restart and never reassign +live players or AI mid-round. + +The three selected sides are mutually hostile and friendly within their own +faction. Prisoners join the selected Escapists faction. Ordinary enemy guards +use the selected enemy group's native infantry. Sites with `AllowFactionPool` +alternate independent and main-enemy groups. The strategic HQ, radio network, +convoys and mortar logistics follow the main enemy; independent groups execute +native guard/patrol orders. Convoy infantry use the selected enemy profile. +Existing convoy vehicles, specialist mortar kits and the unarmed prisoner outfit +are retained; faction selection does not replace every vehicle or item asset. +All mission hostiles stay frozen until the prison is unlocked. + +The prison starter container is the original Kolobok backpack, stocked once with +five PM pistols, eight spare magazines and one map. Existing readiness checks +wait for actual inventory insertion and client storage ownership. + +## Adding a pack or faction + +No menu code, command code or fixed settings schema edits are needed. + +1. Add the Workshop dependency to `addons/core/addon.gproj` and install it in + Workbench. Update the test tooling allowlist in `tools/external_addons.py` and + extend `docs/external-addons.json` with the reviewed dependency + closure and exact resource GUID/path records used by this repository's tools. +2. Add a pack `ERR_ContentOption` to + `addons/core/Configs/ERR/Content/Registry.conf`: unique lowercase `Id`, readable + `Label`, `DefaultEnabled` (0 or 1), and optional `EquipmentGuids`. +3. Add one child option per combat faction with `Parent` set to the pack ID, + the exact `NativeFactionKey`, and `GuardGroup` resource. The group must spawn + its physical members immediately, with every member in that native faction. + Use distinct native keys for factions that should fight each other. +4. Add its `SCR_Faction` config to `Prefabs/ERR/FactionManager.et`, with + `m_bIsPlayable 0` and an empty `m_aFriendlyFactionsIds` list. The startup + validator checks the enabled factions and establishes mutual hostility. +5. Set `AllowFactionPool 1` on scenario sites eligible for faction variation. + These sites alternate the selected independent and main-enemy groups. + Other guarded sites use the main enemy profile. Specialist units retain + their mission equipment while following the selected enemy faction. +6. For new optional equipment selection code, call + `mode.Content().Allows(prefab)` before granting it, and register its GUID in + the owning option. Existing inherited equipment on faction characters stays + part of their prefab. Arbitrary native resource spawns are not intercepted. + +Example child entry (substitute real faction key/resource): + +```text +ERR_ContentOption { + Id "my_pack_infantry" + Label "My pack / Infantry" + Parent "my_pack" + DefaultEnabled 1 + NativeFactionKey "MY_INFANTRY" + GuardGroup "{REAL_RESOURCE_GUID}Prefabs/Groups/MyInfantry.et" +} +``` + +IDs are persistent preference keys: keep them stable across releases. The +registry rejects duplicate IDs, faction keys, resource ownership, missing +parents and nested parent chains. It supports up to 64 entries and the UI +scrolls automatically. Registered factions also populate the role dropdowns; +no separate menu registration is needed. Use keys distinct from US, USSR and FIA. +The server must load the faction and its group resource. This registry does not +automatically discover arbitrary unregistered Workshop factions. + +Commands: `/esc mods show`, `/esc mods rhs disable`, +`/esc mods rhs_usmc enable`, `/esc mods help`. + +## Verification — 21 September 2026 + +Production-policy tests cover role resolution, explicit-choice reservation, +unique Random-all selection, disabled-choice fallback, invalid choices, pack +and child gating, guard eligibility, and selected non-USSR convoy dispatch. + +The isolated native `core / prisoner-kit` run at +`/tmp/erri-factions-native3/logs/logs_2026-09-21_17-49-09` completed **341 assertions** +with USSR prisoners, RHS AFRF enemies and US independent guards. It compiled the +scripts and exercised actual player affiliation, physical guard groups, +hostility, authenticated role-menu save/restore, Random-all drafts, unchanged +active roles after save, unauthorized-command rejection, persistence reload, +backpack storage/readiness and the existing prisoner-kit checks. Sources and +dependencies stayed unchanged during the run; private runtime cleanup completed. +The faction page was rendered and inspected at `/tmp/erri-factions-menu.png`. +A second run (`/tmp/erri-factions-native4`) also completed 341 assertions +with RHS ION prisoners, US enemies and FIA independent guards, confirming +RHS player eligibility and FIA physical squads. Repository checks passed with +`python3 tools/check.py`. + +Native validation still reports four external RHS/WCS localization errors and +five unknown-keyword errors while preloading inherited RHS vehicle catalogs +(`SlidingTrackMaterial` and BTR70 `Parent` entries). There were no mission script +or smoke failures in the completed run. These are local scripted Workbench +checks, not dedicated-server, ordinary mouse/gamepad-input, or multiplayer +replication acceptance. No Workshop publishing was performed. + +Faction hostility follows the native +[SCR_FactionManager API](https://community.bistudio.com/wikidata/external-data/arma-reforger/ArmaReforgerScriptAPIPublic/interfaceSCR__FactionManager.html), +with both directions validated before preparation can finish. diff --git a/docs/convoy-migration.md b/docs/convoy-migration.md index 8cf40aa..434bbb3 100644 --- a/docs/convoy-migration.md +++ b/docs/convoy-migration.md @@ -1,5 +1,8 @@ # Finite physical convoy controller +> Superseded production behavior: see [Supply convoys](supply-convoys.md) for the original default-three fleet, full troop truck, base circuit and dismount/reboarding implementation. The evidence and implementation notes below describe the earlier single-convoy stages. + + Independent adaptation of owned `escapists-ai/Scripts/Game/EscapistsAI/EAI_SupplyConvoys.c`, SHA-256 `a896fdacfd9c0f2db52e588642623545a3a5d6e8041fb72000a68e720fc2b7a5`. Reused responsibilities are the six-vehicle catalog/order, native seat creation, independent native crew groups, finite cargo and owned-waypoint release. Original Escapists/ScrtCore helpers, original game mode hooks and `EAI_GroupLookup` are excluded. Native `BaseCompartmentSlot.SpawnCharacterInCompartment`, group vehicle manager and waypoint APIs replace those dependencies. The round owns one `ERR_ConvoyPool(mode,maxConvoys)` and one `ERR_ConvoyService(mode,pool)`. Reserve a unique authored source ID; dispatch its canonical one-use receipt with six authored positions/angles and a sealed, nonlooping Core `ERR_ForceRoute`. Resource, terrain/water/obstacle, faction and shared budget validation precede consumption. Consumption precedes native entity creation. Partial native startup consumes the slot and preserves every successfully created group, vehicle and actor; there is no refund or automatic retry/replacement. diff --git a/docs/convoy-startup.md b/docs/convoy-startup.md index 3eedfe2..aae332d 100644 --- a/docs/convoy-startup.md +++ b/docs/convoy-startup.md @@ -1,5 +1,8 @@ # Automatic finite convoy startup +> Superseded production behavior: see [Supply convoys](supply-convoys.md) for the original default-three fleet, full troop truck, base circuit and dismount/reboarding implementation. The evidence and implementation notes below describe the earlier single-convoy stages. + + The full AI scenario now enables one automatic initial convoy by default. Core-only scenarios remain unchanged. HQ freezes `automaticConvoyEnabled` when the round creates its command service; saving a different value affects the next round only. Commands use the existing authenticated mission administration: diff --git a/docs/discovery-map-usability.md b/docs/discovery-map-usability.md index aef53c1..bbb27f3 100644 --- a/docs/discovery-map-usability.md +++ b/docs/discovery-map-usability.md @@ -23,3 +23,10 @@ The actual coordinate policy passes positive, negative, boundary and exhaustive Vanilla local-marker deletion removes only active membership. A culled objective can remain in the disabled list and later reappear. The successor now removes only its own local discovery-marker type from both lists and detaches that marker's native map-close/layer listeners on deletion; duplicate cleanup is safe and never reactivates or creates a widget. The native fixture now moves its owned marker into the actual disabled list before testing both-membership removal. Native verification of this extension is pending. The [100619 integrated Core regression](evidence/native-2026-09-19-100619/report.json) now passes the revised native coordinate and disabled-list cleanup fixture in each of two complete rounds (612 total assertions, zero captured errors). Earlier pending statements describe the pre-run changes; manual map interaction remains separate. + +## Current intel presentation + +Partial clues use the native question-mark icon at the stable 500 m grid centre. +Identification replaces it with the site-specific icon; mortar sites use artillery. +The prison stays hidden. Messages match the owner’s original Intel addon. See +[mortar intel and prison visibility](mortar-intel-and-prison-map.md). diff --git a/docs/evidence/admin-pages-2026-09-22/README.md b/docs/evidence/admin-pages-2026-09-22/README.md new file mode 100644 index 0000000..1371745 --- /dev/null +++ b/docs/evidence/admin-pages-2026-09-22/README.md @@ -0,0 +1,25 @@ +# Mission pages and corpse retention — 22 September 2026 + +- `python tools/check.py`: passed; complete output in repository-checks.txt. +- `tests/test_intel_body_inspection.py`: executes the production Inspect, + RetainedWithin, Delivered and Release methods against engine boundary doubles. + Premature, client-side, stopped, unknown and duplicate reports cannot release or + renew corpse cleanup. A searched body with a delivered report releases once, + with a 300-second native cleanup lifetime. +- Native Core `prisoner-kit` fixture compiled and completed. The menu checks cover + all eight pages through the shared top navigation, only one visible page, + navigation geometry, all Random controls and Random day, preserved drafts, + authenticated Apply, mod/faction save and restoration, journal rendering, + close/reopen and authorization denial. This is local Workbench validation; + dedicated multiplayer was not run for this change. +- `page-0.png` through `page-7.png` are direct, unedited captures of the isolated + Workbench World Editor window. Page order: Mission, HQ, Journal, Mods, Factions, + World, Intel, Status. All pages were visually inspected. Workbench's built-in + engine screenshots omit UI, so they are not used as visual evidence here. +- `sources.json` records the tested source hashes. No source edits were made + during the native run. No Workshop publishing or server deployment was done. + +Native profile: `/tmp/erri-menu-pages-native5`. The runner reported a transient +exit-time idle-verification warning for an exiting process with an empty command +line. A subsequent explicit prefix-idle verification passed; no test process +remains. The fixture completed 345 assertions without script/runtime failures. diff --git a/docs/evidence/admin-pages-2026-09-22/native-menu-checks.txt b/docs/evidence/admin-pages-2026-09-22/native-menu-checks.txt new file mode 100644 index 0000000..5aaf6f4 --- /dev/null +++ b/docs/evidence/admin-pages-2026-09-22/native-menu-checks.txt @@ -0,0 +1,47 @@ +21:00:08.675 SCRIPT : ERR SMOKE PASS: admin integration native Esc menu entry opens mission administration +21:00:09.123 SCRIPT : ERR SMOKE PASS: admin integration real owner RPC opens menu and returns current settings/capabilities +21:00:09.125 SCRIPT : ERR MOD MENU: page=3 rows=4 saved=4 active=4 +21:00:09.125 SCRIPT : ERR MOD ROW: id=rhs state=Current round: Enabled | Saved preference: Enabled +21:00:09.125 SCRIPT : ERR MOD BOUNDS: id=rhs width=192.917 height=27.5 +21:00:09.126 SCRIPT : ERR MOD ROW: id=rhs_ion state=Current round: Enabled | Saved preference: Enabled +21:00:09.126 SCRIPT : ERR MOD BOUNDS: id=rhs_ion width=192.917 height=27.5 +21:00:09.126 SCRIPT : ERR MOD ROW: id=rhs_afrf state=Current round: Enabled | Saved preference: Enabled +21:00:09.126 SCRIPT : ERR MOD BOUNDS: id=rhs_afrf width=192.917 height=27.5 +21:00:09.126 SCRIPT : ERR MOD ROW: id=rhs_usmc state=Current round: Enabled | Saved preference: Enabled +21:00:09.126 SCRIPT : ERR MOD BOUNDS: id=rhs_usmc width=192.917 height=27.5 +21:00:09.127 SCRIPT : ERR MOD CAPTURE READY +21:00:09.127 SCRIPT : ERR ADMIN CAPTURE PAGE: 0 +21:00:12.188 SCRIPT : ERR ADMIN CAPTURE PAGE: 1 +21:00:15.267 SCRIPT : ERR ADMIN CAPTURE PAGE: 2 +21:00:18.376 SCRIPT : ERR ADMIN CAPTURE PAGE: 3 +21:00:21.450 SCRIPT : ERR ADMIN CAPTURE PAGE: 4 +21:00:24.494 SCRIPT : ERR ADMIN CAPTURE PAGE: 5 +21:00:27.601 SCRIPT : ERR ADMIN CAPTURE PAGE: 6 +21:00:30.682 SCRIPT : ERR ADMIN CAPTURE PAGE: 7 +21:00:33.765 SCRIPT : ERR SMOKE PASS: admin integration all eight pages reached through shared top navigation with one visible page +21:00:36.875 SCRIPT : ERR SMOKE PASS: admin integration all Random buttons and Random day select editable drafts +21:00:39.947 SCRIPT : ERR SMOKE PASS: admin integration background polling preserves editable draft +21:00:41.490 SCRIPT : ERR SMOKE PASS: admin integration native Apply control routes and saves only requested setting +21:00:44.020 SCRIPT : ERR SMOKE PASS: admin integration test setting restored without resetting menu drafts +21:00:46.080 SCRIPT : ERR MOD MENU: page=3 rows=4 saved=4 active=4 +21:00:46.080 SCRIPT : ERR MOD ROW: id=rhs state=Current round: Enabled | Saved preference: Disabled +21:00:46.081 SCRIPT : ERR MOD BOUNDS: id=rhs width=192.917 height=27.5 +21:00:46.081 SCRIPT : ERR MOD ROW: id=rhs_ion state=Current round: Enabled | Saved preference: Enabled +21:00:46.081 SCRIPT : ERR MOD BOUNDS: id=rhs_ion width=192.917 height=27.5 +21:00:46.081 SCRIPT : ERR MOD ROW: id=rhs_afrf state=Current round: Enabled | Saved preference: Enabled +21:00:46.081 SCRIPT : ERR MOD BOUNDS: id=rhs_afrf width=192.917 height=27.5 +21:00:46.081 SCRIPT : ERR MOD ROW: id=rhs_usmc state=Current round: Enabled | Saved preference: Enabled +21:00:46.081 SCRIPT : ERR MOD BOUNDS: id=rhs_usmc width=192.917 height=27.5 +21:00:46.081 SCRIPT : ERR SMOKE PASS: admin integration native mod toggle persists through authenticated owner RPC without changing active content +21:00:48.131 SCRIPT : ERR SMOKE PASS: admin integration native mod toggle restores saved preference +21:00:48.132 SCRIPT : ERR SMOKE PASS: admin integration three faction selectors and Random all create distinct-role drafts +21:00:52.710 SCRIPT : ERR SMOKE PASS: admin integration faction Apply persists all three through authenticated owner RPC without changing active round +21:00:54.249 SCRIPT : ERR SMOKE PASS: admin integration saved faction choices restored +21:00:57.348 SCRIPT : ERR ADMIN JOURNAL TEXT: lines=7 chars=528 bounds=153.833,79.5833,188.333,31.5938 +21:00:57.348 SCRIPT : ERR ADMIN JOURNAL VIEWPORT: bounds=152.167,78.75,195,66.6667 +21:00:57.348 SCRIPT : ERR ADMIN JOURNAL FOLLOW: slider=0,1 overflow=-35.0729 +21:00:57.349 SCRIPT : ERR SMOKE PASS: admin integration HQ capability and journal page remain within current mission services +21:00:58.866 SCRIPT : ERR SMOKE PASS: admin integration dialog closes and authenticated god command affects current body +21:01:00.415 SCRIPT : ERR SMOKE PASS: admin integration god off restores exact prior damage state +21:01:02.474 SCRIPT : ERR SMOKE PASS: admin integration repeated open works and denied snapshot closes dialog +21:01:20.888 SCRIPT : ERR SMOKE COMPLETE: native prisoner-kit; reset requested by fixture diff --git a/docs/evidence/admin-pages-2026-09-22/page-0.png b/docs/evidence/admin-pages-2026-09-22/page-0.png new file mode 100644 index 0000000000000000000000000000000000000000..da045b83919e0f3e663229102a9fe302abdb6c28 GIT binary patch literal 150185 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

+-(g&7T_&-?G#*CRJW9 zuUO$9?tWMOxX38dIx;{|RgmMq@^EV{j}F~14d%b+6KLicS{E!B_9`&&=L6s$nn@1@ z-@lcw5t&wbt6v$##ihwZ2Bfrg-jq1ExRgDeSZ5EyF=$Qbl-J&o>RHJQs^0%?87&dh zsQN-zrWQGna%7=#(aOyu<-0pa6$@6*{1t{VO`nNknX~+LKKsH%36oYfg}6yNHSxU9hEPZ;b#}A_KU8;2nH?eLD42X#l;8A58Y1-H||fzwZSM25EwaDUC%y2-a%e zPHD)n!s!xdxz3xV*RGA%dfJ?wq1!)Oz^1H~LGXN24P5(z=i;D?R%2-?4n_lXEr(Ol z2DUFh`oERn?x~d2sXM)5u}P*7`A8H&qP&TMWU5RyqlwD_@N!@7ix^{rx>xQj3o)@B z8$moa$c0~sW}7h%H8SC4X!W*85m{%$AVkXUMad00#{D8|_K*(1@mE8V!&yBDEDnoQ{MYT_!0j&C=psCZ#35^WxY6(JLq+?Xg91 zoY5z99VT$Y0wi>Dtsota)}kl9|Jewh88ask#`4ErPKvmwyXvYZeZ!Jv(^)*dPKHBd{>QmrTTD{Gsn0; zMoD=InR^U2(UFK;^v7`+7@LQ1<@5%AjK|oFSK4SlSRF+@ z+wP)lYfbO8c0NL3{-lotj=ZanK8t=mH-DjI66SdN`E;56tvc2Urd6Ez_Jl?=y9*F%!7yFJx3TQ7PslUCJWQrzr5i$^B#D&Jc z%QTr7q|<}yilR5!i-<2GsAankw0Al_hH^wXBMGe^kS}&Kpw3k86$-7Y(m10Ze;x1O|B zAyw6fwJpJ2<|zRGmGapBmzhICZxK(^4mX43z}ml23{#T-CuQ|ZE{lC$I^L>H^82Xl zZsvl0Rd-cPH(xERq7Ji1{oV6fPhwohDV@`&d(7`RrH#6Qblir5o0Z)cFckSR2wBgt4&ilfMtmnVLF zLHZqCrrD&CY|(IsZ(~lj?Dd9NeX){^hNVIGlYA7)B`VMxWWD}S;@Iqf4aki=Fys|%cav#np^x&Z|GCl(Z;nxK3B-Ue<~NmL5$5fZlOcEJ^XLxyAd)QmNE&4!I@7{2j=&k#Scb1t5^)f+3I2EOZ%9vYme z^={d3{r8q|y*BhcZ?3|9^|%EW{?dn}kWKLL%gVtv4mnolq9H|hvTj>@ zXU#-C$|x<1Io5%KXRhY!i>%Gnmy9(gw@d^?N+N!C10uk+4A5d>P*KW2&xW$Bp-brX z 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 literal 0 HcmV?d00001 diff --git a/docs/evidence/admin-pages-2026-09-22/page-1.png b/docs/evidence/admin-pages-2026-09-22/page-1.png new file mode 100644 index 0000000000000000000000000000000000000000..69a281eb3e6399db72514013ecdd359570a83e28 GIT binary patch literal 151142 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ⅇ`764$13_Q7w07=q`e7bh;BEp3ge!;o^v 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 literal 0 HcmV?d00001 diff --git a/docs/evidence/admin-pages-2026-09-22/page-2.png b/docs/evidence/admin-pages-2026-09-22/page-2.png new file mode 100644 index 0000000000000000000000000000000000000000..776bddf36369c412736885b64052dc8b5f60afc3 GIT binary patch literal 156185 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 bRH~r{b@U$H1L)wrJ>bY8&w~{%r>^}4X+bb^ literal 0 HcmV?d00001 diff --git a/docs/evidence/admin-pages-2026-09-22/page-3.png b/docs/evidence/admin-pages-2026-09-22/page-3.png new file mode 100644 index 0000000000000000000000000000000000000000..7865f663ce4d1732e4efc75067ab72d1c50c8a11 GIT binary patch literal 151297 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�W2}$oH2@*<(I~foCy2Z1V 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

}xZMIr0GFzukvPWm2fS?-!0FcFA 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ℑz<73BlnSB+B56<#BYlzmS`$F2wef) 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Ώ@nP+P<(V-5NMoY-|P z28Q*Eh;}OoyGW@WH7$5TP&)?v=7`tdn7a7ZjPk#PP8rO)9%JKIsdzDfJN%|YC+_UXXo@$qKF*XDM*vN?ayg0aN zXW4McE(@H(#@Q*y&3V2bIh5EKYtbw2ZKN$@SZ4kS&xV+lrZ;S2cApZSwBY{85afTz z15iO#QMs_!b#<4L<-kdPyrDeKlSRcz7i} zMFV%C?viS)THz_7ZL$}SZ`o$k)(}__sS`u!_Y$(Xg#1?fo5CLB_R}WVn{j2JiacCA z`g}I!bC#!=TZleBsA!U#Qil>ffn(mZv$6>8Djpby4xIXpB_>%(GcdrZK%pZ z$c%e`Sq4q9J%>ZG)B2wwQO`iC?j8h*R1ukd+7mL-AhdYDDE{X}Qllz?|gTGILzi!fe$T`rDsD(!Tj_kD!^NM+?SD3;8 zV?#`B^#i@OiY`|KiWn89G&9eX1pl(HXc2NTsmTIA?ex9LQTsxhncgDR}azwX6l zc^WQ*Tr1%qHF-Xo5B7~GkJ>!ExPX2`$^AIHb(|AM0FpbCcrrmbA?zs{IE`3FC}-o-Hu;VqVy1)K)n_`4PGON{S;z z3~6aJ#gn4+(86b*%q4GA0DN zjTb{ou9St44x-el`BG_ykQpj9#?=%_Qs%cyPpi6DGfIA^MhO`Axtpk(H%fmqUQ^`}vPqwi$+y`Q^V7OOn-WU>{rlCCL9gnetjp@bB$h+tQbr)Qju z&nO}$N}W>SX}KZ6?`$ZRAtw#M32>1fBan0C+1n*4XWwOs#%FBRm&3>H(ISC~1w4;D zi3PU)5^fM__soK`@!c8sK67=^5gaquI!q?zVy_CiRWB_$=$gh~-&y?UpPK+B6?iI# zBH$lOxj3wNd!;0mgL-Z8cGhb>;u0O!Dp^Bsbbdy&C*j%3S|%hgCX4 z)BmSIKcp!syy6iO*Qu!-z^~UcHel!FSS&e3l`dQOt|2LFyLS1eUw|71Ac-Chj-Lkf z+)jvw;{eWhTD#auApXUCR|#tuBd8d28OFQ~ zF&;5lLY6=ZuMf2a2R;LXn!*DZsdnCVmE=7BOSVtw9f?}x5pQ&8;Na~qlg?=#BR+cn z%7X(Io3bFV`Vk*{3VrN{172VuCShz(asEujD%G{)Y$lqMr%1d(<(=AqTDr%%{g{3z^3)4!8n}>B*qNaU*r`acqQ#pu19f{?neH2P;P2Re z{7^((-W8h+t7Xe5>I840FB!%FvPNj26e>I_kVN`f3k?2&F z18Nm(10{vq5G=e_#v`_!i(v4pdeTU-HYR=d8BmssiY1tym((oh3cUs`XrbU>J}4>S z>19qtMlwND_wvv7Hn?~jDP?ZGKw{jLKga9a=_q@#` zQis;XW8hIi$v&$Q5M*0$-s{qj-UZoJ%4^Q!#^n*4IX8npM5qVdj}1pW>RNdph)szJE~nhFF(iP_KTSSZ!WYM7lYgUnYq?!Oo0K`UHG!C+he) zr;S|1?^W8|MNAoDNJM3QejLLG3!A*@alxWB3E$H#dqG!jbRpAbokncTQ%}P!*^!qB%|NNVx{7XtT>2T*+MCsA3i}U-P^LZ=5_ED>8K0e(u3-ir8{?IQ+TbH!{r+Y8z-2UguOY8sQR5fYP;J!9v6?8et5^qD2P^|HDGV8l(mE5?#Xu+Hj|-Hu{g-5~H1O+u2XobyYa(n6qEp$a4T_6~b5o%Z$r_ zC>P6^ETxn2$hJYr6PIGld*;bFm0tC}gBQN`6?ENNJ9lUWh35z0YVvT71iKKG#IMJt zjsd9@VI2(N^TZbq4&+roHfwelGhN|U(Df8PRr0XX7(AP;eX(U_jU)n*v{ zJ%W~noGPz8hwv8QVGvH%=?ucB-lF3ttGTCl*#J2*_Rok>-(omYL1y;Pm@&YzM+>&HZK zmQDj!n5q)E_{?;BKFYFfR7551-=FFyzle?iU~y}^qnjrfnh_gJi$K)^nJh^ZC_T4RoVNrlS0 z_Yc1xIuP7TV7@fZ<(m$_!&0X1J{)J(5PEcV1dGQ#RaT3=m{Rj{`9%9+z?XSdF)Ym1 zUkdmiZQtR$B3Z4Y&!oe+qd^fKj!#fF9f(Gx|0e50Je+epSXRHe+<4TRcewkT52Rxh z56#nz{6jr0^1srMIS^=arEdiE`qb68h4%6$jm7#D9Pj9cP$!pLgjk+Kk6@@lk2#H!+INFhP{11?qAM}lWa2XlBbJww{ z$pHYs;K{)fmz9mwsKbB4ATTRK^kHCAyr0$g)rVJBYX%oWU8Zg_{ch9PfWj28OBIz~ zIvjpw*v8jP{G*#;JR+8L1UdaTm?FvJ2Qc|{#I(+U!oAu>cN(_#tWLL%oYsN8KE)X~ zM5RB^fKuKC4XDA*>nJd%6_5nQPyjG>uym1ts?dNCFV-7MVQWZjkUotVZ%`{zLtuO1 zxmK0|w3QW%SStz!5|qx4Po6h58&p&SfE+X9owcP;H4l86s?G55v`@1dtYNo05`w!X z_bymW?|8Kn3-!S61~JmWB*80lj92aK^`D6T<9tocrqApK+4g%GN$IAK#9f*WV~$;x zyoymE;0n$aV;N9HQ!|Vi932Ag5Z}H#P##P!iVl0%$YrA-5i6j`1p-hnVhTkCz&NBd z7=wvmukp|aS{062WXz+~mg+ORE&OytIX8aCyz#hKiF^`CxtGl+imZ=|Lt8>J;(|9s zEBS<%dC+&?_&Mo$H+?7}*1@NNukf!>4CFs6k#;Q$HgD#le^fvKt39f8_bTA5TCvjl z3oWl;C~aM@>kOe->YbNQvD@D#SV zz!T*6piY$4A`8p>M7)ZSFTji>!d0nGAFpzvV&tk`J70Mb7(MYK=mcQn(Eo;B5N4^Q z!@1f{%r=OxEP-EXQ#N!pY}~v#0K&n}^5V9~`xJ?4`0a9@Yc2sN5r5^5&HAaV0%jPH z-xX^B(UzqW*Vk7@TxHZYCKfAsUPqx&r)XDRP3!2TJ_hPYK~;271r|J*@|Hw<2ELbR z@myh-6q-3Ny|+Eab|6lR~}4|j(EGkjoe zqica&v$k~cNT$MIXQ#5HncC&~SFf|y@8&uBDnDL}&;%cnkG7h3Ctn`Xj}DL49%w(U*BuqCW}b#|DWchs8X(G=!YPPAr_?^++JV2ol3?^ZQ__O7b7A{)x--fJgX#JZjzI37$540|5^ z5s8lam<3Kg8^`IDi$)(#+)4EbDAUL0hYI*Ub-+})Y$tt{MzG3y4_ZQ(u`TAEq@{Tei+_9P;MH3`t^!MI-}XuPHWkzj$i$VFSU8{($L zT2wyte70R#8oUMm79r}~f7aRHvI9vZQ6F$)pgK&-h~cTJV{{5j*6kz=`bHwF& zXzd_^Tt2EW|1Rqu!3K2#Tcc6fFY#15oy~%L6^AlwYu|+=WvGgqAhAuK%Nf@i{=O7( z_(2LXH<^5~kqYwrJ??ZXWmBe&XV#+zhj?Fd5;Ux`UD)E?Uq^abOtTW92|SY(2)_g6kos4T2lkT2ce>Tya{J2nm%C^fRa9aI+%W=fdHgtvkvA z?cNZoDr~EKg@@~*%3TSaQ(gR%lYh6ODM*k{8)?(|?v%kwb!lU8mQj6U2o{eEGn(`7 z!;Ho|$~+fg@LN#%_%JWNW@9pLl!a)@K8IPEwLdDj{KYb(*was9JHzNpye13&gm(ki z?rG#RgIQYBSJGKbX=GVWS33u8taS5`K|7e6<3FpC{n+DTU6HTK!eJm5UZu4&*XIGks^$0cMFwf)7sa9fuI`Jqsp&4? z-HR)t@$jT$d?*#pDN?XueEjvF?}kT)N#)kWs&44elX0>EMK?(E^NRT0^bTFGGJI0u zFC0RUqd>}h@W=6QDtQ=7uq7Xz;xZJ9?20;>UNt!fwIm*A>h`DkunLqjN0a(jpI^#9cMMkcV2 zrTm~QLnE`5Z}l9mEC*+P&%#(&V`!z12*woviKTIl>Efxbf!7LClD|^CYvr#72EAuL z?0UTmZVRKK_A8El8w0pEU2H8ZC%NOqSbKY020qV`x`86?VOj78ZRHg?3X6%BoOKTc6Z?v`1 z_ZO7t&}BG1@nRm-7Ife%f0;1Kr?OaDF{A62hVh?%lt)EJCvwK~eMGU4WxOZlSvJZ> z(s8WLBsVK>US_5Cm+6X`bh#Z?bn2#;*DENm0$d@1Xa(U*OG&9TFhY7J_5M7b@W`$v zK$8vN6VxqBgwB&^oyGOV{@xS8K6oA<0h`)efq>=N*{0z1PxuNzjkQ4T*+q`+& z#?7UD7%Xz-ucKI5H=C+qZT;>-gW?(It>BJ@l&=Vc zxO|X{f@BRp+$MtCJZ^(9@&sNKOQ2vd+|E-@Qw*#GCBEnwoCD13Dtbdagq?u6VWo%c z=&)=gCK~cC6t8?N7vivE8 zs<`r<4x+O8y8u7?>)g0?ydwoSS{bL|Q!Ergu^!BzCyV;`-)5^QU8vrof)3cpd>ZYC z1DIlNP$Nk#InMdnPk04M?0XV3cBXcbeili59Fg(s?m&XuFP~*b6L-~;pB%xDDfDFF z*vU5uiMROxl|g}TW672$1fM-{(UXuzy9j)CwRTnJS@i^o=l8ywxAfGq-~AF*r#;390=@Uhh3jNcO*5oEs;__L!^g=&zdfiKm9)}V{5m?Hr%~1i z2E3M}PGU;E)N|5i9g`MD%dgw$)usI-EpI-o1jFb3ldZOJ>@_wi7+n<;*z%nLXlpQ`0G6Nh)%WfhB*oE$7P@2h-b z9i*2e-Ij5|C}pTo#7vFpS##=ZPFs5^QzhS8J!d%dQqLtrzglI;y}_whA4km$pk@KV z?@wh&8?-rG&ft#gM4oU@!*rHq!zwK>aSV>BX+#0YZ= zsfIPoA&1RjQI2z1M4AefvpI&G59Mse$YG8N8ObTfDMbgN2t_KL-oJf*-#=il>)Lfa zpZD{=@5d?pkf(+^>!V0dkcKK_)4}0(1kaD8wRgsokmwwT(Pt-$GK`@)#!yeh;}_S! z!AqUS;?i-gw+%|h@R@sNN0lI6oZ?tU8oZP_WmVzL2l(CQxA*}FcD@FC36Zmw2_E)K zBD8pn*;C$+?!vFXm_|dObAN*#myu73-r2PMr*+HpN!<0mH@1qISLL^XFMy}R9{*Kt zp^r7zA4JS*4ZI{l{o_v|LuLy8?mhG#R|Bo9VjAZVMd5uBEvm<^6Y7aQ@A(@qP#6Q8 zOt@f2%lyN8#;eV%#7OQ2GG7S#*R#8gz)klHB0%(P0OiNu+iFjIH9{Lmb95-GX6f&{ zwpY*1YPHVaFuLx@>B7>H)DYEY$7`4lfH=G)%As{9s^yC?;hf`2m*T!3XmyPF%bea z68Fg@tm4;^v#>MhivO1G{C@N3uJT!Q-p=x4QJ=Fet8oc^-Z30Lil5_7^uHTl|7FX) zdLi>wIfvmUZ z&|(osy0b3K4zLU!35%rh`z!~IE&bhPTOArV26q&HfIcyn35@Kx{^Sg|5I-S_npM1h zG(Km{tlj{yUEeRamjw9#doOoursvY@?0Y48)uSZ9h#lDWDo!;DYUja*LiV3G}*gySMjr zLq~_-P28f5SgOTYCR+j;w)^VUY^z_s>zDe&*P*r;%$8T*t&yADDbWu4gRtg0x$Vi_ zco6NnZ(@$`@?|Xq@VbFP3Hp1jkw3G=?X$Qzj|bz|1}WJEWIFMCKttr1AL%|etn2#* zyS61@VgfXm13&=D{0i2N3KbXY1LVATIUyLDuiXtw^EN!4Bem1D*K6|+hHS`; z9&w$EZrhH9Ch7fI0N5eIqZqaF_20iwt;ba@oy{;c^1yXP?%8D`B$-PassKTO=P5x% z0ZVwtg72xw&L4qK2L~pYn=Nwzqx>NkyXi$QbtNPb2t6~Fl3R^e4O>^>!TDjy!_L1^ zckuZw>W36)MD(q{zw)S<#4ph{TWe98$yT<0YbE!(&h;A~=0+fNj#p_*n2x(9E=O>4 zLG5Pya$~rIlc6z^Gx)kJJ&@Y_syoCWxwIg7HW+#nI|*)y1M3fP}0_%O!ZI4 zXYm=e;=tv#gVys89^~(x%#Zq?mT$0>0Xk;2nO^uI=$o3(*~k{k-QphK4$CA*GuBpn zn#Su3`L%p9TGoz*{<6>Hfw!pl1DrVeJi52MinU=a==$a&7B*&qyjid+`ua*O2bNp3 z=P!uQAfHtyk=zI6K1U^8+PU%ljLZGPr!yxM*fq5Tkb=OfQecfVMur~$V!jaVfI6gn z>cj~IkxW&3!Zm-L8Djv2QtJ^YS7%=JV}<6IBC}fxYXMVk@OU!FU(4Y6dXYGJA;ftH zeXUuux3VzTZTFGFX!MmGn8>>fe$w*dMkAMV+cuz-MlIl2Jc!nMhAcposajf}-II8d zm3Se9%A_vJU8QVogrH73mVyCVl$uU}Qmpv**J zuQ)7U66F&#?v+-f_EUh*8bRJl8;SRf{_u2#zD+p?l@=ZfwLy8}3}2Ijf^Fj|6pM$i zs)+L^?w@_NLjuK*{rxs}`1;x3tAE2aif#1o{?*^f@~>B~$8SGu2nmbq zeDva?`#8sq325sU%6h=Tq?s_!JiqhT$G?SGqUV^U3zXA8Rw_Ji6}As7c3fA zv#<3O7F-T$ZoJj=ER90omK&Gt?7cM1{d7?_CewndR1H0@YrAQ(WYbk3t&pvSZfm!= zUofN&yx*R>f9dd#Or`T0Uk_g*h}OP!IwdbW+*gPIQso5{sI0|bf0vf#_rLGgM{+Fq zq)pz)K+yb9Sy2B=dlzmH_jQqZM)3OFe8CiGgLq||xCsK>DX}eYuADsbcVm^Kyx4Ql z{QinsP&2O1TB)(z_NU7Kn0Jz6KHglZus+`5~u zc_n)!{FGJpN*$B5=N9Xup{)ct+87MEQ*S=_hW6ht@+a~COy=*nMgD$ZTX+PZzufuz z?K)7#{JuNCNpUwM1=+7WhsL}jZP9EJFzsvuBqZlZ#+b;| zDNY3Rx#&oMR{@kMa@QwSNhUhZP%9S(qGBup*%3RvP%xxE$xzH5Sj)aw^(Rloi-fV@ zw#+V4Y^j1Nei$nMU|j-O5(Y~hNr@c!@9fvt^D0|32BNJb@9$8a#hFN_V9~fW5k#7` zIu9_Yx00M`TT8b!v5nszpmM(z*(9z{yuSSE#JI#jAtdW`33MV(YDo&6eB4w>S^*DahlhNI%|76|Rn$|?V+`-XHMas!6ckCTM8e(wbNwzo&D#oECVBUVb zAui4>)O@*6nc3__E7B@97sE5B^|%rI=-3>W0-SAc{mr?Ic<&dIR4rfW<|0zoy^={v zkpp8%5%4~F7;4yri*LGO+p{IkZ%&Gi=dZ1v54JYYXl6AR&fY$IxA|-Eh3&hWIpu1v zmoD9k!(w@h@5=V)$w>qyR}2) z$J0q}?lMxcaKHT9XZs@1gvt|1KpHyC{K&08@@SbX6G01u=f!w!XcAw1*C_-zWAa+( z@3*J<(1prdR=7|26(k5K$}yN#qswDQNf>tATVlzqs1~nB&++GJ-ma zPsf7YWTE3W^T}VX_Bii_cw0VQIk@IFxt_cR7% zkF68$+tfMkXO@$-t3dSTj7XA>&gsbRa~LQ|P#HYcx61W?=gs2#EQ7BPF3aAnJ-)!X zUkBi$BM)lmruO5|e8s=#UHm#PH`=GstI~F1CyxQ*Z%3 zs56m=iia#9Lfp#V_;+J2&Qe7my*O`a!9384bX4@@))h4!=ddgg5lU z{i|Yn3?{GqRb-)541cocePtyMsgJ+FA$&Y=!1(?zxaZk}>1zIx=c!0iRzQ*bpNRoW zNoZlMDgL=06%OI_1)6JE4~BxyPPk)G>E7#}q67I7#h*Xth2Z^j5Cw=A=3AOmd!53} zC;TzLJfXobQ{hKfMM&YI=4H_#TB+UY$-V{K3LGm9HEYLh_X&`qOc{GP4FlV@oXLdI zZwh_Kazl7oUo2NTYHnXq{Aj84v{PgRY7b$=T^|a;%pHAYV~GH!=0iL%)|g?I(r1vP z!pWULw3j|@IvTLHu!g=>P=B{p>%9~_+wx7x06`;62o%!ly3BS`T`%h!`o6q8!x8dl z9xx1hUQTSeE~%E~45&Wc(tq_Na3=QIL`ar6ytBvR>zAYejkVc> zs$SHgJ;^7@~crWT@Gw$6FOkM8pp>Wln+(tY*pmtPsZe~HKntkx^d&gS&pGAo~|NXfA<97q~ztubYm--_2%>Vm-H@tZF#z(o$QyVuL z?|ixY@9om7!N0}VoBIB|d?53D;&qdz{`IFu=Rf_r>UiO-O#Vuj=usV=t?Rz793AF$ zNcac$Ro0#opkmr|Wm5FSyR0Wx@j$Wb_T3<06Xls=&@jQtI-7;U&+wne=$3p=EH<}& zbOJBd_o&{i%U4n{ko-k$*!ns~%hT2^UO()a>B^p8{=r7XdF!+P?LO9@Kv;NeK(ib< zgfP+BRm-1VXT{$gxaBW$BoPzVA3-O7_+geO_jDzE=u8Pqkb#YAejy}qYaCCe%+?rr zVK6>LVqv3}*uh776b@VNE{i0&-TPzqX3RsUq-ydpQ#~sLbws^q>vmg7!m}kS(p~C9 z-~B9y3D#~X{NJwTMR}AM*H=6aXF0JQyc6bS>cQLUZv$$$e(ni-{&c)Ra@goB z9#YBHPuq+ahz6!lTwRMsNBbIb$s@Q#IxRSK^R>b|e}?`=8Ta126&W}yf4|3dlh-5v zLO~5E=-tHW7t}e>&p(C=)7|=>8NmE@)XRD3%@VieWu=(o=bM&G^lR4Mm2aYX2QO+K z+g?iUY`UVMxt8g--L6hx=6-OF6uf(~gD-WdKnT=Zx^~rtd)Y|K*5P#2vUSrNnfY@Q zzrU=Q!BrzHJ3km(903hrp#3cM@%Wx4V{8IrA9bEO0%QP+w?azBq013+I!7@qOmSCy zWYDbwtG83U5Tg-eo5JFNFj11zUdihBe>w3JW}OYpcU*h&HL7QO?_b%;Ydk8lBm@*t z1cedCVHnVaD;+>857cWwr5J{t@V`xK~Jy`+(<1TDmYG1q5< zYiEfUc9u-qg9F(Kx-v>%x5}Ye8-vCH&;I<0Kpx|R=-7na4(mC3ezW@<^r?Z0u&9q# zf40GT8YZ}3y+jaIY$&dM+$RNalz?Jf^6nKXKLbSmX21)zq8F4cP)d>v)r`~-8E#-U zc=5Cl;D}iG_2=bk>Ow91=(QF{OH7%xJEfV> zvp|7!;;FZH^IWdhpQyJ}QRfE5%3DOgr6*+5Sh}0=umx`$NV<3+a`b4U|GpA`%wGkz;YDH~( zHOR>L=qRJ5g+94c-}IPzSTp!h=U2ooD>-cE1f8D9GA*ip+$bt{x=Jr^aQev%4LR2G zjrt<^xTB-&91f+$fpz`kXz(&Rz25nEzp)Gf_eyhBZ^cz^qbANy^Wr^l!&0L|f2Ub?2S zURd}3`o8FoxaxE%wcS~J#^$Xy5(!Mvbm_)nOX0uXetkLeh41+T@+hRp`%6q781=g* zs|Fx4jN^%_F(eE1!1TKLI-Q$=CG(g}gB7Vlfm}m_g~wk=O^wCAf68Vji;gu(p({rn zUIqDSG!yGn^CK}i)v8F1O_$%9zU-GQ=~SZL>9<$&J1$H#3=&)eDj7P=CPS~HDym1r zxdbY`u-br={G?$Modwj}56E=6Mk+?6m>gl`NT-eJqAZJkF4kIVpFYhasFFQ9Vof}m zm4q~hd0%e%gUKNdjx{Oq!7))-xU(+bNqq^&)o^^GN9Sj&F;CiVU2-I8Y0F4Ih-4MgNjp~ zmCK0YFAWzdyXt(ASYc6y&SmN^YUx1r_Il0 zg1+IpoljQ7UPMWJTRu4;8R%>6c&N(EgY;dYAx9_1OT=cs&tVu2wz~`}Xqs@h!Rg(5 zX_r?nnh1gv+&C6PkB+YJ6E`a~5cYs?tnnZm6s{`W<+n-a)92!YadEhMLqZldYU3#u zih)5fzGX!uATCb-|!jKbFLsREv3m{Mk;=mWfhK)1&4Fe#6mN3q5Gn!wNIr1h8)gTaN-%HqzlLYFz5fZt*o;%8(pt-4TE`}_f|eD%Nfjz}s+pccDGbz> z?W=`Qt%ePw_C?n_c4Wp0uQbfG&X9UD&7OQnX48mGx%@TZ3Z0Qy;A9e-h3P`s)*Unxv+$fQue&k$mk z*1$Q$uJ!5tVLH0VKch5<6rika_Y5(=pGtL6KmwJ`jYzzzPP_Ky^~p%Wfq@JRriw%; z&n-%mg|x-PbV}M(pZC{jnJMa@?^AAiC;%#cNpgDpPS^46S6qvPL~JV?ZYJZU#7GAx zjIgsQG-GHMST}|G(p6}VW3QrKiA7)2Xzum&kY9W8=Z{x36U>X|AxIQArw9(X$|{m8 z*J^aUTs8M3F@dji6dY zP7K51D%7O|ayoy0-*!ivSoY(;m&OcdBsvq;+8zYGOkQuoS z7z~a;nPB1g(wX4`&0xl6AUAr^g@>Q!RYr0M@Zg^sy<81VhDNL20CXpxj2d`5&BxJ zuUwznOgB|ZFHmmBu5O|~++*eXmeyogtlo5heK-vXb^lFD|5~SH)jDT1yCWP^CX$6v z<4iolscODOSsb3@1};9K+i$nA^Sc!mTG)a&S7t?km%fp&L65Pc|#ldpg$d z(S{Qbf;yy5x&&!8W1AYbweAbF6u#p66^9&iZIr_jb@VaW5=`$t3v>_)`bO8EL&354>R8^kaS+S~b^CRppDquWnm0=QM03 zT^VtSW5*mV!EAB*5yO}9EkANy^Si(Z=QL;86!{93Hw31jD0vcEC?EzbpOFQtsD*7f zY>vXsJc_EtOKl?JW;}8`vehX>#khdPTdE8wqg4b*^_rVBIij<)>zpSr4LVn?E3U>f zXfi#@2y6cm#D|L5eQQQ#wRO5p*dE7J2M&iE+z*Gp^yw1LBGu>ukm;+>`Q%D;C{*gG z{~RsXK_Od|+nUE-T=&Q<9{bUvp~>dXa>>t$KSw5F6KqC{>`~1Qx=R%nCUvhPt6|5I zJ%>s6xfzN)6M}Y%L(wT|(-?r8C4)Fmapb+Rw+n$ow3<0)_YM$#EwKt|!al8m5%f5- zg7XPVzifr2h{bECp^A1@YF1Gn@c5nvHcd6dQQUm3_4T5P7y1|TZy=VcyB;2>{6j0RPvo#`o3B}c)O3A zSI$B)R+%J%!5#^MWGRBQJkls%0=#PdY9$XxV9E~+Q>cpK74`rWt>{u&1eK7SE}VH9 zU(l5t3uB9w1sT)Su7N5-zRY>`{&YLJo$Ju1cDyFAA ziF}|mIV}$^bD~VyTtt)GhKJv7Mla?0>i)eb>*X^gFht+g55?dY9;_- z0BsYV97R23H8l5GH{Nc6l9tm^!XEw2KOyrX4A!nd z)yH67_k9PaN07p5XO9aiEMvj`&17nqN-tIyt5%&dLuL>hbp$i3ZOP2nM;POu+Qnp= z#!tWg^YNvSY(r53zDQs^w`Ec*Oh?m1$8i|9r5*YD77 zkghk%@Js2H6bNfgDWCTjB38D}F?DM7j4DCVF~tc-3QW{ST46aH!|}pAJpxJ^UaS(0 z_DS1UFsko8E>}l0MlIYILdwv9r>ya8PYA7d;NnqcF>DB&%gS{~wt}mO zNikxcC82Q(gk&{C%dKp6o0ki|?h8286(MIIX7I7e_EYh}ol#vHY85n~#n_pq8;DPl z7vc3KEKrq0c?(i2bp2sr~c0U;q+Ohqi|S@8bik-vNy^-i_3fvZ23>ic%*S9O{F=qg=(9nGf} z{*LDw+J-)5fXm=scR0^fJ%P$tyqh+U4GY9-oJ}LD&C7m2?A@eA#g!+V8O&i1yQC6h zTFM%nXH$DqXJz?lq7xshvl5CVyo9m}dH+5hmPFKqYtz{+QNU zR9HZ8B}hY=`b9O1DKCWto#1wr6em@AFn%=B;$E7n7c1DDt6*rANLE550MKp2MapFF zuf=M(BFdjzj#{7!*3ldMX{sZBs1@a}J8pZ-Wn9kW#Rs3848m%+g*EJePslG6q< zLd;Dd_hG(rg)D-)2 zRP@Z><*BFr<7i#!p##MXF!Ua(=8c>~)x|!%pwtMbtXqmT-1@?l`#$F7^5Le~qo&>~ ziKe#C+q|iQp>>zU?C)1k*f}E-q6Ou#fy@goc<09NqOv7{qXR9*TmXYYa2mht^w{)} z!g9q<&wm47bJd)i4Ac~uFD$lJVz~I0yNMDjV^*p8xemh~*&hcU?%q$SnBg@)H_q!{yI%z<5aP4+UxOoWQ(3eNNuRh4hrJhCrY?-Kihvxp#UX zV8XXg1AAr;SEp`O{0=)@0O3OKxnrx7gK8*>ykKQ7Z|f~ZmGK#F1Lfq#UJ^joRq-J) zm?+-dT?zx@EP3~`q`7AbO6#Qf@u%Gl9=;5Z*+0Xw2uB|~njJYPJ(TGT8Pm0DuvuF( zI_IiZ?fosx(TIEJmWtU-i2}_-i&lu-bgT6>3R(zwWjv@$!PuNv3wpI!#?+YDYf+Ek zs<=7{Ul>+)AB9ULBkqYpH|P(s=PFnc=Q)WS4^c+LoNU(7>up*xxk%Q>)6B3fuJjZt z?SkdfsFtakl|=EUwLeNNPL6k2v<>=qLH8mTjI8q-mQ(N_se0=ob%!~F8cMME${l|v zlD`6G33f~^x}u@r8NAf5F&DFQ>zz2l2^YX%>Q8)pL5d1eOJ@i%ckj2fq>Ps+Svo4} z&Fj(R$66O1-NgY`r}oj%)scb~=6;%;TJ_vJt`pu`vCp*YnUABYfrN3vX_Yx5xxxar z*)2GbKTliGEIzoO<1ht#1t{4%ru_vsYJBV2g4s*>3Rh*%A?WlB1^v`)k5jGG%xWS? zC>0{mz{$G7cnj-?#r#BD+gFaZS_gdIH&;`uX-JEe`7cw#TjqS&jCv-fRmXkK$TIug z!!Mkq*r;zXF!Y=N)%TQ!uj*%UAnV(BeCzDZ+Szcn z`o3bc$mO0c!OMjb2t38$D(#eBZvMFtwn1vCQ_I{D!$UYvD#wY{k(|a9kx>D;`>=wzAq!+so+$T zB~7)bynf74@PaLK{iA}sG9XDwb6lPAdArSvcSh9iErA&@gFS37$e2*04vO0b&N{>W!}a(JU33Kt&_L z0o4wEx6){B%m@X>BdwIw+bm12FSPKKL57`ObPE*#k>BBD7 zQ;`UgUjv)B43Dc;Wj`)Fo~c_gGs5jlz#0;lD`aw)J~blFMEG>WbN?#9$#Fjju0v>R_A%u|<;Rv_ zMQC-fj}S3EAn(IX9O|O$M>TE|PYTqg5s7B6Wm&W2*eq&}!=V#ORv8u!>9JuQ+PnZ;IM^hTez- zYCnn6D)QIi%3QE$&l3Cep3W6F7v$JT%G{{#*VpPz7UP2aKmo1LZ0}FPp-IC^#`Gfb zh<6%_7m-n3SYNBUh31K~-{x{zFRz28zRnTV%as%wMWzqr69%jaHtQN1a%ZNVy?PlV zb^Uu(6I|kxdbmy}QKuE$zjruabYj)f@#XHWKM8qd7@9{|Md(VL87|^%01}g705mP- zs%OB9@%-ogVXd;>LgE2iaQVed048xfxEie?7UOU&2shO&qS<#V(Ia!K`-a0<}vEln~zHW63Jn4x9w4#jP|rzKn24{z2!D_&>ek zrvGb#i+o;rxZL%-9*irg?QtzK+^JLfgPXsq<5xl~yyL2R*@-uJI2Z&psXr73qG?{# zQCbC!zIgINQT4-OIf=sPOwn7i+tP|kX$_h-U zz5V$|7sP_6R%k>$WY1BoOF#gkG4MHnZw*_Np8fOhzQF=Z7$(KE6`%Kc(-+}s2{K1G z9wDbQHEb?t8zdAcOHS)QN5)eZ_4c!dquIc4w1b62h)<&W^PE^EOGQ-cK|Ej9c*Yr2|~e8 zG&Q~;kX*XYT(_`~0aH#yh@8O&j)oPhYR8J&T-6J0uajuzh1i#~*#K~}$t8|mqzDD( z2Y!dEJ=pj_Ah2p&bTah~mYDr%L~#?P&h~MpGB1Y8z4)TY+BG`n-^{MZc0c}ob{t<# z-mh}nqv=IMzsp`hYq#dp+*8X+TCFFZ1WglDai9$Tg z&?Z>RmCV0E3cc4Y9sa76PFj6P-w3X)hFp-5jBJ25SpDiPKZn4QwK5Ul`EkLR7uH!7 zu;Xl99t#`aFeM?Bc1YUvZ-2e;+M4v{GJ|;gFLAFAj9W1*YhPKD>clX}PO zL?orI86rnBb)M=@5KHS?=%e;;T;&4K$~a{WBu#C>WD1>@FVdwp^8J!2STc9bKaUT$ zxZkn@)|5X!C8afBgS#MJ?&q9CFL&&HQs3G4)PidP&<^d1stvR?rV24MR}I+Zd1|F# z+$25m_=$WzZs6ROZ3?a6-M`41d%Chh=8x&WE72@kSwoa7`{sS^d()rOG!R1;m&czx zX|YNRla98#n<~g}&$WVE>^hh>2gRmftgOsfU?i$bhF}Ul zFIP`8C$K~3(!7Rc$-p8XNf>AUWjX0<&VeZvB~Uih7_iz-FZR{*FgAh!rb-BSMoOq& zf)i(@WhON7w)}&0rC|wuMJY z1xG-Y4(IHLAq~^C7g9^3+3KN-{&C1*V4N1}0;5nB0G%?^l)0@BOwqAkDDoU;QmR;Y zu)ZI@)nJc9*%f`H3ptj)He6A>o0t$-Q)Scg)j?G-y*U|`7-RAd_fpVuM`mefIhFx7V<8)cTumHmA|`r%t&UnPaHbhaUoP z*tqf^DHRJ3Z#HGY`RYMSFNIF8$dDM|^6$T&z3NDG^%g;^~9-p28fwFH9#W zovxm^%!ja0Uvt$~?|=F>4a|M%sr|VuLkvCY^he=6rze*s0+qI`&g#quwo4hCk^pCpezrT2=N?5y@`NDb?YI=>W--lbhi5nDiF(lj7LA-7S zmBN?Q|4hfvOjPY)pwWf)Jl^TxKuJ?%iYX@wPc|rBFT&H)5Nt4q8At*EL4RH8z#vnL z5(@E10@3V|-{bjDN2iCuj_w3s`@qV(vV}&G!JeUY{_DfX1Y$J2zYRQy)DaRiilE(N z5-aVeCw0{byuJ)BZV`MQCEF#z;nRl{3&ZwUNqQVAWn_FpeX(9JV+->`$f@2~~M^2lZ>p)zg(OT6l#rXQa zE{a+0^4U@eO3{)%SjEJ*#ji#CN5LwX*Z77E!RKmw7en}=rk7JR(Y<;G)d$e7x=9($ zQ1BP_&pwj(y-tE)+JF)YhCo_~%SKr=9FaTBp~CIsm0kYYnzy`L!9zz>DAA z&rYDe(D=uZ4%|+R*HZNo=&jyqWT+%`Y*EK7+l9fP>1s5qfA45@^sj2HB0GURwa^6); z12#vkrbjU($=nLKi3xwXYK!h-1$MnCmn=_7?)YrxBWPWgqs>-H;4JX6TwKYjc7z3> zAvZ&aX)-fZ5mP{siSdBLotuE``7k{5|~(KFIP4f@i>h(ic4RbjY= zb7n(1ONpCuvvYyExPcHnc7pO{oRvl-DNSMI!J7B!{fvnY1UIEbmU zZtcozHwq^=q@t8X7(w~I1Ommb%q}2(_C%>to~cS|3zBZc@qbldsZ(?uIZ&EweUrL~ zw-PY_Xl&2gdHF|v(nP0qf*?7VIZNLa%%a{?dIwjW8h9xQb@WN-uPQl*;7QSRbL+kq z5D?z3cdB$^{2GbGc`F~Y7m25lNDr;y=veqj(v;9SM{HETI$$vutUPqv?SN@Y`TDv)QzRmEco) z!~W^4lJ!rcf{N3}EuUDY_GV494U0Ru(P~>IE06*62eqnP7{nYcC;2g8hgF24_YS)% z>N;jb+t;WX4qHqIPM|XAMh

w4U_LA`70*o^-_wp;Wy5vI+}SSkY)8o=T8~m7%be z3@$0W+A(f5@wqING>7qJA3yS12pV{7p!-o{a>1sZ&etcVZyXDXx23r-u-NPDX0V+Q zOXiViu8C|eu8j*^T$KgDE1Od3m>~=c2=EeHU)+Kj^hSNcz31d>XoS+3%{3ah6d7+_ z=>iEZxVM+Q-DP($(D1_LRnD)r?xl)1<~+TtCY&wsd5WK3E%N*r7h-tPS;tY9(M-?1 z8%KR4139z6aV7& zjV(2Ymf<_c9sTwYIR>6iLB+3GT@sp>C#JLD2sH=VNWi8U#tteWAILxl1mP?6#CZ@Y zp!74wAJPRZ&X^D!#E^+d9|S2*nT!)sS+@k$=4c>6H>|u14xet|Cjl z+=*eOVK_i1pNFNPvb=OuaeME~SZ5-5UdT!Inv~l^(Oa9kmb1EH$@7A_UX?22pJ4f5oEh)p(+OJ+FO0t2tn*Nuo#X z%3Op2Jb@h$SV|yzr#*c5@N?Rkh#RAD^-<(cj(rOF`sP8)={=Ty|sOIw1~ns+Oj5J zRwf^jkU(GV5IeaV@z+x#srh&ZX8LU(s@TanlRFC!tO*R#Zf4l!^04lKyiCB^!yq2IC7;*OMAQPX?UR*H;_Op zRMi^#$ZTIMqm#k4>AX{v(-kea?5gkg3t=h@11*IRdji!0#?YhbBE_ZBv34IDunZN4 zv}Jf44U~he*Ygq*D$^sCW-zn zey&_PeT3fF+gjk)KKo49>yDOBG^x$?3jBhU?${Rv>6Od;33|$w?oB64?l%vG(5@xL ziZ-_`s*X39OohATOl~0J7tPnz^{wm`hdW!M1k{2@!=$FmaE?iWidiH?MYt2!A{YH`(3x9^{)hdX$ zUEm{YXkaC@GxyWKDNT*gaF&Squ^8V9`tBJ!A$t>FCWyyc3(0}rUE^$;QwBbop)uYz zci^WCD+m;Mxw_TMSKhT)sdK%m>g{}S_L{%47|%|Ao_Pux@J(;5FSBX=eq89#k|tff zc>=b`(nZoMGK8XWQgLi)@-^zWUtI|=#vRMQysu6$wrQE;{I*wbSjtSuG8>8UzE%Vp zvdiP)2BIMd@%(9>xZzw;4g5pxP(GH$a-@h!kJ2nh64NPUDjP+B5$+#5XP<#x4Z%ZQ z_#2p$IwxgvlV^Pi9oFF=?DAb>IC9UYu__|G=kD2vQW(rLQ8yNy)x@tHPv+wJyIh8( z<2;KJ!)r@x1WvJug^(rX9dsdgTb>P7% zU}7y`??-QJPG;F&?QT;}>wRj{lQE{fHRj6FsUu?4~JwQ7s+~)4cRJXFZ6#6?}S@a@WqS zuSY&Kpw)I(Uw77eD7Vj1&2M3M_bOE((IaiiflMISPK^6k&*~QbK`3d~zRb4P;Ek&Sxw$)E$MFkuLg|6X!^NEbS9WDolsa*%_@=%S;__O} zws$zP)?yK^%-IoYWP5@WXi(^g%gW_@QSYby;bsisi|#VI^+=`3s$}2jMRU8UN%8d2 zV*>gIM=HJLcenz#+UjqyEN}{_pKtB!PQG!26VBL_&SKR7A7!uV-8t?QAWSqJK46F6TWQhz8xj-*^+hO12o=UOfC;i`4U~Bbf2L-qQTnWP)b+x`8J5ROSMn&m zaWuxn0cV~v@l7cUWDkn885@uA{E9>}+uVR|-DmD8gl0GAqd*SR@_musEkHg#!sUgr zFTx?qoJ;*i&gxAe)R<#^dAPfvHR?lMYF2?U2P00&I(lRM5%$Kx{K?YkM=dT9tuFc? zE&!V{rEb!s5c*M(D2(L-+O>rgexaiayY-({>OXrw)9>P)9$Zrj0OaOxU8pi9Z^A%Q zZit-%7o73Jh31JTdJAiz_&fr6KZ-rXwhilB1rr^02AN%EBhG_H8<1ovQ(C&cf}Kw_ z^ZR{39s?IjrPFIqWk}`yS`GP7+mpDt}cfve@rE0>@}tmn+6Zf;0)Ow3wsaoIGU za$|2I!T5Yl_v=4Z?76&n2$NlEdz8bqFnV60PaPKKje8qsW#fJTH=u~X+-|hq`4IBd zztrz7mowqfHD7xWJSc4-cW<=dttzD4t2(64nNl0$#XTp8uU)`AT1Y}nyhfS(_;4hy*Mz=^yoSWYHf6cvlJXG)h zKRl&U$<}6#ERk#pjeUfYgeZhiWM}Ng7)-qpiByWvP=q36-%XatI`)0+jD75k88i1a zy+8N;{e6GSegAu($3vZT=FBkwgTDtX00FIYaUCh;f z{n9ZTj}CieTt2Mj=3*Td<=1Z|eaN#gvsZG%Typij@S(??0eVA-p|HD! zE6L%GOU_vapd3GRIrTd77w?(O;x5R;eyy_>T-@19!|`^OAAHXh=~Z5DhP*jcr2h{; zR|o_UY<4r37xmY)&It)*HC#3HiDQoyzTu#E!OJ?n|66KQn_cp70n4euww-hcp`u?g zO@3$JPIk#VLR|iCj~m`C;d}0i-#d8Ij97`+-7~8AKC?)t!;psqH9wjw9zA#NP4uAfq;3QI9Gd&J< z)2zQEf$inT=svCY3T{Ov-)vmZ^PMnvsWDkeFMchPsu7))E1v%5kestke?))cAFa3D zz2(Bb*LB|gz^`6@%x@E=wg*~y9ZwmiCv=&MJ@EaN@ZB%&BWL~N2TDl~p1-s)?!%aH z3vTb*t)$7^5&vnzlXK!hoOw=rw-HRw^0;Bn-6PHY^)T9-k4kWIef;QPZ{9TLaBnFqtF`M} zZqTVO8*iVp@-HelRNz^lE^;q8U%m$lva#I-P0rU@oZkne_th?-ZA5jh*R-|CbhFTY z+6Jv&4&l^XX%cWS%h#AZ^ULjpI=;UY5*^ zjKs)$5YAJKj4bW$l{Z{0E0v3@iUysF8+k500^-_pjU)E=eyRQV8fz$45$9m?(`ZA* zO#N1ye~wyILeg!;Tijuh&zo#d9#R*(+!A1CcrvViSXk#%m(x@Q{`|KeI~gQngq(z+ zr|grPv$lpGjExz@ZO@)@jQ;#U*r>gU>+sLR5ALs2^|(18BO}ggL>RhkJr9g%=QXO? zIrZp){FNMt`j=b68Ghoeg=ZmbzMDc%pFV@=$>$h-X73i(c1ff@Ij-j2e{;9_@H*9EHaLIZ*5kh58u-2{bt(lB0P|| zc=v)||Iw2IjaeHqz3rzxzOfk!HDqMT>oPmXX6P82nCpp!nKO7vx5xTr+Ma2WIgPX) z5NNQ^m2r{3FSq^qia_%m!f+=^rt?&Xd_$emn?92 zJFe9}nb`(%H{y-$5fQC>C(nvRT+#ca@%c~x;`f9hD(TXLUs{lF@{TLVglwcXRa!0c z<$Mxd90ZO;9YH$BhcEvSdC}H2+sdS4b4V}hL0_>fKtlJ-lb(FfdUjVJR7oeQtA#7? ztfnaAJ?<{<895zWl-y-QhScs`jJST^#7mOu&r4o}c&2g?+JC!S0a;=F<6t*Bk65Df)+ovtwKlSZB zw)BfzFY&SWOl`P*yLWaGV?qC%;+MJ)+p+JBzMaktx)>Ij#(l1q)0LoO<2!46!3Iyv z)VcM%xU2n9hYZ^p7rD2ZvQqt=#|2J@%`t6G8R3Sn>Bg!MIn!e0Wc&9k9A`Ted2D%E zUfDb>HGd)GtK2ipseY|7Zq`H2Tr1~(ro4t>oInAqp-cN?!!v@HL+$ar5Oue#7Fnpv zDY5EnO%b`eTU}|_8%1s!3U|Ce=X71Gs9;C%^g7MZhKSbsP?cbUbgUlY(Hd$eXMIapo zuJ(S56pw?LgCO~OynluW1oRy~g4W$=U=5mQ!0w{3*c^QUFnE$-?TfoeucB3h|`sl(LfzUFP zPetK$t4t%NR|@KPEyBZC**xz-yOgBVs5fP7X=TT4d_R*faP7G?nk0_h$i|k`PS<$u zWcSDx4xloKfrOAvZ5HgtqG?A8wk%rcEYG~3IfvAz@h3u?o7$*@5AMP7d5_fO(75d# z%EWyGUd2G5FY01x;nstnYjrus6#OS9_OhOS4r9|eo=;|5KQO34I609%m|_cJ{gf~} zw#49>52n_YUbBlLM6c?pXm?tPfy&;*fgbl>EhGQlB>%pPH2D5J>SCVTcXr6$uloj1 z%}zpYE#;Bs8ATbzu6gGT(7L_Rf}+2q?(}RmygW0|Ixf4JAnVXlF#0)c$?h{zH5k`q z5X=Bkp$?|Ge^LeyOJ!hLnzIE%*)$^XVG;b)&ilyZ*_^;|Ju?@KcTCOFBm?7|Uw6kY zH66S58lm#5t$y-2qD^ObzmSPrYe<_o!j95K(sbgU7v-1pcXPmZ;jf`k7D4t$nRr44h zr}EH(WS8b?o9Khg?2wI8*gyZ7P#2Lj0**#4tn8j!a_C4_^fnP2^yAxK->phYK(8-Y zOSLX8_JyS!l%w;1{(N}$xAZ}GW&$aQhm* zO(c$xVp7og10(aq-?0WN$r%e3PkLNe6CJQg^K>rW;;Fhx$p6Cr_ThS99F&F)=ZP)K0uW z%#;qOOH1yGxCd>w<{eNAt@kF#DgJBE$>YNgPDtOM)Sc^>7$oVIWoerydHG3>85zf! zL>Ow6EHWom?7G2?Pr?W5u6P&9w$Ft3^xTh7kd^IO0kV7syJtW^R=Ja(-z}@k1LDSP zYyIS%1{H4RQmExtUf>*bOri8zt2Qup8l_trOKFLx&GukNiFrkozCw3OxHYWWQ|R6E z^BTtm8gfZf@yY0M6hFhWR~*vSTN~LUj+2Gh?eb!t%nHnIHBnWskVD#P*eC?H9t+zJ zK_BEf=g^vA2Tp?f8}Zl;EOi>)J-TH;8^Te3S(CA$Y{65a=sQ-GBX!-~UfF%ep8fuv z-aZy?imU5d%A@>aNDc_RZ)}Xw=Yhnb4tyiC(vO)R2gVI;2BR2Lv)2UinECSsQL|ZV z=~Sr9uIes*nYK6teQz|rO`x8FC=m3MDKG5PSBd-H=v!jGb8TkG$yGjss$ErLz#gW3 zwtQ%)i7)5~WNdRV&D&cXtnjciFBAj*XpFx7?>AL`fB9v6cdThHhWE8VFiAX*__bI< z7xA(C*fTVZNUH}oK`jku<=>}bH-cWhdbK--3Jh>|_VdfY!%;-^HjFZC!sB`@_W~>! z*Olg;!`|M;A@%6UGX_R`el#xa8qbzm?XOs_+05j?asTrg>Afij9k7G(Ktf9LCmVCI z?dO@vlqqjqp7YacUfmRvq%Vv!_$Od;% z&@b0onAiQlv{kGkrRp3tcn+#h`#?NMZniTsk?gE%OCfF3%KYY{bx!{cFs12fo8e2t zv}Pu0*+Lodx4g1#?fU!}Sm0c?yQ_yb@jyH;I4mN`W61o~HdI!IJBkq}}r51@|%I2bAHJrWjyx zfJ9=~ro_D>$4=Rqy=H014B;Q3APk2ch)M# zE7%_wcvR)TP|HXh*?XN=wf})sAO6XkW31{3M4RQpk814RTzdG}`mYO}vc5rh-v#PS z7zZu|yS6e;eTgO$gNp~2+(vJYIlFIvk+!Px+3T#$OI8&n5cH<1VW^$u_30+f<4H9= zi!VRHXpHE=M|;sdG!ibbsZ>55wz-sv-EZWv4w{Z$f^M7#tt5O-|8(_W*AwVJ2mBvj z$D9|AI(MfhI^Wrk_&X90_$ib8&CN*QYTJw17TJXIF{3c_R=RZ1 z#DRg2GG^9_NaC;>^uJLL=Kht16W)g?0@c4&>LQ(o_nwvXHEUTMavJZ$3S@Ah}!e&Lllz zO8+0;)QFRa-GtTb)r#yNR_{@VWht8}WRjbl;Gv>2JCmE$diDYMufz(}*w2F{ySLDu z;bY|lU(KC%-tOzkiCQ>~h-jyr=q~G^6=oYXKc8UWg1JFap0c}k_D9{@Z$A50%00O< z0vRr!*_hQ0XT`Y}8~M3DnRHGr1>brHQmtcWHj8wT+Q$iPjwJz5cz2o zd5Dc2vN$X)A?22Fz1JKyv-U+!?^wM6WX8;IX06sxX1Lo{Je{pCqi_t$o|<^dfL#VR zVw(3TAps-bD2FNJ5;&4t=HXlWP#Kwrf%O<`U%sw>3Zsu2IpmXET7mzbDk0M0SNgN; z=L)1kA~HK(TCc*Pi{=d=m>{kNkLOZt0&nbi$9iM&QAT|mwh9>cWY~T zE0^!<{tI`?-1-L&>wtWW=tj#+=2N%&gjiwMYKDoDQPR>9+XL0D6$}d{N>#)c^~8x= zH*rbG_dI;RL|C2hLPM1MvA4~S=X0S7-?RYWu;HAkEUqdY3T(usgq2YU$1#T7$Sb|8)lIW8 z!1*m4rk`|q^sP`+R2Lm$7iza{_D|Mp1C$KjdX-N5ZT0Rn%im-EftMB*6&1zDC~z}N zTLu*NB)se3K;6C8Ic0w%v?0CUdEsQfx1AZgX4KmRQ~ZOd7saf;mfW_b1OCPz#=<39 z{bujIO8wa{tW!~4i6R!t$=(umdQleqIwWuCY0@IM;@h1M7lLo+2Hjr{2+@dGdJCel zM8_qq?J%ZS-REow8&!P^MYg>+&7z@=oE+!DD^u-rd^=XY2HDzV_l@PG^_gcbT(4i3 zYmc~m+OpisE+8OaWiwKS%}uoC#sl+K2dY{@J!^BZd!(iNz2ly$Ms))4^A7EG|7hWC z5K*`4q2qx)!==B`OiZRday`SNPs)w8dWQk%y@4%V%y84jLDU;$jw#0P#QaYedEC?D z$}KwKDz~K#3Z?q$7)CW(d_<0Pd51*I4j=_W2Ng-FVsI{(mA69L<~jZ8y7A}FKTQqJ zmoH}RA66zSI_E46$G8-_bCR8NUOGAVtn);8=>%p%TQizAUfiBf# ze9RUqBriG0HYDi1k?(E3K-kaxhq|3)`ID;~e8V35|yi3VId}mVOP@96fBk>uaqn zE32nvn)^r*nZ8s`%uM zOlJ6XusaSN+nWesg{WuuRan;ibB9xMM*x8K>Ye$t7$rhvDg|WR70+wSzn(J~sI1q7 z^93}KHVI1=V^8nL3J@Q6#@C!<&RKU+1FyqzGbUTQ_M0aOujV(6Z8xDQb?L39CHRhT zwLPj|W#1z;&nX2+)&A^&U$B2T>jfpxDJ#fFnAc3*?^j;jqpu_8N6Wpz&8GBcXQsZQ zGaI-r?4kmphPs5+7c0(!JHX+qz29Tocg890w9|DpJmyOJ=DMR2JCgJZ_S;(%fb3BS zFc>L*q6It?mHX(>GZe8J5xY_}f~oxsql#V-=boM~zZ~h1axf)T61crs=aPppyra4^ zSXqJzho=%ag&=aicfj)_CcRjs_! ze>ook_1qjze6zl@TSZVM7xGIzQov?K+6GhSpNd7WmBu~&{5v_tyD^llpL)rEI@+6& zh4&){Go&*;{b@_#t5tFOiOM9}K(%il{`ZRAwE!wWV+WS*H1Rylp=V?wEWcW1i!nJM z^<^@efPm3_t;ugWr&Frdx~GZA-Ir&Ygu1}>4;i^=$8^9*4P^5ilVpb+6Bo)Dav2}P zrySsOl{4zr@5c&zVAlq;ap3RT$3Of0BB$K?y1{56!38$O zjLQyr8J;b@nR45>XwV(>@S&m;4)t>h_Vfn8gX3~VSoo}8xYT+U+65w4;)*#$MjjOx zmQ@FC3GusT%w25^JQxUi+Fs6R9k5E8ogEXgAk%sO&_2`2>&SUn;LfWgcV>tZ#_x>k zz<{%E?jy6kZf_innv4L*wxAEPPa!eIsBEm=H&88iRu=34`KP`8@Gp1T4tT3letGGa z)_Cbmr*4T=Sr9<2YpSAeS@}1V3S%O8ap8wX7?p?iw}bEo<0yo3De?(TjiT~n4q zzENkF?+&uVj`{Ig^N|(5fa=nl-@v^xKy-C29v*#+pYZQfb1A+3G?0i!a|>Q*NhfbDYJ!I)!F!R-d+vGs}G-m~mMq*iNSJlX$D8!I|3 zP?X02i|r<-1WH3bVLjGC*cyA{f+bl8yR0;R|Gs*kh_>EjBS^ct{TSPJeyABSqV@;2 zKNY_pLbawOV}Cl6r4O>ff^oB^Gw;iiE~qMvM=2h9W|HkY^JnrE$GEHgxcl`E9DjMh z_F@ik(@k^n*L?9UYIV zE0|to-3D*Ua{{UnD{we)oy0DZ(66;R@FGz-Iks!FgJBDAWW3Zc``b~NP;a@qw>}+f zI=-2_tFkj_n|{R_S{aT%G2m+F9LJP54R`N7QfxHUVb?=G2bP`T0Q;T(p9mw!1As;F%?C$d>Lya zEa)tiQbr8@bP7=(Z)F}7my3CAyP~EM(GF66nY#b9eCSo}w zq~j9_2w~yYLaFWt{qE(onlqxSs#FWFE2AAP1*ZgDoi1VI-9ytktOLK};nr3Dlj}|V z{L)EA#(nWMTL4&uqpGP^QaYC#Fj|KlJ;nQc@poyXj$Q(Kr-JskWV>ND3}a-u_FTkL zclQQ*AD4p1YX@$&x4PFLk)`H5(UDeIY(gfoJ}4tIlZvM8kE`yE@Wy$9+t9u zHrdYM(9~V`owTihRsiy)2bh+3Q3PDd2aU7&yTFv8x@IOQnniM12%sp}jPCYqfdrCc zvb3Y8F%J4TWo6x?zvDj)njW4%uqE)n%N{#hIW}R!-UZ;@Az^-r)xc{^;bmqKUwWK$ zVG)*HlzTi2IsY8d`jniU+aeg+*-IT$Bwk46tap@ioOLG$e15MnYPk36oA9$SZRxEJ zHDT}ozhCtYfrf1WJVzyD8acPEsBxmJk9{rA*>N4#gZp%}cU-s}X=q8V$SqN|zClNW zc%|Od%Rlf`?d)AOU0K`qwzkpXnTq~n7hTBgu` zMn*OIp#sby@LcXDej;j|JiM~AyzCm4-?Pxx-mXes zF4W^TNM#dn$YVpO05c5^jQ|n$jdyOjdEBgcUX>tTaOWl9&L!qKA&jhtpY;d8;re2} z%Y*segbp2UgFi#!4R}Bp^7%0;$c>ri*jNkw6gA*@3nTMlDx}`} zd)wRf;0cL|N}%1b+?(*#JM>ev#wasAUfvdK8ad zu+@Wu(J04O=%+)7hq@h}YGfW6{oQnq9No{&p44TUeO*wHU5Dd@A}XwG8iYd|;$8IG z8CL2%Ziu1DFJ0bcWjY2{Q_G@vR+(#WwX+btRz5c_RU!sgmT6qV3$KU2DKw3!3 z%#2zmd!K)A?*O*ZbzSQbair0T9?35@aEuELxzV)I}U_0xg|Hh(%ca>l3_V6cH zhbp^Ab@{6-)AbMg>auQKFN>#>BKSElnq!j{Dr8yo(w;T7QZ#siA46*9AF?{73WXxp zCTeRRd+e=E5|UByY(&Z_by3^d;&^~}Li!s`O^-IY0B~LBAKpHyOBWqW-@NyTP`x?3 zM(IJ17gcCu$=am@b+sXk^c)2p^Jid(ex#tUv5Xm!HjX6+F4nhWG1~bfE;oQA0L%tP zUpnpn$CB5<8%=dT5!3~AS#%{1hXX2u>c$@-NT+kL+D?8<5Lls6Dssx6cX3#Q;43Z# zH&QKnZ$?-2$#Ed05HH8`(Wv|eEMtW$-18(7k}&GelA+BXv^AJ-n^&{HSfNZ5K4xj$ zD}(IG(wIqle=hE6AsCE*;YCO9nemyqIcst+>%O>hqQ@3cgH7|S+%`Iw%q{Hlp?&qr zf$x`YQjGS2V`(gl13{s>aEpZ7N+vJc&podJsrHsbj*QN`(Oylwe{O~6>HQZ+`z?l_ z1R^<>O8%B&mgtrgft2l%g?s`=*p?tWonFr4+zDu5>zOGrupp2Dfq!!o&8j=B3T-Mgw0s%Y+Pwjyn z^uz#Eyyt9q)}iB5IX>lwaMEvP-`8sXL~W{%lJ8@lT~%6`gH+%oOecJF=z?JApe?wU zk!D$(%4VA^ZuE)4oqz1}^B2y6>k ztGi)!#zt3|F4vO>+74opgh!Cdh`YnaN>9T(J}JsVq2YiQLBYfIeRXwpOL{COy^bZMEU%2!wZ~NWy*K^drGy8odwTJm;^=xYKou2M*}6TWP2uBEO+a(wO^7WOH)5NPs^(NF#xiJB!d4d{`mXe+90 zWO*QPDRQ-oaaY0WJqx?WG9z8B`g+!WrTxcT(8RCBqmB9)C0`J9nkC1`nJK~hB*Luw z2e#5EeXoThzy?+|jB+mRbZjxg)+b`9pHw|uP0b7Y)u?;Z-Pu$6rFr*r7tixzd?MJU z`eT8oDYsht+b=TkV`+@A?R^7^M-XYbWJKqkuwKvXtX;!WFhk(Rch(qbsEb`*1_(5+}R(=%kfSz-|Kx;+sHn39CWML$skyl>`b8{?wDhhv7K4sJ!ms5#T z5UCl9YyOPv3tKAwtMqie0fUwKjW-#+PfRk|ok!5-cgz+1*Ctv)d8LuZ{bK6yIxhY6 zrN3pmY+xokXESorQYiUXmoeyle)#n2=H}-8`}YCSI1T~wL`=}KZ3=ZO^Hu8L2iqix zNqTGxE#spHH$y2^>H#d7x5{Bez7u?^12CuZxy7^?wE&PGOs#`_O<4>Ix@@d#+`fW! z{eV5b20^S^cDn&uUQQZN+YV9Yx^Wy5FKr#X{+q*n@e6o-oIVBvLR^mdh&VM`!kBjo zzD=bQL<#)-56}brj@i#~uK#0IgWAmH^CA4ddHvhf(;CM;N4m`URs65E zUQ6$N3c(PN$%Hmu4NjJDP>N}*YHI3nO-MJboI;rhnKS6CvySpoWRS>cZ%D|_acC>dgc_pMR zRiGLOefh|AAO?kG8Yvi`>c<*%i2v}MSOwo`eRoRrIo?t-hu8b*x zQ5#T77!=TFH%o!iFmIkh75%0$ z`_i;w9CeR&0Lm1v8Jl=$6vV-hH95Kmw(A~DtsdVG>J~sC!y}C0$VkLB$%A2+yy#Le zmiMeMc;En_(71h-*1TZ7&q$l5tpG+)Lz&H^Okwx8>NX~xqhhG(MAA&k{@(X23G^%z z%{RbLUukA_g>BsrnamH`ms1{S-+tTJE~1Nk6@;`BRHLlb6U*nmg!8>qV<&4z<>xLn zOZr+iaT0%K4pn+lHHj)-<1f#kH|k!Yr<-Ux$Z=>}@XBr#oS(7;+eh3=>ncT$h|afj ztY#_7fJtlIG1!vWc?JMOun!&dh#Kg_73rX-2fTZ*A^2xm+2D#FVQ#EN-o)6Kp!Xqw zRLntLE)8aeP~5R=Td0~@>GCQDNa3!^e75_3DQ(qMjf5ZHZV+Ov>a?grSs}pW$h=G@ zUit4~>bbGS{}QHBtWmq7Df??#k~nHDK?M5Rbj1oWeXOJcTPB22^tOk?S=cM_@F=h* z7%=PsYxDsNDzWb;z#oSoWxeA39m>-yJzyIVnN#M-2$b(PQhDiWU#+?AfSs$~yq z4R|T{$9MM)s1aB%I3dT(g&$2>_hoP_)Av#4g2qVaReD-NM{kU(CI{^d*@9f57Wgp% z@WR!qOS5TtwrhH~q9a;rH}*uVqj_Z^jyal^GMo4}{;?ns-+c#CD`r+&MRxmn%s4G1 zCE!3bxU447kH9RrYROL9P9+p8F4*J1i-n46?t{|)Do833x3!>~o;ylsZBygb$nLBQ zRPtQqiXRh1ZDUXKK$d3bm9ks4D+4K`QORSZjcn;63qY3O#pWpAXWarC5f%mjuOiB% zaMZSOC2Blv^(FtFwnOlSw%?@}HN_@3`(kfwW-%?TO0PnoiUBo83;9wGrf~-gtfMps zS`v}ho#cYv##$n9qGP*b;KxdEKOaki)$DbP_YYSqsL?Tl+C>n??>}I{!GMam4n!WX(QTtvBKW6p#xbSVSnll=v#R^FM&HvDbaLY>~PVzUEu6aw2Pqu|i_4 z8`%!Hv8_aR`Yo-fg9TcM5$%nwnyDn$8-Dea!8nhb>MnBtqDdEwV!*KS+kF&RAXZay znd94%=u1w%QdJafEOm*tu8iGO{;Ij714a*if=+6*wCD^yCt%B$Nm7{Qe5uyATMofw z>v38>EN{)kWHkMyap==aZq7lk zi@QMiRF!Br*fwj#Z5PQ41+2P{@ekHmym0xWJv#V3d8p{tIQx4s|zJ#8ZxFT@Yy51s9O#XL8hGycN=h zGL%k>*)qT0*~(W=6ZAtWNuuBFzzKW-+a`DQWt&0^M}W8nEh`pl14i#Wy;pFzR$%9g z=k4k%$CIm+I(YN&Ue(t{N4VUbsMcilY!+K%rflw^39Hf)p3;CKicZ(aN2P5%B;EY^hIRl%rb`ZDZCWji}l=*Ul_?}m&t^)Cu<$$C%%CO7E zmAo>--obS1-+rNdvv-(tQ>(RY?lq*0t@^(r$nku$({fCng))Uki*fv#W^o`bM9Q>? z7XW@<{;+Nl868a;12nKq4tQS^wQr*)V8juuALSZKK=u z?*C5vus}Tk=KCZ;6X4l~4jFI5vjF5;L4RAEy=izB^7(xt2GhPd%IST-r(3TD^fb2$ z96|bC*94~ue_!`QFOABKQ1O`fl_i<^Z@!;7Pdw-`fE`daae39`8S@a2S0?&z9W9RM z=PifVK@JTVbpSLQn>P%M6GY{c5U7}>q!?j^4q-71tie+gDf=}8=nZYk2XAHfc60LH zbW9$Pdi_X<{Y$$rwy75px0NR6h7J>9XTR@DK<;2wZ>m!Emn?ZUxKOxP15 zrHAIhgGd2eVq(C|TW!eaK4(Cm_{m$DFnl1%%5M7IOJBFZCGc2$;G+eB8zlV1AVmPw z)>r-0y1?=k_>Fqb%=9MVfH7Y>^h$daKp~@56#a1}E}sbm0>&F`?S21)-ZHG}{xB#% z-2wr}Uq<4uIMbuxvNx#t@3j4w*s}WchydhKO(5wvhxKTC%~`D&M}i=q4t(2MLhW(F(ohv%FIs&mwwy3eDp1 zPjD^@ye7uR#=rfa;qjYy!`Pr-YbJTH$iUg(@m8*cX8Z`3&6#6qi*LjExvW=q&o{;^ z+~{<-Xqv1W^L1#)8GwTQ|l)g~gpbsQkzF%k3W zpm0%nkcr;U12I_|p{!)YFd%J}&CIYdFAkWRLoi<6K7(UBJjL4q*8vv*L zHh@M$7izj$K}HEJ3wz4;g`QhN*(?C2``_=4a*M*KlJp;!(jUWvuKYA~ctQ$nm@Fn3At;r z{iq*2aLrg=8*9F;)jtNB%jheOkh`+N9<&q$&VDfcYSCb6W4w>-t`J)U*;QB-`6Q%& z=S#Dr|3=+Y_3|rD)qW0xO#*Wj+NkQx^40TiMoZYpzZM~&t?-W0P1na)D~cFny#6Q7 zvpeynX~`WLZ-;TqZ@SJ;gx3h~??iqnT`7qW6J_;sd%4+o6K8Z-x(X&y&akKHE>W$#<_Bz`5c*?ymmya}e-@t0>}!yMljO{ZUp_^6)wq6CE-g zr1sCxmq*2yxCXAia5i_8F*t!y*jKNe#U+eU>L{#E|n&OZWWMVaJS;`vQ$@9<{khlz_v8T7U z@3pELtNRzjx@>lTL^?u`do)4au9o75gG98?uUf?BPYeq@<2iNm5l;-*`$mAZW z(TJ!VRd9@(H;ceLggsO9n)w3`b=!Xr@-(PBNdV-2^V;Wo5f-`@Dhs!5*EdMG_t{9nzGL3+V24m4lYUx>7=Q%ho1)PVze3};a zQI3~ov&vUntysl9`c_)yTEa;IxTEi}#Dot1N5{sOY3e3=m;4v3vz<+)C-UtjLV5*?<=%wmmwg9^x%ccw04R(pgP+ijb$rWm zT3LqExckHui&BcTjwpyk&x#Lil{0N{Xe_@57zz}QB5r~9FAMa~Q>l2eZF!d*&KoiEqwDgFT+J*oUYRJ?8vcw; zW3(7v2nn#}Vj&hCwJgo*b8dFJIHRc^p_~-h%ajj_0wba+Vj6$KpZWX)4i5YJZ{sq( zHw^Mu%L995c89hA)rQ56aoC6kFS}D%VLMQ2IGC)yjIXeCad4@w-AeMEFtRLdIWLfA zZRzXV*BIoufg2kqGtxG%uhvAPUPkK$>kYFKaKXySm`}e()ND=h>*te6%INtEHA{3p zyE3$VvF?ChwKWBI;1oEw97}vmUhx-+#!XhMq_~emUsur&8@-am3>?2vAskwxl#nvE znB#)5+V)7wUmfqVpWe&x%y7PT%M8)Fy~9!I*r$t)_O{i{>}NJujy9NBvMifCM7(-y zd`7W~BpWzgipx5H25&W6h>kx~KIIJcKcAiaXPeJ)#WS~>yuD-A_c`!5J%c1~Gt4iY zyPU@}tq&ia=r68qXzw_xPhGJlGX~3As24nf)^4XxMjI3|4-a*N@&vwg{~TO4rcB&n zTLd@Ro`U0fSV^0?0Il&wjQ{*85*Xh8LBxFyQ*+~JtGyK6t30Y90mdFzkv+qM0U?+t z;>G+fJ(0>qi@2FA3n&#O!SK?rwW4{Vn9zLPYAc#ylxNI^5@FG9l!yAIthhOl?CVnB zZ{gJlr_9GPmcv~u+}$=5W;N9TcHMSG3VhJZnB5r>=5axP!YdSBI+2Ml$f|pSFLd-u zu_Uef6uwFt;9JW@&yIBGShV-T``Y1XBJ89{wspy_7yb5=+|b;WN$i5|(g&koYp$0U z-X;3#%H=ILI&`&11R(t5^poGX7IN@v zxTJ+I9o0!HC$i-1yHqUZP0!>^7yL0spKY?Bj=}a)23Dp0;JnXrRnM4MT2|J_>E}e_ ziu96y@uZ|eRVFM;*A>g*a^A1EOC^X&&F7<{NKsq+h!i$ zYbO&N;U9y8H(O@C92ZAc*>vLdt%bH|yh9J#%&&P1W3_&B9MieQyd^5Qq z@OVUJEYJ}xU9K@iBRpaM@m#zADkjfCVH?w>U6VCS<7jlYay9>J;TPr|$;R+JZyo(< z)nM!>(!fmZ2taeWm$)4N_4X3=YT5xY-inS^8tg&8r{}=C8=-$ejD~CM-&TIQ*8!2} zKfn9`)!tjFzt?>oJj)dffH>mazip=f2LQH4V^s3tI%G8eGzC;2tb^f;)plaCdjVJLi1wd*%Nv zcm|%ay}P=*YSpUM5lRYDs7M4zAP@*u`jfZ{2n6#B1cD|)fCipv6jovY{*an{QjrIN zyr@B-fDjPq0eC844+L^$0f7z-K_I>~5D3>Ht3_D=cmd8>R!SW7`u8WVy*LSYCrDcS zqngK`qi4@7%6={C*iL(Kvus~=gDJsV3&{d!$w?2&;U5fxx1qoK0%D*{P&{~T#zK2_ z`;dpPpMRei@5kL(g_^-)}U|Ia<`%z=4A$);CPFn+TSN0~_ z6MKzN{;Q`?zY9Ir9!4hq`R+YG4r++h0aSK}D%>GDOIV@Jw-9s z;IFDxvVNZx4<{mFp5v@fxZ9%Pd|&6PO$Z(C{=I4@f@Gp7y6}_3$lT3DO;>Ew&#D=( zbKnbtg&&?*J7`qPV^0PWChFe3SAn3nLPebq7Wj z;x>Qy7=0$4zjV3G_`Y;QODngh*K&Fh8bVa*@GFo%V4;HjqfQwPL2)x>-r zZLB8muEBN1;(PmGNio}7Tiv*iQI=iDk|W=)4?oLggMI(?o(49$iWy>3yoOQuBo`HL!t|G7>o10Ozo%Oj%-D&x>cUQ2#Si`>a3VqI)i7b!KO zj&WP#?6Tv;kB2;5k_i>^6aRjM;7@~ycYCRJhuEXtr4V|hp-y%oG%;@o4J@yVlg2UQ z0%iuDz+{PuK_`@@X9ZUn4g7d}NgeAB$H{bP{MOs>1?cNW^S%0e&&_4Ue-~d1>|H)? z`=_{|Fv+(T)jWdY|N0=l2ikYRH1)nQOThC-u;Ay@2ks6sT>E=438LN8R_D`HpWJaD ziTzWc{S$(V6@;tryBFqe`9iF#;_AOknhB}?&HuSASOj7J{pP=qgJ8se9QM~~VUk$? z-#1X+|8+T*L|iIz@`F$1;o;#e5wjWdwa)0EEPihpl2jooF0(!C$X;Wv%o)|T(9BQJ zf@v)g^7U@}lIz9{&3Zo)>(LE9_@Yu#K}5sHR-!QzoU1Y|z!8;v{0|j}J787Wh-4MT z^Fn8w{rgFIn?X|pZZFyj%43T9q?NFF30^f2DLGk)UH$@foIo|L?oY zfOmgRw5yyNov+m5p18o?+ng-!2}8}!*^u33n7k~^oKGC?u)9+EEIr#wcdJPuEm31f zN-jPvPibRZJ{Bu<$TbYvr?s0Gr%u{GJRCNwi>7j&_@;sr)mvCts8Tvz6Jfj97!w-{ z{cC!9dTVP7EcR7YxQUnlArUs<tc~#57 ze67jU)YS3x)ZE-0Td-WAim$IPs^VH{DJ{ssc4VbGPWa`n(RPt(BedD~(GA4oev)OX zb@)evDV5~C#yH|sd3kmxCI48??Gd8Zu41;AkY`|+VRYeCx*DA+UQu$sE>o&ZuSd0k z_|}pk3gfVhG47R{lcS@Nk&#gLSaeKGE8z!frsQF&)jdvEY=Vy{XlT&C?k{)eN?$0X zVi_11fDNVMD_=Y%75CovsJ8!GYHF)F#>3-d_0NsS!NEb*Vg*;lYAe`>4C^Yu$8&n_ z%iDgRe!Pxlw+4?(Iy=_^zYlHj0W>!i69jDOBYS%mBm5b$x_Z&IIXUlVkjQUtZ|Sw! zIXJ%Hg_UFKYH3;0(S_oMrwx8lDNQ!jvbMJNGV@)_0w(G9`Whx6S*7wraIn~djon<8 zpsZ|ET^&2I3qG&Uodb0e@OZZDzPhX+IN1Hv(AKJ$gZbLZEfuuTYi^RHM*4H z?Yae`1l`Y{X;LD+77)pE$4Ph`L=v)q(c|iSkY$d(7xMWWbC%9-&ZPUZri$1w`uh4B z>Q_&X_;6FEM|9j@vtR9a&Rl)ksnTn$YQND2@i?sgqKFgtaZWF-hHn3J9ZsAGA0MBH z$fnLDyX|C25m>PozMq0hxRHU;+B)s!YW}jk2bvr~ft+Nb#d$Xlv^`hM!9LNPYCV?P5j;CQBc%-)6j2 zm{J+bjqxP;viJA*Yi+G9Em^NvF7MxS$|ECR%FE9Jch{_|(blF?DknFM_r1*A)U;WR zu5hYU)TjhmGi{3o8>wl@De9Kee?1iU;{NIEtfndsmzTNr6W5c2tyY-EfLV=1(!RbvY;O&N8S5&hbqFW)u@Fi9WnLZ&H#a{I z&ouSdlhf02Gv|&NLBXPyHQ&X>^9~{+qA{~NFmveCK8K0T?wFqWc#dVd7^uHxu7SR3tHTuS`7ZJS%ZPM1khP7c_$g;SOw2TeJUgFjm|&O4=aIqKBm(eZI+ zX6D0{ zPVwhN($o7@kLkElsOjLDM6=QsrYcI|BQN#<_HB)gMP*($ z=}mlWY(_X#%RXPcrz=(`>v?)w`t!%ib+XBnO{*_$oC3l!A_@k!Z}`BEitX(}nZn6w zRf}dI{K?KF>9*vy&y`|88&b5TdwV~E3_U$91?l`JqV%V0M(*xB__Fom)V0A%G(SmZ zgGIb03|1OSMpG>zWHRZaW>FHatqCXVkYgF1e2CE3SnZE$4S}J98EHJLf22q7=u?Mx z$FdP$>P`BqY`CoP`W_rDn7wn-(&pQ}-52K;*PeWKnd@Tnw5o6LIHsK#n3$Lt7+iLF zXx`SewaJMO4-bcm62qMR*o}yYa3xodX5BvF;^%K&iJaNOBP7&x=HutbawRB_YFEMo zriTl~*~aFnC&E0_b}x+3PN}@648nra%WkvCC69%PPQ(*GYS#I}@ys+7_v5fji98>i{4zqaQ-Mk;tm!8h7?^#RhmmylY{5WWoSmp%<7QnIST9FM zuo~SPUfp3OW5kAPSD(UR_El4{`-#zL z8>LeEv!&(0cfWKc#w}i?--35~5)$F;!E~q5?)xTzyrR9meFz#g$9uA`#{87UZneYL z@vqeqZmc%X-9R8fBFj!sM@sbWW&yxv$~NLbB{d=#)*mDy9w+p$*X+D&*LuvwNqh^W zy0L8j>eds!5-ZP5L~D!_7Ha%)oIZh-Zxu(<#}-+Ms|Wyex;b7{*Jm>I)=&&PsQcl2 zvebOp6^eXZJ#z08XPI%ZToA|9Y5)(1^v$%Pdi%`D;+m;km#MmfAucx7lx;!OsK&HB zKH1o5avcI}MQ7gn@}=;%9vo#FGPG^*b{R!po$H(Zk%BP4o}P{l4y@{m4bGPBQ9>}} zQ|xh~Yinzdt$g1TF8bXZ?T=aUSGOF{t>TQ`TN^z7F&w;(@-A3{Z#UqV$eT$y^vll3 z@Y+g{>g(@M{q_yG@fhxv5+{xFpL_)c1&kPbH?%+~(vJu?F)>M(la$$S#XVhWu8Tr& zfu|yZM55uOZ4)n6BG7swtbrzA8ub7tn|p*8#`shcxSupB1PC<8hD%ey-s5CWMRdiw`(VtOf~%*rv`()C4JSee&cKG8dPf_8 ziTVBeHxTVXcmxD0N4#o(Fwqwqi;JjztJx;^v3Hj~fB`HHq%6_-%gf73L9_2u_?+0{ zF{O0mMJkpE0%tBr6chzj8_MbVA3l8G`|R(eZ3C=_r;{Tng0OWgav%{AgiRzoc3~+B ztTW;E8lT^tZ&rJbT2FI&uXlw?k@#Lc99Fyg``#>=>saIy%kT;b`JJu(emrSC-DdXp zq)SmzuJQRS%)L#$Gw?jEg(y{=w;~1<0aT9FAA1%S(q#%Q-^R-nx*yFqB=o=Q&EbFd zOJN^cuh@pX42V}UTFZ5+w7c7CT$zL<<0B(-xKZ-Lb7pnT>+6{A`a|14bo}|Uxkjd`k@B4uP|>gnn#nVD^~?MbdHO;5#iO+W`~oEkwHdUNa&DaMNcU znc3OdR6)(nTB(BEgb$lO&lkr-Li$AD+HlRxptv;u(Zo2?~eSdJ2anyqDWrhRbF6~R* z+x4scDSo#j2be7Y{JWlDo!;Hu0oc~*?#zfxy!Nxt*>CtcZ>n>$+;RHq-;4I0{{UfP z_a#gQio(C48HzASuhorgV}Gjn_GFnpM9B>&)HT_`1y&rW36M4uVF8f8Jatb~k$c?y z!r;PlI5c#zkuRKvx!d>amx$16Hy$DJG8d4Prpq!$&7`E70#DJw1JUd)pOBa~cDP$O|@Zc6LmNrfS(&?fx`4QN;Ug z7{*psPJVv+y@48VpFkGuX!Y6|GvP#3O=266QhSrvQdBd z&<D*JMnb$_nu46EsFJ^RmSA+{0N7DSM^$5MeLVpgcZ{lS z5kCxUBdRh)bJ$?JSXVa{4bFTcMltw{j{nN6xw~|}_T-&50}el-{Ok|9-SOPv-OJ5Q ze$ZN1sI%?c1z?3NTU+206RQs|%NjgPc64+sx4N&oulkmyc}oEysrC70QTVobT#x*N zQ5|>C-+EomsX5Cl0U87>!?fJo)x?R>ndi{UDg}`~Ud2K=@{2N(6iPjWX8Z+brIWU{ zw&dY$A4v=K3JT*rCDDo!&l0s@)}j%TY`(3Pl@%o{kK!$I02+DU94Y4l#Z)Yb@QD?d zhK7dCV#oEYj(SKdebvvd9~IuG?Q=gW046~ogZ!63sMVM6LPuJvtS-r5RzOa!KCeIBm{E4?I(*@=r?D)GZV+Xhq8{Esd%K^b|r-<=rO{ObtGqMk_^|*0S)LslX zRPgjqgSDHRo3XL+=}J35l&s(eEYq(mS!s8(Bz={%6OM6i)^(Fm1FF%`E<<=2c6$HG zm@nfI*5M9G` zvC(X`G=>#I3RRR5yj7P{IM=k{I}mh3QNR-2Qdo9y0$1Bm zMt(A#@iLIE&#$Hw%hw2h_fJQedb`lebxW`dEg5hK-wU}*fTOR?l?841-Kmc=h!ZuB)W4SlV*;#c*?1f zr-X*Sp$gTc)#geR!%}`UI^rA7!IG4+8^!QAnrD^ByFFgqb%j4~*pu}3eb_Hf(##R4 zu4WdIGT(IpKxl_f9Bfd$Qk61-j6|`Jt z5&o(8&!0aHwKS}&X(M|%r;f&Vy*E;EC9ETRXBjzHJjU(xqZbymOzDvNzS=>}_{9Hs zVN2b1qRk$|3me3!9?G zZIE^wVD^&d)&M#)$N%LX;!>$sxa2T#{5IBxs~p;qL%dYYCfD}6isidP1kl671Ah*# zgPU7p=rp1{_)S45#!a)cITlW%t+$^alaS^xz`^i^LJaiuj^DdieFOK{u87lB5q@Kn zu*dt#lp>>-@=1a*8wimZ+1asi20&%|HB2(k^Tu+~t@iVXSsjoEA8${E9XDV>*hry3 zjN3>z&q>eCg%22J?$mt~Plpr5cy~v4DedE>R*fg}+!;LF1(f=7Ri}44_KAca6%`e0 zKi4x1&zX~$eiZM`oZ5GxPGUt7TTa`&OqbHV$S4|BKHNU%*lx>;~ zfN}Nm@`5rnEtEJkQ)}Bb^x3;%BL6T`Xy2MY9bUN@k&LxFG~|>R735qMR=({WsQEzj zWZ55^ea_!V9kxz|C6HkDK*eYsz zo^9%wQ5yvk&(PYzTMG$%->B%gk91v?LoP~^3j~Qvf2n2FQnlL845`D7w(xTtrcN4d z3mo#@EZC?QLM-)R02$~18Zex)d?jbQb5v6?1VDWN@bB%-Pfv@-ixsPsPE4?h13a9~ zec;sSG;#FpQ4IR=Xw}kW?K~*2Z^?T@J$EW^TPNPD`ZHZhB8Ejb%f_k?SBU1r5`#95 z*eSpR?P!vTN4qu_7Z>}&Xc-t7SbQd2oxi!hZiru^MBq-|1tNRmcP34Mb9Y~I?4Rp= zxlR+JEKWX07M=UY$^9D}#)Zb}DI%z211hCUKa2oB!UY7m*;PZy$<)$9Z|U(VrRu89 z>-Bx+{|&`Be6YXon4MezVS8jqkpbe09eGMa1E;|NbT1el9v}*2~q^)y~c? zd*egnTrKeW4B!ZWZWzDaa=PE%rn;Tn%tA-OhJ!v%|YV`Nw$rh>r znCe|{4dItzN-<>}O|l{(m#ue0PfuBv8R>FvHa3q#Lq9S<&9IE*{55^5KXzYBThm*_ zMp@~E>VJqeIg@@+jl_GkH#dz4&`G;0=zX)9o=6HGsnG^rr7B4eN5z;r_vRhrXOl<=B3?+K$Hv& za=mHaA%(_bSdeRLY0;+0Bqb$D#S&RstpdU51gO5X`ROBCC(E{~jc_Gyf0$bsbYZ^J zT++#F$f>Mg0E&NZdp#?HZKwOL(91)$W-mijUwX_sS@#@zy-=VspPR!qDYKN?XB8H< z*V1@0sn!0YU7j0WR9viAJqighXtZrg$E1LpB6QGeKqAk`&DHsbSv)yB)MTEWQ3Num zYM2~%g3NHG!0XectgI~eibug*Qr|Oah{swW{7xqN4dDnkVPuJFIpGrm)(Qf)ESEfc z(jWqvu4n}Uhsg*F%Bs-=8*^hHxZRN#TRXfN({)2$ULFT2c*uHm_h->qOK9jl*Kt%) z`k&@0)&b9LH!xJCPO$A_c{zQl8eQh-JEZ#hdbLuu9}8KQMd36wZI(EpT^Jyma(}uM zjRh5Kwb&GZacA8BST!K`^aEl>SLni5>2p<>3{=7ZA%4=m4nX^&q9QnWc=hQbfMZlB z=I>(Ye3+@`YVe^FnBPjiI9jO7a^9{#)OB4C>uBfB;gh7-S3v zxL}}5^-Z&Kvp=qBswJb~{;$PLaSs0gs-5DZqUpuqtu}HpGc&V%>7r{L?no}v_fstCsPLpJkZXL8J{;N=EPvq2gMu#&&T5? zfL^SqsQB5JHd|9)|J?-{)wJWfIaN6wj(e@Pl1#f5vxmg~anhVb&4zzZ+~N!pYU=0L zII0^g#Bp_eqSj&k=CAAWG29GR1B@KH2THJP+}v8SZ@GRed>bxY>$`R)Uj+%=tpx+v z7%YlbxR9Bf`+DNuN%*AR&Tcc+(%INpw3M-#8VhV9?hsk{^XyX}smc&(q{YT(;NRk4 z`iN99WU`Knlxi3Mp317RlJ7tpu@*`Zy!tTP1kB5v9~=az&w;ke++6DLcA|sK8***H zxj@%LII+EJdODe~iRo_Y8!!D;A!b}k%8XNU;^24SS{THLYOb_~mX@?T${Gk037=h; zBdYzb%e%X~H#axIo*3_@3IBXEnCe{v>NA-lr!R8B#m5g$q31Q~>Bv#6~#QN7QR@e3dyB&HL9ZmRs1Pd=hcf52gSsHq z+tE0jZer?=`l?wL6rkaVVGNih?&A+aZAG+|!#bRnksH-XAqQH&+2F(X8?FP)Dadc|RO z*<;fE>%q;|H}z2gY5QnZr$w7Q2#7)5mQni&3)yXUrof}UemH(X@BLqiA6 zmssCSU45iNnS9)G6PHfx79K6dl5&zC^<=2>X;h*-eznKK?nElT$L1$%i zZTh+Jj3%c!dMS~dth^H9VMcgx@E~$L0wNZa&FTF*R(|boob3D`s7j}LIpq5sJS+r+Rmx`U;fRS^_ff+HS z@dBxbtv!~3YmIz5c#TI^v(x8+tx0y zW>?ex@DI)kMwn4_EDAEM%(jzJUha3f5`{{&iin8POpRV6S0PBr0v(n!(f zFzM^^+wzAas@RUiGC7C-SQNdQt~ACK6BN#ds$9foBjH8-^%9u<0WxuUtuBhl^yezy z2{70(;+MBr+@JStaqz<4vQ`!xp{Q%ZlGdq#x0<&uuNSz&r-Bp9deAnAZ4@{Y;{FdUxdWQ zl2{2>+MPUO88;u0?^hB&yFn=)GuccEqQV{oKQsl4c!v-B&47BSS3t?z;kPBo0osoaLC$4EWUTCh#Ol6$Zj&v9%OnK z*GO-2RvZjaV?I~#zwV3RwR+$XUaLr&w3B@YiRgsGJl;Zy0Qf8?oiRlwnw3oADK^@u zSq1zK;6y2dYHcYRF~adWP3kO$I0#LobTzR~!#F3p)<5j4J3Su4=~xwHOu?A|8wCQ# z7Q2xF$9*)o9tE_O~(+!jFEu!B||e;>u3;qGFh!zyX1jJ_gG;$7C8OpD6P zYzd!g9||Hx$)seI2jWJ7F6GfTO;W@Onw2Y#xGKO#kEOVe(N~3z;i?4&A&XVoBO)B< z_O9^@dCIj|vU-DTOVb<4pQS4YhnivqZ}!CL2nh02J*_QlK=l!7|EL2^=#4J5@;F~QtJZCoLPb{E(4ruBcUVxK_VI~O&Oxm< zGVB5BB9R7NP3Q*KJrb-{JO+b^QB0q@ie|==RRO>JgsalLKK7#3CuGV^*^uMJFK|Ip z1m~P@$1%EOOVv~038JJD9MIw@@N$Jr;y`eh0fJr)vs)bn; zPlaewdu6aVj7f|a)i5Rov4%yLUTEGR$DZ{-3-jsTk7Xgkj*Px2b#}=Zku2nRZ#~hG z?VwQRzfWS;$`|g%9de5_i3C%Aaug3pWW*hQ3j!e`+@KdJj-*r;chp!iA*05i{^M;J zXc$=1vW~Xus+R*e+6iw8GITvjM9?P`(5Gc@NdH$%5FX#7r_Of~5+bGR@|Imp9(R}$ zW~EM&`$j{-&WhD7dW@3af}geMl?=dj$Z(C~D9q3pwFIgtha7KJzPx$anU;*S46<*O?!$kN`Vy!vO$tw~&J zx{;milqt+?M(7-SbGy{hLF%yS(~$UV=N$<2E8)2LtHS8&&*HPQ`-b(bT3wuic1bJL zFt3r3GIj?`m^x~B&{!Z83@IWh?1JbQ)cTe^Q3zxYX&Td_k2HHI&8(H_0BEGVMIZ~e zu(VW;a}vF}zIL}l65Y)o9cot(#VJ|ghd3vl{rQF`GK!@4YJIE_yzc7N#542LU{J zphZiN{@#+Kht0A=L9`uH81AL0oYR<4j&Cd{26OT4=Y=^ahN{do!?ldZ!U>*`hCfX9 zH+t)7$p>E{O0NfjgSWk2?^g|>BJ~~*V$n?aQSfF7LWzS_`PrwY0G(M97rWe-Xm(4i zBGfecOH3WS5V&gVWlu^{P<)(R#q!Ulvw={~KFHhp$`7FdVuG|fDh6Y^jEmIfjg&fX z$rC~1gP8ciNKm`F0XOCl$XP+GNU@3~Ej=#NNRyT&Q|jsQF=i01tf^p+JXlo~gAdnM zW5q+8c#{>`iEge%Z0{A(DzrA1E;Iw>kjEf9J>y=>4)4-Y$34x3XIEal;IN6hXkw@W zOVvoq(j~-)Jejpgt^n#wWdaXYOVee85povt`lga5f}n6OqCgi9jSLCy*{K4C-`NT( zu^EKHXCxz0rvk>ZDyJl^q>xv>j`ptUAv2KvP#E68WcZU?F zKIr}q?R#^$Yigt;)f{AAX78Br%CGVRq{wl-OYPCNqO!88vNAT#eh#)p%jJKT3ZVkM z2JUH|6U^bgx_mDbnLBz}=ixMFRQMukfUI$Ot4Gh|#B@&qJ;LsuYpZ*Zq&LGk>GFkZ zSrpo&1xQVjF_LJQG^S`zgSG7g3KWRK(uGF8D(0QX<2voT*{>KUQK**nolQo&K}}t7 zqSkqwd|@qAojbwY{9w+hbB*RF(yFe93qe^09$d~E_Kt0S7B&I@axucv=l8Mm`r{oh=CHbZ|iAB zDnk1{E9#=`e~6(ZI49FH$l2D~%D3-U(Y?oO0)AnL6uRU(YO(56`=Xqyo#&W6_zVqp zZo>}}z|NeX^PG&*hktuj>KVaqJV3+!UNJhYs3g_d$Xj)f!hBCoT@!KtJ$2w?J##~l zm>5O)4nn?-t7)yt<~m1~*))f#1FT%g!Snvcd58WdFOb{#QqJ zNe?pg@$s>=v~;X}H>c=g+HnHMT_))otT^zIj60siE<{=1|9pvFDWd-aLq-_1N4iV< z8;%f3c-L+rY3XN1IuC?v4gw6SP|4IN*xzdJy%dgPNj`;@_t+0#9q*)8CK#r?LQ zHgk8>p;ixuHKE)TdWEPAne0_P#?H0@dHME9#PvNmTt;lC4i}@`fR7S5W-v{$pR_%! z?`92VAuY^GPv>>s85tTvGCBGyEp2tTH|M_sij|^a`nJzJt_RZq1C#G3=zg+Ps#=^; z$qp34PP~8~x0);N@zwzDuiPy~hEtQ6oRsgCv@C^iqDkvHq(P-axP<9GN4UZLTH_Z6 z9yHAL*AZIK^&_13Zab8bTIqwBqs-&Y?df4Xe#=ZH3Tsi=gFH$gYd8;vyP63<`oPm4 zRTLBUj*sUkVD~cT&8v7L#1d!0CLmSs6- z1Y%s?)zahJvvTTzi}2-IUtm&Mj5l-ob(+2%*PAPy>p&RZ=t7w zloZ#kSg~xdNrf*l@^~1*2VGBRRfr4RP850A0ip7$F&LXDlA4#Y?vGH=^y9J=-5u!We)<#9TMyNv@v3MzIu*pYG#&@x2kWu>sv*kJaufZj|QdYCq&P{OuOO` z(0->V#KSC${zQQKp86O&eC8P%q;Bal9Y_g41|jO>iDGeyR|HFC<_s9#XHyi$cL#8Nj|$z{1e zv%BkbT45amMu<3)hbnys$D{{farg*?dLulbd4QS)C`$-|hAk08{Zudwp@T!KebmFj zGm-YZj?t~^R+tAM#S(hGA7Ay{%|7`y?z2-DCvdThQ$~j)yHd^0&JKJWpdxo6koaOb zR?kq^+VsOFy1;6z{gD_UWfOCTFX*d+pe#L7aw^Vgt<>_W?U}YIWpYd5m@uAphCaFs zEcnB-WT^_AJRW8-!)VH%W?L*{D*=*o1SN`WK~RJ~X&QeHm-b%YyIGL2tGqV&seFDO ze_Q(Th^LJI2=)UkETJ8w$&gBZi^9OaK#yW~G4`rP$WH;9X+DoL`b6S(Art)Q={&$x z;g^ZRjQ8*q7uzi}s$59GlFPM~JPVn30S@Iv&|E>QxGB*l31#`+M;V|bt|<{ZoH@t8 zP&2fdazL1b?gtf*7n@H1SXaLZ_>kjqp_==kW_?Y>?^e;&RNUD~0s>S-#_K>+x@r05 zhYKGn2pJh!QTW;A0tu6q0f_}Bl^%Y{>*;qud&9>s-$Pkmn|^gDq=S;|@G?-7_V^$T zB#(S^ay4l7P>Kj`XTN4pK%Y4;b72u|8CYY&T3mdq(rKAIQ6DVW!z5GfEKaLe@%sLx zOL35s8B3Mq{`j-gXQ@m|mj~0k>mL}e?qGuAjJJHvRWSGF7wL5UJ}*p$ozmq_nw?t+ zH%wIc@VewiHL(q2Gm?zI&>SRS5jOnKO9dD+NF4T0qwN&OQni#8Ko1H2|2#fk1c^!VucT~k_BY??}<~Qd*MG^<__u3F~z`j z-jgVc!c6`6pb!!FQ&MUbxw^CiJ7gf+S_U0f8r8%-q-jwc1;qxBoxAZhTN2^?$mYkp z+wYM>keE@DFD8!cx=wApYI;dqGz6vrU(QQsp8F3ehI*{lIRzH76N#M<0SWD5t#51m zx{)A{$?jNgZdw`$HKt069QwHnnOWEGej7O0(Ej=YKRY`+-3J2?97nj7rB%%0Sx`XF z_pnvK-jrEJ1ColLjm=_D&-cj7O0L+rxY4mO{h#q1Dr6c-9x$+z=J)o4 zft0kM1_4^vh>UW|mKE~j!c9gN%Ze2`8hwxWfr*+S%>tA6+~1@gEnFD83}}+v213|A zH7OK`wG5OcQFQlySTmh;g|moGr1~(#g4fudv#qI!hR=t)9(bCMaiP#s3+CggjJb)c zVyRD^|M~p=np=|Rw(HxU*j-QQEa-KWwb6(;ayJ33Zc+%IK&7a<%x6s_dBsBG$<|^z z&ettK+O*gt{4j5#+_4{Kr0afH1Jvf3(1?gvrGQuyP`~Kdc}fF)5eE9q(TpNQP&g0I z=d|o&5tS607$?;~+i6`oVlc}ekNz|aKVCz?VsrZ5m4LEpt}1&Fk>hUm#ERuLW2EV% z+?|Rf?BFwz1(~Vb zmk*1L1<_MF=%hg_}PKWzDKB?biM`#!=s<9v;%%HtJ4C} zqz(gpDnK>Q4QQnREl46Is}W0>p3=KxzZ>A}pJS(&@K>DJk7|dh2sxfRcQM@Wuk8@S zHUX*p<{FjCl>ZQgyuD_rriN zqtmy81>KjmcfZQEJ`L4)k@g7?rHHnk2x-4-50T~X8eLeI!nG(QTkY-RvTTsxQq$a4|E*1YzvheECr zFw%!v2%}@3US9#k@uvCxcei0IQxa6$q!c?5&Gu)T;w1U+7eandfM&BFXgULUdTA*u z`7H=g1+1Mcx5g1k_khKut&*(`YaG-DDMPUuJG1~vOfhhD1UNgeSo+1tXnnsp7w90R zr~PyQq=4MEGR?YvfS9JguMv=jaHl7-;H}fa8pVbw;}<<&-+lAQhvTxeNG@ZE@5)er zBqgKGL?;X<*nC5xh=TqC86cHkL*#!)>urvbox@#z7_Nq9K>*Rk>#*AyC3ZlPv$MIm zh9g9?mCs+V<%gZDc9X)6l^+ssi17rDhPr)~DP&`3-}F<*k?93@K5e&N2iTziJf*q=B2!)ahL%di~@ zg6#Ft7lB1Elgr^iW+qxuZ7g|A3%Kv+dj0^^Mc77B28krO`m}_2wEUmPq;Vbs2BHe~ zpRzSR7NH$_K5eT_!y2N~UD{yi#0EDht>gl$OFQ>lBu1juT(q`SPheF8=RmRm zX-Eue&qAHK|9-09J+M-UOM$~0#(F*DrXd*u04F$y$B11qmRZJq^*~%Il&sS ztNYh4e0Ln7FBqxQ1Y&g-bI>N9#d!Jf6aE}V5#1C7lHs&?>E?VwudcSO{tB6&Qhg`Z zzSP{l%w*#Q%Kbr%qieId5;ruAq&U3NR5|ATF+jP9cwtk(JnrUe`+Euvrr2tEA!_}@ z$36TN(m}T#Wy7WP(=oHV0sdiQ!)6pM7n7DK@SM|fS7=~6sGK5%?4TnGI`u=T@Twvh zg~5zp981U`u;ik{pnz{_nn?%!++^Nnkn)XnMWaLw3JLVjHyh#WYJ%pC@FH(&wMQKwL= zL91v?BwRQSjZbq2709!=(=Ppp+D|9Z>bJcmPs|8tU#a6)I6_vSqGN9{sgKW!;o};l zgZqi!9t5pQ99oHv7fZ6m!+t2d&18o(7|wTazpFHmIo9~KVTzHq#*$=E9ML!Ap3kx5 z-7P@?Zto6}s)14n%*L_g7|2dCRP*KFFTFLw{UvL+a?9_Jp(w^&Re7tTYUg2T(Vd`a zDmpVMKdLP!$Vhq>9l5Va9LSV11Z;L&+lFWG$o9py({>`CH(wB%!bbX&98Uj*a9EN5eal=OOe5q!|v)_whsCeX}tZv++kz9${<R$X$e7^2Xe)`Ez8<=>j4o@Y<1vC>Ym#bQowV~`) zIv7+akUb~eWO($`VN?T>wp{N=xI-q(Q(S4t;^LH_rc<+zfk9`yXfD!d{(tx{2knUz zLyuJ|$PQ6dlxWU#7}2vzyE|`{t9EP+PW2SfOHS&%3yZ^6(N(cMc_s=}uI1+%-d&MLfQ@FXU-y zB{QY`2l|=(iNRd20{NJo`EX*dq;e4nYw-lBy$?mfq21T0M(@PwIYbpeD5}WfL}K4R z!E`fOt@dI$OPGWNkg0qRB&3{lct?Q8tp`T!k1JCQSE-b#ghCOZ%R8v`YKdIKM0SkN~$RP4)B8zb(gZD zus0fUu|&~CuhF6A2F~VP95K0`j7o#0HYS)n{^}3CNZ=Bbs>8K0dfC@3ZvWlovpp?=bWGk-mcD2Wui{) zKaZJmEt+3Y6<$SKFh?8PuBSWCQ`h@NQMW)wqsn_^cbzKJ3K+$QXJ`iV9uK=E>q;SU zZPARl7pn6KDw_mv6?Heq-0^D$^AVE?BYKJD6U;2A9hV;@CIe0|EN$|BG}}(1!5gfVb9ueoap4`Krg5OiI} zO+zb%mNaFueCo%v+~Jigiz!A?9C$nXI&h!=U|~%|(a>wejFD&d?It$J{B=IziY!vS zUnvQ7XLkMxEkeF+bO6kq$RTF3LWG~e%mqy>s)o|R6+K#`(AG>fN#sYvkRKQ>Bw3Qz zW^`KO9JYsyg@xOwRCE$%G{@1%0-Vb)VDzv>U$pnnd`y3P5t}zenh~t}1y%V)pKXFk z8E!wLm%SnwTiwz38LF?t=o{)}jQk{&A|E~{Jhm`)jJZbNnB8}+mReeY z-}v*%DGwV3(h}mC(Y#}rH7&$CNB0^WT<~!<4QZqDbR42Nl6mTrM2jc?i?Fv0YODRi zeuEYYlmLYy#jUs&w*tkjIECU;ybvf(&_F5fTA;XVf#4K(cXyZKo_9b0IUmlv=fjy{ zhD-u8$$fgvh0Opa2B6pzeFY@_jMDjwyqJ~Oht>Df1-DoU3R3MudW%Kn z;EN-6AMyxZxfd&6Xr}cd%(^;OvPfJVj#h@|RP;#t&gim~$ zYV^ODo0ryz@)5a9P<4JMzj0nR&8<%oL)37heQbH`+I1k-UOB8JmdPR1b=A-LI`B&f zQ?k$3-TQDXe%2p*Yr2WvbD`|i;?Mh{Ryg{8A=PlzI+~OU-l*e%S5YfEiKppZB#n9e z-5rT9|xuQGrC#BEZ#y4|= z77Z~1sq!I1zJ>R2(wUrA4sL-#*J*VWZUUOdkmO%~Tz z%p;kJ`P6f9qw=_#qvp1U#L@-mR=ZHUQzcC4TYI-eviq) zakvvaJ}!A6rCDz{A1JvZDZ&dY$n<5t7Ap4*tv~iKIQji^_T{XNEA|4#CkY7{o@wkQ z-d~|789CH?0VAoxdd04gDMW>1Njo{Y$vbnYVM?-u<;qA{!e+USjfc#*B#mDkXRm5%KPqZ`{$$jZh&Aw% zRCB61g+xd(HQT}rV#km?Tr{>9UJCy*(cGE@_~O1x(+Nl9ClS&77o7t9A3Yx@w+#az zq+&A~8gXn>?}Zx6wte2$fyU$)$dks(KUZJlqSbiFPE$^iO&tx4)HMW+8ZwZZzPgD8 z?H|TQJ$aFS8yYkWcEXM*7Zs5R9m!Sc2dTZ;Yy3nCY10xcoH-+UWj`gA{B)T_6HLtB zWFt||LSH4*o*v-9VXxz?l)kEaSF`eM z0=tYjP0C|Kh$M}px)kn|V;{5Qx-mMSf=QYIvtJCa`e_={%Dby6jA!G5y;s#g(?{GB zT;}I_kSMo?XY8d_@bUa)Exd_t#cFV;Ak#&pC3UZ#SD&0XDoY3WUVR+uYjNr zqsr3FRb%1CqA8|u(46mNOyZFP)$lMg?}imGiS?`cFh{Y8x1-6k>(aAF9#6)L-+?yk zyJN$EoHEQ>nSym(eQe)Or{-h!_OW;6OuLz+S~qChq174adJRog<)6B9>4U6QkS(n* zziEf@%SlO(#rjpInj|3e_2&j&E>V(x^kEUb8CHC-YoU`MYc+d4H0XdC=|wYvy<9x@ z)o5m^JJ&;$9n9uw*vs-n6LFj;SO9Q-T(C{x87<8OMRk#~Rw>t-gf#AQYOOPvrNs(` z%4xOYq57{=@;xuOJrfh<1YJ2bjY7Ys2^Q~Vi8W!S)lQ}y^nvJbXUnq3=PhVV)&%8p z$3pYE-!Q^tbfR~*7Q%Pvm5(I|_R9F{{zD46fT&MzQ6ep|{*M)W^r`bpRZPCj)ILHvUJI7 zsv$SFBbkplacm)26u$>%7js2P(Upo%sEk-O3E$Dui8)2f&rW{L?9IvC3W-osQ!I07 zsdku?JU+z9>7(yEF3qm;Jq%(P<`Oqv;tb-@#?il=O)FGsQTqB-+SG?_%#g2COcv+~ z6yu)goT`$hpud)i zWR4NGY)ON-xVXC)9yDLC8d_OzGCU&rjhF48Ia-E7OrJBlnw``OD z_=`SNL591KTk>fUd4E#schARFa_CNmBhb?S47wd?F?#AMXdC;sfY^I#`v-4obzeon zEvYy~sJ31Di{Ck}AS3Shp{`%QzOzV$-Wwq{=66R6BcM;a(94>(bFr&Cm~DB(MMMQ+ z6neiJkU%NuvTbX471o1#f8Pnp!n|bg6N-3m{fZJcmr3xIXMvl?jZf2qN3O3Hh(pw2 zd!hRQR(9YA*k*&qj+{Jhj#YTOfAQ~cIUqAivaQdtw!;jaz)1xQ7s3*vO&>906x5P6 zOgKZe@ELHBxFcMjFjTQLR6~~+i%UOhT)z$t%f_Qf>cr8O#EYW%)MHuCsKVo_5&|ae zpv7K&9_fVMjH`m$GriaNHS+Id5p9TP#nU@nAQVFR`~ZDi;Ro0{E|-~N*Bp*d9jB@V z>QN&1h2Y=1%tf(0H8oA&PrMJ)R@}E>hf|Rn5G>GHKlG`dXZcH7jV`nK(nLEIzgNmoBDzX2`?dcI5fn3DPUFFU&A zdINo^5W8GA@*Ev~91cM|FN@!e056Cm))0@wMi2DVU5<$7%*Xy0zP8pLcbEG-_oPb( zCBW%Py{rQ0k$IM_?zwtWW;JF~n6-yYbDHwQzxc8K(pIW(a!cdbK-lt$wHbp23HiEn zsl${sT0WD$W48X?%R2m)1YaB-7`lOIfx8G4$pX%}-~^Y4P@UF6s1n;NajOPLHNZ|xyh_Vdif^Q&zVdjl}qz&Ofs+A3|3`K3Y@y)I6g)10oUehml-)`ZPIOHrjMOK zgJ^MX&yHlMD1#*Waa1u9_*7ue7dO`WoY4UtI?{x?E=-j=PGiD}Y4{pwc=HO<)B6p8iph|64&o<JrIse zue(*AhK57_j@^~Ck>u=396ao^X|VZ$_NYpUv)W+opFmV7=AT&F|I8WySC-r7MZ^2p z+2(@;^)MjIWaK)X;P}u{&lw4vsQjxgIo8R3w=deBY=LV%I>@|G;d5QWusQG_X-gHw zk~E$h{fusQlx;u~3D=;GBWc(Z<+P%-oCqC#YM1es&~>%Gk>}!|;r*Y7*73!~hrm?? z11LEq#p9-F1xaF5%xi;?qwVQWg~yc}rPt$Gwv>*c(>G7g`#v20cjI+E_a?5c_TJuh zi047@cy*bJki{Y&9w3qM!HF7@ByP2`OqYTZ3fo>!?VlR*fSvK~+%65zr}L*W;~>08 z=a@zxkXcl-?)%Wj>hV1|?i$e8nk7pqF;?GG)CZZ)4IFVK8V4V-zM>EzzSlFmFvS`z zQpx>2{y{A^c*bfsYfsHh#eYu1ZY{zZ&+_=yumOHw(!`v=mn8Zo_OL%Jl^FeMx^8`Y zMd{6nf9}7zQ*7$_gtmP4Pu(Xajrt>mc;rC~5 zP}e6TpS{lAg166?`yAdMeHtEGUw}Ya+Wn``>zPRHqDD{5U5VeHMRC zZ0dF;dF+u|#ktQ8@f_O z{sEG<5Y8|>M7D`|V__LN=r>meWvKT8@NhD{-`3|DV|YNY z@NLf*&OT2|O8iS$`V5ocjpDtNx4#pwn+`wPL{V$2<72?^oZl1}OTTh6y5!XxcEWJ| zBx`;aL)9$l*enwCx!UC=wpH?DqjJuK&S}%A1>ka)U(c&LY)|e)9VW{i{>nFDU}}Ha zh{1!;y@NyK_*UHa5eWF6Aj}j1`;%Ky!c7g9a%vN5|1R&{)^|(*Ah}1(5apvU#}p(z zsl>&L%`+{`*=SbJ#hFM+jQkrWXmZ%cEB&Gvf)!+ChIB@3I^NblZ+Ke%#vxrsl?Bh7 z^oj3qtt^J>H`bL>%Yo-!g!o#%2sRuGA2l$F$|DL%w9X2VBVQ?Sw7#1?+{TP`!r^fRDu>AR|QVqWg;)g{{6Ss6vJ_bwTv zcjMuKLwTqcB`4{sXLs^PSVss4>6xq_!wz4XH90?_Iph<>SQjn}d^ul8mX|`V;SFkd zrsr4DkXw8m_lK@{d`z0nA2p(MMe9?*X%A%vyoW5Z(^c$Jzv>Spx~E%8#4J)+RG*ti zim{eNIVB}6EP32M+@q!fCruJ1tEvc3GAq;fo=KFQl+BMv+E@}pV(YD(0xB{cI+eT% z1=M8+-b=#I{S>@1{>7)$Z2mbQMq(4GV~PGCjWN@RoXhTOBCN}t)WAWBcp|k)Ykaa2 z!?VM0#$P7KOmTLhgo5?rb)qYuU08V6E}_2{1)1ESnjWX4((u9TGIpy+Z^{x^6*oMe&eO^+1-ZMheoMrdjI2OK^McIq>gdOAru&Zc-H%7oZ~Vpv%gBKN^WT>chn@5-LvM0+CDv?ecW5ly3}A z{Id6NVtTI}Q!*T^SRf_9g@*AV-gsdd&(wxYAl#ITtsI3qZ1PaawPd#T~whadLh;nA#^7c6)rze7?DP zIv<6Mgzio4^CVHujS99M&*%q%SA8!39ae}xJ^&j;x6_3?;QHQlBYvhPmPtlJ!G)dk zABm?tHNPYJ>gI+T(0|(==U+gdl6)O}eb-S=9|&op)x*QF5hoQ08k!Zvn$*7LJ?s#d zV7z8Dqrq-<1#xZ#73Af;ZEAb|nGRX3L#ixbL}acYLfRe<+b}?YVJfa4{0Xqjr>Ea9 z8zH)Z>fvgZ+;{nW;9$Ws| zWms3Il4Z@Am2GQ|RcKAoL*)tv~3VU+2#qR=qr<{I%ewD--A)9+e4g#rLLx3IQjJ~1s{bdRu{VOuD z4K6fUsS0IKP>?(qL_H5G8aYqK9O43=fHyCLo##EWgrLuV`_8@rawtH<@_$OgdG+dZ z!oUSbIw|oUbgL<AVU7kV3^!Ps{6bl!uUz5Tv!F)f=x0_-0;(_uX;myP!(epIm%gT$rHV zOdkhx_uCj*O0RiE$CTt`@7tJDfSCq>kZ3apabFQR!wrNoTAv%6ZQN!f$yG(4E)#SN zs(=7|ZS&G(+zUU+>~`X`)Kp|YVE?QM_*DQu#OSv3&!37pw6t)85nd&bfX@!Al!$Yu zYl@PktE(1fb3v+i6Xd?{kjo%ENw*D%8!x zK~mQOgdDAPJtP8k#fX?b_;Eo>iZM?~_nsL9p<*ow>kj|qZ>IMZYAQK^9{3lA9(r{( z8NoRmKy7Vn7F_sDv#|+Vrf7T0kad9Hb*qZG+If4I>ar#(&{GH5F9IQBMpZFHB0u!> zXz7usHxmew0Gp|D-30N+Wdthd1(3_wIht3<`(2$U@^DmhfrUj&+bMn4POF-$&NNu9 zqpib|_`cPi3`uKXdwTjkA&yX7Kh?&HXj7)=!CYDWlHGrCdw?dXRtEBmuWhW39o&u- ze>eiL7^jGt3em?s0ssjIpn-s>DQHh7LCod&y}ANwEh|f0zb5lcoqf)>GYOFG`;}>= ztEVUUd;|gBG3eXLXG5$g?K>v;HUt#zn?X**P9^#4#&L31D!lb*T5h>J)JpepzZ!b+?A;U ze?5EHwxE$wfwvkxNmowlVNqt~Q64?oBO4l<2Xe`}t{N z&70d5-`hlhMz$#Y^5bco3Guw$3@0{7t$xB-k~`vOaKfK+U{&w?elbjih*u;ix{i;7 z1Rvtf5bTZ2#2P|0ltZY7{*F;+?_UDrCf%qKl0W1%;+N$>$DzAJFXt)1jc6x5syX zPQfSfi$|qH%C6<~urX2SrCe7N{R#ph9K*9;V5S|6D7WYjc=p&7GygW<#748-tD9T7PM{d1v@^ky|L{7 z0J+Z(r{d7oxG1bp0d8*7)O$l1aQ4-JF}zSw%n~du2vLylYdw#rI^0$ zl=kZ*Mxj#6Up-L#04u!Z)k0CAitb3EGv13i)Ia^&z(nY!K_q+sC$&F+2r@2#d`VP#+Bd4JT8~|CVoI5{vW=}HG z*I(wIl?EQ@=~4eCic|y=-64tJRQRv9_^8I*Ry?fu4!gE1SqJNYTD4n{AA55~-%-@# ze5=0g=~%@zPwk!iJS0yYPx3X8`>xV0(v*>rc^Uk7$>6r+H?6GWwf(rkov8#e2u!81 zfJ7H9UDyi#9q%w=6B5R49wZSJ70~FY&|kzwG)DR~DFw_V;`X^M0C6df{dxXf6xf~w(Ujb-5DJdzOJMF3lJ`s^-3k(+^a&mZ> zncC>rmnzEcwpuRQ7zAl7V&spM00Os2&(yVArs|(h1N+iXu1(_vY}?K zq$b?BRJdL^+mkqbE?>+4c{0gSrM~F7*ax>LyryXcdZNy;T}fd)`23bbpXgKnaMe>r z-Tfv@=J#Va>%=FQtkMIKUWBot5zTqU&;FBtHpeUzq=>{7@xU977ZF|C?gUCkV}OiD_MqqHC6 zK3**RTCeWbu=xIsBTgb4&PX)1Y(5P&Ck#ZFz<{)@hKY*74n_aifF~G$Dp{%^5gkg$ ztugo8REt{#MS3s!2L_3hG>9(#?GGn(I-Su>U7-uR?!@^O|D`kc(KGiR>PfZjN!QTr z$zO8crm37l*GS=MK;b*+aCqk;$JyH8veC+%bNak>sD9z1Yb(M_bwa1uO3Q$U%0f%E&w3vWVg|o+@ai5`w z7-RroNXs|rXjXh5jyskM#2%2hnf4DPihUD7{#1<{ZIS^dNexiCj%h)aP*hqG)u`yj z-oR2&<={Z{QAo5pTm>#SEAr|9M+fR#=}>u zT<5q1E6mX6f>kt-_|4?0XYbKjVoPbEALb(HQJ z=X#Olti1OIYc5(bvyvS2O0U0+M6k?${wio>Ab9inMn{`7`$nNqL`8uStad6DRZpNgg+y;_UbEZi?Q9yRyGt5l&Zp}g~Iik61jE)W9i0~4e4 zNGO0%19Nhk(bq7p5B?5q3_W70lBU-zweMYL?Ek$sK!E+Fdy1>={R9q+y>c#OuD@AO zR2vq5;*fr&h>9^TuWrL&_4l5%dBSP+&u1eOX;@M;EAtP>pG7YB^!(%&;h5B|r#KZ- zFrSu|@G3V%mvCsIE;Hb;e0tbzRnsXNH5-Do{|{=9{aHjTM&>WnKyc~l6v-z^*69sJQT@>u1k{Cb?~`BY+*?c%a}(WqkuG}(WA z(bb)+vkxNciTw93CT9J|kN)-Sjw<^_0BZCM6v*>Xc9W%)e3PnQd8rZ*!Wri?^05}_s z#g-h$)SUyH+;$N`lo|9LS4oCpq-2Xl>&b7iR090GFgfWi;vAbLE2bFDTH%ikB-~qm z67OP=}-WNYwARl z?2wm?_{=mn8su^1bFLs}I>F9|ifrI9_K#WLz;Ho~&vKqmGgxbqhbKbxqX-TFCt#~! zrTuL}3=mRkAQvf0o*ou}PD3v~4@C3{OC(Wgi>3w!Y*fW?L3!%(SG}CKkKP2IIY94# z`WFjpbJGkU<46Stt5<2VCTK9#{IT^9rRxWXD7*r?tb~j3QtjE9bGQLRnxNP9<6fT} z)_akwOP*QsM(u6wp`B_14UK(G=D1DkGM{-eO_r9T^%)wzT$!P*!_xrLplwyq? zH<3XrmOxk#=C9B28rVtz$p4Yu3u!=718$CGN7+oce}}o@@|zN?0MXIWb22U7d?Ql$ zqybkEWhihvPC^4kbgZnKr8{>A7On$88yP zYt;kgn3N^dXsop)6qx9#UJ_OZQk!9fs_Y3cPQ6GN{LXB_*`pLkAdhS+7Z8eM6;7lg zD*CjvDQ$lJim1o!CMtaQ{^bzohkf2;f=sFI1}T#G2kucK@f4V+See}@lF&&a2t(~a zD97EeK;!IL)iu@f^yIZ=q{9LG<1X}WmRv+p3^Mx$X|3d}tdi%QOSt5>*`(HqdB_c= z_%l>kcTx8F-{wK*I9a)EN-#?MZktQg&0#%-9sR+0J*DsEVwA|i)Y+KZREVRZa6`20IFvT+ZbkwwyNr=wnA=oU0q{c-NI)Y z!qe8}ANg|^3>iyu$ZUDd07cX2=|G342cVpgt={(hk34h-WE4zxPF>Qqh>&;St9M5+P{G~>Q^m&GI5ET?Sb4Nv&gpoHTvBGcTN9S(+B{eE^e|z3N;zX1+}? zRo@bqP6ygsDhNp>RV}wvJ*d(GLBn4J+}7c^v>r z1UHD};sfB;04)YUNy8D(D(a)a0Rv)f0KVyehIF)^WU_z-&TzofE-p@4dz(Ge?@16E-lxny2}e^izu3kDzaVPVnh~ZLr|3 zx&Sg3p-yD>y+oJ?7NZ}p8=48WKZ!w}^{0Azrd-7ygLz&gYUEudd@3~ykDW^m4G;kN zY(HUns6XzzB*G@_4fJrxW;K4DNHHv9K4e|sdZrs}yER8fo?|$QM>h$kqIu0qU``EW zm{*Rk)MEUE15~u8vnUQ)*~@IThyjN8<$1TL5R@N9%w`4RZPrD+o^UHB%dRkv(p>H#)(XiCwhkRS}=*3v>M{A*>(t8D0qRVdQx+Y(B9PiC?6Qz7=x$ z3V=n6G!?8>0VHAT)3KxMHm@~_Gyrnac=sCMd$lyW)7T^r2#3A!s&C2+4EE9IEpae= zm96k<`85@Dc0ECwih?>>s2|X{R##AGO)cDMR*;a`3*yrjmZRBrEObcO`v*w~mCO1| zCG=2C8J`C4XmFN&J+Twcr1Nov1Qa*1k1uPCEdh=OftZ|jw#*9;PbN0o{uR<4>Zq5&gq?VKIYBO>LppFBvEGZrWk}vR&J^z?f;2IlBxP z@kA~6n(*XbFD3NxUoU?azcepDzZJ0zUz*mr?P48JpAHV-L`0y{C^&cFNOyt#)D)1T zZKe|gig&d7lRr@XSn8!IMb}1=jzulxE(UY0GF$=4I?dBK-UpOJ;t_Lfkz$f2Nr=HC_7tu zcY6tU_@s&IF3jz)$7mtXWUxqi?^(zxB%x$8E;D`?X$$QX6-Z9vVQDCfvec=JE|@2L zdzu8X4F@qKeye?>baJ+N_a4NR=TL%5wp>ZwIZhFsDQ=#x@Ewh_>-tg+R-%O>QwV!gBWEkitiEwR ziL0tiv@OBtVs}FSd@zOK`fqcpK+Rv_m(|9W470+uW%Zn>S&wYFZn8$Nx|toLsl7>Q zwh}elDw_0uzKxT>9TSSO>D_m3NJ)7=T~x_Z)OwXdI8=~j+UcfJL;iGjJlT-5s#n^2 zg}lg*5jXhFljManZ&eWJ9i1lH*Kc+K+v*_H8e6q0CkH|-xHPp>>h{38KWpc2H1+qc zgz_K$qB9Ku?@baUA3H%rgq$)L@h0$4@{Nnwg~zNt{cNWqYT2E(17~B5gsq)=JhLQ5 z8bnGjmV}01sV7>V&fG>2U9BS{C7MotLDIRWviLrMJDDAqM8jG!-f5nRDOZz-n#rFl zmI~e>AIt3z3B>b{?@G4iQ)iAU<|OOr_m*$R84owyNDxuvURzx6>u~>Px%(CN#^D7n^ zb=}_vlGfR;*KW%sJT{2A9rWwytQP|ybtVjZ0NIa))BRCGZN;D>V38qDw2KsCXEOlD1C3Pj`sOd04+&BzD z64E{CcDm}pKeQ|G#?w^7xkjoE9$&2GY83fKt7Ck_sD3RegsGRFJSiPZhgV{8hmz2b z7E0_#M^jWwhObE>4I6+*lMRR{t1F-zlcw{)FSWpt|j9gmRNpSK}bn0Ux{7&&JsZmsN@!(F4dQEgYl*^4h8yr63%v)!j& z%hNBQM=w^VVhAecJy-roIbKs()(p3tY;)LV$I%9&tRi4Khg!%j))xUq&o+YhOYy$g zqVgYnGRX@tc9h9TncF}iA=I;=RSbJ#_<#e&AHj|7?cfCuCpNPzc3Vyg~3q#kDXBb*By z(7yI=mgtQt8^6rQ&+IkFA{ zfROQUeWGVzpj0qHc`r_hXm@;6U{CUzU5sd5`85v*u+zPQM!LF>dj(=oapKq4rbV}L z0LZQ*y93zNjID|b3QjN1KJ>X!iUNuWFqmrfDM#FEo4j6YAi)R`oau44xau)}HG6e= z2}mB9f?g->&x4_ToZ&zv`pf$n`qbI$yS^;$ba1&(zSxU6=tSIxv|VIkcM5o%-z7{> zKR>tj7wxxreYfICF}j0idY<>2=@>Y{!5c^L3&i)?WzZR|V(8f;R>45R zz{+xy;`RjL3*5hLkB6gehrO1TRp65ko9F6NRKo4qBFb*nf@W-b0E+~v! zeM%pyU3#}|XcpV}%5(b)svIPtj&{&>03C2`vgDSaqYqkaPtqPvWzGT9o{h~JyV$5S z;r!yq?u+W29&m|56z3NF`919WlL_YspS9y)Q(pgaa-`xVU11=S0H8HaM^Etqee0H8GNFP8w)IXVo=M+%goI`n zox4YlCffSjB6=WCPjY;qJyq{`*oMA0GkCF3>(=I|@vqy!~$h4%LjF zto(tPyU*?w?KUviO67ZcXXmyCSnFTD=r?VwZ4(g0fdKIB-En<}AOsx*)H_E8;&cuWj1B@ysY0);JrXK;|2ZfzAamy0bI z_dbRISHNKwBZt(TFGi2&X>F%o3VF^0yg=3;DT`B=n4BCS<-zxRaz--*oGyMk8WDD?pex|_#ei|F z&h3W1Ma~#`<>=RX)zuW6NKD%uAKlhKa_KtJPdgEv$i0x)v3+ZOV7wTNP&zYgBV)};CU8cZW3zcSOko`=kx%IJcPLEX;5)SQt^z}0-< zAfT3Ik4v%_0WX9~eYvqA^M?ATN>v~T7*(HvW~!2p7(doTXd<10)rQCcRYSbu)E&sikAUB`oZ9a7l9Fk+;0KSku_}{rU)Q zTi$p+mTjAENG{?I^iGzWY{KvA^c|7>GCg(|IsR!OAFB3)abzUIKS6s;Gq5{{3pJlQ zF?>RevXQvBW20eJgg7#q8W|JDwcNLVWb*9gF;OL>C;FU5h|SWgTn2_LxzWw`HN$uu zIA5!W1h0H`Cv0D?KyT%(VqzOhzX0aF5bl;!6A=*wfj#s2LD+&)X#nhaC!9+i9S4R_ zY&OJ;)47IjH4qUM%>@h=F3iUuq2Z)au$oX;7-U#9j8g|A?JjXnT6gZqP-yzSqGBr9 zKt;w!#v_jbTz?8QuVcB;CF-KXk)$H~h>@hIEv8QlAY~dic$(Z++t9xFaMTY)zx`t> zgI+fD#vkb7%f(V*PsU5q2vrp-Pp$#GqTC>tfl4%4X_&F1Ub${K&j|5uIN8#gl0pZ# zOg-i%7ko(Iq!Tim;?&K+*MUu>hinsoGDiy}RFHbU&K zGKf_8?)#j&i6eGS5%T8*+^uA%PgkodGxw)R?OxFPUh!LgC}O0(Wt)}~u{GLyAxm+0 zk^?&X+4k>w?2FjlJcsXjjnNdAb8AyfUfCIzDg(L=uy!w#D0aV3X`ra@>N) zNVAsw<}Lhx87t5z&{GK|SaQ6Q(pJbO$I={IJ%EX04)=xsm%{$Mp=1*+3drha?>m+O zO279yRpi?iL9vIdG;|U98`7D&gb(e-cEor%fpK)woB}AEd33P8XhC)sbid>L*L2dF ze=#Mt(g~u~H{}VdRP5=bQT1Z>UBbB7e-Ows<(`KW&G~7{SQ59>BS|qxU{JqyWTcUg zC0IygD@tYbi+0i;jt`x7`SDKew|OXCkS2r4i0<^d44N{14{>a5E)MfgtZcfC@RD%z zuqd8g2bp|pusoBRTt|#zY%GS_w0wGYii)@!;tg1@5$f(e+j<0Oh3yy(C&KR;2OA$~ z(4DCTW)3kPG{)2-sPlMvXVCT(ZZ;uBbiB-r+RSElS|&}f2C7D)f3r)T8rf>PhK2we z3Hi4|_kj6CMa%I{wxmDA`!J)TKX;Px7j(V-*#~H}E%FK3Eb{R;Sf{RDgz1YzMrVyY zCx4!BD(lao^E2e$KYu?W>id}Vz zpILTt0(T4uJiVpyY*YL^2k~$!#w{Rl+v2t&C?L>KS;@)Gy+KiJlKPh@)Bw1)B=d7y z@>7esWYkGG+SrBd+Zy{dUW^F4ovxH&L|W)|n||u2#_ntYMjS;^h%WS(=R&+zF5b-h z%otbnM*&Q4O(u7KpT$bN@JTipC z6rNuUBt#W0twf^E^I}hO;>6LKrC-#haAQxZ&Df1#Pp+Z!1CuMTCFBYwisDm-zfCGx zO)yE*0RtUP^8lbeOQOYMVzjy(wc<9nphpKLNM6BYQC%)pS{+$VnlKebPGPXxZn4^) z+D?B?5`#J~zFOg4Ug#uLT4JxSsANHjG5IZ0w1SVMg0Y;IxEx5GHqVA2AvRu8;nU}2 z!GCj7y{-2tAXbL5yrWy5F)@(b^b1H*4mCby8kw7qXAh%H2pvj!%pQZVI0@re4Kg@z_ zguWkejY)&+l9SVc#dje3%R03;QXH6|2@EOK`=W2C_bCGy@v@nYGJZS92TC>4l`GId zw*m$r0mBW_v$dE;hevr`4=5Q>k1B;dTI zwaKe->P)h$6q_B3{*nR5JRAa8lo|*0qj+8qa0g(C;Zf` zWi?4f--UG~E8wu_#!H~@21(${DIn9u#)9#J~7I6z0BS*Ih6q>)94#uhUm9HP1~ki`(7P4Sg_v`bM}N%)99Q7 zHIB*Ob}qYjq-CZP*~Z!)H<*S7(zSu#C$REV*rB1x zaxRUW9E#SFYSk~__{q)2EYKA52RDN)1(NUO!z$puecb1O;(#1PT(+g6#Ghix%2Sem z`8+RmF`hP(fhl};P^oe?@+*qnnzu)q+OCHolQkUh=hXiF`M6yMZ=Jo2ipD1mH=mTy zmFFFP-%A3-OG!BsT1@H2{T|?Oh5YAVXLj>hztH@nMD@35lB2NuOcuJ;D|SB)MFka^ zf{~ajZ1fvr_A%14vbNaYs=uV#r%OdD)V=m>`vJ^?A}1xa>8lUx{sZVmY*JZ}|KKKw zsVOw+ng1!I|JjEol||t(sGfjQau67Q-t~hZyb4%1#kS|b=FStC-&q0QAq7cv{WshZ zn0|MnILA1CI;T$w_P_VZ6wPBnvX{gHs3L&<$(CASlILSt)Vm zV3JMdVseT1sWR_t>P^1Ia--$5(FH_U4sgn0m}mjL-$`D2{|+3U?hYlrgqKJd)G_|{ zSR)yzYmykT(o{%qO==I=Hj{W_)GD&oa!*xaR^_)~&ngZZ_X zf8w# zOz2~XaNF(!kTRw4I;#3l=C-ul30b}VKFP~A$gQ!HGHC^f*+0y))u;kaA6ogL_mc?p zSTKn{fN>fJRcg)ANXT!AO$#9N$oCO%N^GH49)w4*l6IT^1BTw<{N(BZ#-}I#*sp7B z6%`TC?_wmZG(1mD-9bYVTH!qNx2o z-{1Sk`+FV!b~y4px$f(}uJb%U6OtExk9^(SHAWn3W7?jvrR$ciP<-eK1m&a#mld&5 z!;=NX-`V}vr@-EwjfLUCPAGq_8e-Y&B0yC&iiUT{dhuMtDAU0`hhvLu*rF*ToJxw` zyI~7%sA^`2?LxvZBj$#=Ahpo7nRDjn`Mp_z3R-gPHXJyI8#<>%yYk< zQ|kx0SXoTMW_mNeecj&09#FXkLSzwQgh(9Y2l{HWy>%iXEU$?aFCHP9dP}32_3heW zr2(2)d=m*-q%QW7#grOoP)CABbP`1|68N&=(CipbJ}8BNI-RJO`wdvXuNq;sm$p-c zT0lcRHi-{HFsc^9#IxVc(X4n5?GnKiwGbIui4T++kt4|l^dO3S38AsrrqYCN7zoKL zp58T(b1u}ux)JRq0v(o-8wJtEYVgUDbS)wc*qC?-grdla#`1~AU*k~dSNXeQEq1$$ z|Ayam8gOZzhcurJmwx80mztOltjyLJ!9YzpUuD}ziY^blZr{t>eI0sve21&Ugfn1j z?q8Mv+)BvhhF)kspD3ROcK+b-iTVu0Mr#Iped+3agwwmi4&U)d;XD&-#*!U;o~t+v zpTHJ=Pt<$1Y-ME3|B(kl{Mh{)rh&;8UDcNLHVGvK+25*AjUd-R^4cX7;fZJc56WAL zt3qo_1O3@yq{GP3KuAD^I7v zo9URH(!V&=$P<7DeNMH}Bz$736G9o2#w4){SSr2Y1y;eDSrA-U^!^$`{B2LK-Os7er0m=nP$V4snKc~KhvyClPrLqL!fF}_Kipg|qj~>9M7*&{ z;_11lhKS$E$B6&Teik`evBSHZEW2~;|y%J>-HiPzC7H|2y?$bk;#QkfsDqk`h*#6$X7pZc1@t$9Y zuF-soz990wb41yxhrB#)k`uE=Z?O>S;Qik1A4gM zJa<3AJ9n7lU4RZhq1y5K&|JOC3NJEa954WvUyrtNjqB4vEhS;+gOBI_BS*2?l^boo zc=Buo7+eECQ&Ur6B;-c_MH5zqUi`lC(DWL;jGk@KksNIx6OB``{=*iBrRuT26xf>Yvb0? z-T=2j{8$ON3=$#Ila!KTk*!~%tzyxwtUlZbM;0eRqnF-aW~AupDjdsb^fN`1*Y64^ zBsc|;2cSsZG4t=jPcq82&LLYUhUl*GsQ0TU7k3>u4@HpVr@W$Vo4utUP~2%!-1q5b zg&)vqOmVrI9UfZuA9u!@Q&6Kdt*Ke$cE}y4#`V#o z&mtbTRsDz8_JQJf^6U*P^PU7CZcn=>v8L2u#wWdC$jmD%oB&K?{y(M9dT|lPXMHf^ zYZJ36&>USpEl=Xd90n@g!~pw|%iK6}LJi zqqU?PosAknkZFL-q>&jhwZy9&sWT2uQWhDmFxbN*;oz{<4jIFj9N0B7 za{KaB3J^BDQ;Ckb?iwb#6O2aKQ5UBk^`Flk+y)#Q-7Eut83NUM&hFQ3P^ol2eKw+Z zC4(3q9DKHAm`joK)9U0T_wwLsPr7p(FjBVfWnG=T3}(OTl3%!NSJ)rDCJ%5^b2yvW zX~b(b?fr+{`$D_jFHnY3HSmdW7XpvsSrk$%r{d!(>@tbbYtcV{f5w{ zADJtpIzDokJgo|3-q@x9A&{E7ble!%zP#+ZIl&{5|m-M)B!{;ca${!D9;6pMYKO<%gz%D@wwJo+tV zInKTbI~i_%JcleP1R}y+batt4rjz;)LKM5M%qX1Utfztc#VHeZ7fD-n*~8*ANPCjZ z1xm$w*eaK!J6?q3|ES2Uhrx>6v^JQOQGphRZ&vP7;u*q`88NuF3XUlybu2;2esD1x zB>OrcKa~SC_A3=BfSjtaHLFWC0`qih5LPugmL(85>l8rOKuN%Qt(BFz`(n#wT%lZj z#Alf-hK?Z=NMM&wRx2dHp;Sk}!>bZ+l9Y>0#{lC^Dynh*Tn6R!Q(RjYTktJv>Suqg z6lCSZ&iOe3zg5WZhd|E8`t!Dn9QMlgohWAA7cXDZqUF*~8~rbU`X+@jH#KLu!Fur{ z*vjOluHu#9F3U{a_8$Kmz{_}uEOwXyV3x-rD<(`#%+H@k%Q)?xb#PkAnMA6=B@429 zwM5!n)$<=A=F<`6$2d=EFun+6L!wb^K~^*B`LfbN7FYk0jr5gnJq#Sioq|$(`Q`VN z#sJY+*cwfBj8Yms?IGB4V8DxN4&GGwO35a@r9a`uDfh*=S{)vPm>* z!em4xlBqPa1eC^VkTU*CW%HFW9EVhtgcz=3Hyj=o<6TOD#?^A6lR$ZYXYm{r7b=+b ze;AaNj(~>9ga)xSi%+9BOmrgn{8_xkRBhVNEO-8xhNCNds7`NhORqoTP&VewlG|f4W3tzw}dmGqs`2f3FV43+S zB*f;K>qEUKBjtupQd_Riem`6Y1gtDZDBr7#7uky_z(Rdaq7tF2`@YG0HB_+L;`XO#evT!Udbum0pqfwMb$Z zTFFdq?A!lQP)ialfen6kgj(=x5KHzi{Gwp-x`|Sq;PM5ufnzVzCe|gPKPM;i^U=vs zy~D=K7!+tgq(vPZi%b_p{MgvCXnP#D07Z95Ka}=pLef>W{euQ8n!~tWBbEWDx^)O&=Pqt!e$pgAYw9(D@36 z3jdHAnP4gu4^9?}bil>Lgt?V?Ey662V08grxXDGi82oT?v5Yra7NH)Ukfd=RCs1rO zpVD&rEg#7ZOHdaBSw8XhcH+*_Wu%k`ZXm$*Zb{`i{J)!BeZ6$i0r={$Hhks}``8T*ejwoQb!Y9EdE|pxGW9z2@4a(Gq1tTx+ZM3ASz?F+Nz#kC;`+_)`K!lS0 zOt|`5_NPoTxj)*4uk-|vVGP(zK1VV3;0xzRK8jMjK;nfiY=#Wfqd$dO%cD0`G1EaB z;OJD*<`i2=U=8K#D{4lUzv#k}DGS1WMn|S#x!BwN&0RjJTRe=-I?I%Ok)uKJ7fYaUKwM9wQ^zd@)?nTspkBsAJ zi>&ai(|aRf$}icm6SMxhNq%V&eV%VBcui~*8TwG=&N(Izd%?6t_OnTTq%7oI+=4yY z9xVJCHW5%zA09k~wx$ZhC{uE~)(D!Jze2mZeV00jVC5@*p-dN>YEy(Q*DS^gr@@}` zWhG-9MrQgmD{S>3dHeBP6gYAvpF_HvtYl#a%j&I(UCuGoFEzV#ZsRP5J3JG}t}~m& z=Nl%O<$92a>Y`0 z7-ZkkShHhH&jH!!fU}B8Yd=4}S44kGqtE)jq7lcCVbZUB|6QjnITxd-uJJ;gR}Uz| zYc<)33L(TRunmLJmJ#B^8L3bVnG@LtC<&5?k6WPk zE;jq=80x?g2D-r`Q3iS{oTB#jREgNZg~D;W=`Y^D)4Wf6htvG3F%OW8e{_#;yy-57 z%pFIj%-{f!YoVP-feKd&8W{=&4U9 ze7tt%1fOScTDbnnDi@ci(Ge4OcDj!Kp`?*N503p7c_)$LIZ|W&-%*keWG308OhgW+ ziLg!xLu!m&V<@)VAi|!yFDjI^Rj*}(@p1@(w53^rj`z;8#>4w~D4jY4BHfUR8bPqm z!XMFBGuRPW>)snW_A@C1_DVCX`b-_m3J~u(xbDc53>M>d#iSzB*2;<9NXfS#BvPX$ z=ZshE_;QZzEJfc&rZw-YQ&dRM5K=8u^U{BV-@2DhZ$;kba`0z!p;16bNWSk zz{r)sx=10{9@BoKsuqwCq#!lJ1~#o7hu?Bw2L}duC2)gy1g;HZ9pgm1v@=@!c`{^` zmN+;ac!fzAMO5xRmfySG5+>DBy>z#UI{d->){mxqpv2&KBJ~rdnUvMb1?K>Qeb}G~ z7L@mivb=;vC1TH6ERtAt|6|uq?Z=fTN}usz`yvK!+0-=`TQbiy&1i}alJIE80kQA$ za32u)^_vNzxc?n+1mE+{eCE|m{y$ln0993=qPm0W6Vl-j+2e&RVO`mLWy_*Xnh9Lv zr^30S^l6PLOf^sP>64lw#4r&11kd3lfsfo8++jSo=AMh`L?fa#Geb^_wOMHbbpDNJ_SstjO} zbTHcfVYny1Q2YvGEDV_z5RC+<%(u+9Q7^oB(feY*RkihoE?L|TX|!Lhh{UGN{v{g9 zGFPk%%K9ax`UL!>e&v3R_Z$uDhxf6?(ZMuFcVWPco*t&1c{g|HK^<@8i(YsJlCG|s z)vK$|u1fb2fev(yk>U+&bf*TLiU>7LIv8X#lPwB{+Ov^uWRrN5RN5P%#QM^~NJCBU zs1DO;ZiI5ERTTpwO;gk!s@#Z>2O~7tW>d8x8Y$juX7{0rSDTi{9+#&(j6M-l^w5!e z`mCA6CK|7AHxqplVgw(8&~gsMuU?5+Vo5e4P#QW~;L?yW&NqDVFOKZXGTj1p3`b*tIVkawevDSaXnM7L=v z^0kyNsaX$D4w?uu5H+hLvQjkg_ zDx5)1S?76Da+#ZftuDX3mSiUaae(RIk}j^R*)8L6;8G&ik5DV&Q|V+^aAr|n9jOo_ z2`7-x=R2@y8#qPRs&yfm#}wQ$8`wB(`FZ!9`8AqXl*lJku`z&Nr_OB+UuG(&(Kl``^px5FB8sstGh$2R zA<17_HT8`A7W2phxW=P*pxq`rOk5f@4?_6L)`NV*RhzGfBXw|U1B#Kz)VEBlP*x}7 z@-iA0I8OgWCvvC&{B`QvPc?|!|JYazHeF|gnc@wqvjGmSd!U=|E?8eqjhx0Lg{z~o zi9ioQeI!xA*k_9l$ATh-@JO$cbp8S*XfI0=yC*B^l`4h~i`1<9*zSKr`m&B}vY==SSjx zKn_21_0e)as4H{i;V*39A{)eO6()Ad#t-tF}vKKU#&bLp2Q zL2ujWTe24SG~VDdJw(#rKL7JfI%fA$UI?RU4zeINTa=qc45AE;V0V_ZE-P5akA-Ov zveS`EGWB2)v_ND{DGDrM*V{<1@P*bD-(?eZ?K9GDur5l-b%WC6q!eo16(ME zQ~625lEOhq*-s91pF+0^*y!HGV9SlF8@?|rluFe&KMF)(>%|evWKQ!w>!?R$kaCx7 zebutnGDMwxn3SxO?z3PcDn5uOW91ufwM|lHJIv>>3Io5VwY!mTQMI&qQ=x`3mk)lC zv#69*%}<$PhO<*L6!*_cH19m#@w(Q*8~*N8lbbdS5Rd}+r|sR{jcgNC8nFN7l=pMJ z7Z?!}rOchu7qFmscyt7K2v1I)A~p#I<1kV?YP`l{EiZ(mXCkhzioF3+j6s4(iW#u# zh}eYWLIpoBPtTqAYF@U&5pGl^kZDmeYBb%(Y+cl2bqU}`LX_u(z#h^O@j6gJof_=| zMC|kg^7bd-!0OVMc7gU3Gt{lwZ&bU+H%duG)BX49@IR;x)FINLAowH{39Io%90**o ziw_eOW)&@=t4#W!%9m3ch12=A49(&pOmwh;`kmJztN5TEsVu0+jWwzow!JJ~?jps# zMkKth*d;ZPjI=4Gb`RVYO%_wKzq}D0=zpy)3FzD2wkG=RR4ZQA)pG!mLsggG$(5Z> zm_yesLV-v`YUu9MV|gH%1y^pgzP^6>+v;NI$@zZJ<#N@P<2$27xqI__b@k_6Ulhv~ zu7<0wY8=c$&#kV;OxD{k_I9tvo}ANwT25Y6wO%%L0m|!G{@nBDFGKfVD*l-PG>D3S ze8l@{a^TGVy!j=8%clkJLhBo+3a zeO9s0pM>S|WK2-e?4(Yt@jKI>qz$w0ja7#|lpCokaQ5fphH{aRks&mc(S$KX8q35h zg6qJry;z-_7U1=nZ+ZsIChFV}C=*xwB@cNH!y9E-&s3?xA;sE3sZ?gkuLjPBx8LX& zzNER*COyz)@gmCIO&%UhB^HamM{3@c8n*#LQHy zcn^0{oFsgl2a7?6Wu0i)nLqJOaY5d7vkOZlGyEgui~}ja>se3cKf1ggcvL&Rm9O#~ z$hsk(?Y3W?pXd(XLI9~v=_O|Ml=S~Q?B)^8+)$D()?MGMBo<0*7_0lOW~cY82-8D> zB>4~pB}4K;yfJ;lA0nDa@>d!Sb-D)hr%UHr8c^qqVK2%GGzA=x>E#R>0#I-|xqr{;YHL&WBlQe9H>V&wjuC^|oeiJe==7jAmWyi<|k7q56ztt8f&Zegm17F9# zc=2Ly_QhmPbJKfvk4E`?SMwfS6}wx^*3{d6pZ32>7#X}_d;Ma&rn>qX!<2PL26ZeU zJC#7^;QTDGOL~@jIlI;Ws#@=}fBUar8Ye}mss4A~m7aCKVE43@s~%Bk??m!C(um5C z5j5+zB~e%iM1r(<{&{`+0n?2~63nKOIPXl_hL$wpQaD*%ZLRpt>x^g&##QDm7=(|B z$jrZmh@m6O{T=Vy$Lz?!+@%uV6#3Vf5xir-$zm{i`45?~0)z}Dk1R$yoYQytk1^a| z0tSQjfNYC__N(&TOPA1-JL%Jn-cI%P{?QSgX%!}SELzf4v6>5e^X>n(7Y>6#A{^92 z)Mby#b#O;dPY>rQv8v^&ZSoqq3QbGBbnsS6?v}WtOnOYtJ@57Q^RYV@FBeXQM0*wj ze&#ptw0KK!B=XyV0(PZCSNwyo&aw}_)ostu`-rhwwmm!XZ#koCTg=I2wzFT~3poEP zKGL$gd+}#zA)5?OP8fYHycJEg=NRfPT|51{X*#zvM6b7%cc2YYNDL#!>iuLfO;Eys z$b1(-0TUHYn*^Pz_c#3sTG@d^Qi8qI}##bf|ddE3)5XCXG_ z^w_ zj8clOgs&bvzO$0$Z&tQM%4-??s*xzyKDMlCHEt4cR}TWr?k*;}mcA;Mrg{zIaH8I@ zrTUAyg`=N^FGChdI2&*}(?5PZ7=ANT$CwNdUUNrg>VN>PEdbu90YtGL5BqaI*stLH zSG*S0T6|PZ^&}*#f`5r@De`!}OYgHb4o!8x)%&gzG;P+Yg9a)wKHmn%)7tbYiJ=X{MTOz6C2s~UKFNY33Ow&&BYycjAndZ}NR}2k zQzqnb#3;#rU)*PdgU~uSNsn7tV^gDt7enQaWzPD4OKW26RiTXFuS7~mHf09d=Tgqb z$Z+#N@$32o>Kp|LkaF^{s!uCwgMCfV{mWymucV_}`pi|94>$ax)w$ot7>llp?LNC( z={YK~G5lt4k{Ac+Slg()d(`(u*t}tpbreXbMS{4JGlEZJ`9sfMKkG};QwToXoB*<% zbw(7<1Q7-W@K3+3j+;{4(<&w_foS9>%^??Zbn{oIlio1S(0@zh^Bz|L5+Ub%dSG-y z8u9M=AO88hqxx&)B#6L`jnMhh+<@i5U*a($xg$G(Tr{g){AH$j$k8WDb-Ux4mb=?m z&arlSA6;hQrkc}l7ysG{9#_k+fw}VHG7i9)$n@%>bX&(4Fp!wxa33dcJ2!;^PB|ut zD-sSN@uEE~`@?Lb0PxVnx00rJqoU!mB3vQ^)*_E)>WH@;`wO^}YUYE#bbrYW zAnQuPv_u%l~JZe>6Z$Mv-KGV^_JD& z&?vKNd+0D4%`Pq6paL2H#TTJu)!%yG%I`-BYo!rHm12@b0pWwaP_Ufx% znYy1;1m69lEWU0sy4Gv}xi|}1*ge=X!(IIjy{LMrc==C$;bi#!&8MsXtytaa=g2_E z02Om*XXn2$Nnv|&U{PZf@0H$a47anmeA^9fYO;tm-sa}!`0h`N&4-KMzZ=7rkaz!9 zPj7q8&xR`aEe$>KX5^1*N>e|s1|aHb7_EpL>U`p zg<{(eErk}NTP&vg&^pPp#~h7aG0i4C;?W)5_TV^c$t^9j3g*do2T(p+q3m}gdnRow z&DVu*F>mCa|7#Z>0zvV|7p;==JwJbOam(cn=YN&ecva-A zz?kN}Z`eHuR20KuIy>qxs+*Y<9WezNh?@8kaR@iKGvat5tM+d235sEW!7gvC(f7y5 z8G!-xh@!m~x;ouEE_pfIWDt&Jb|7-}7ClJ?bH0G&h_(`+4W; z`}L6V>SlJD=NIpr-Da{6^4)+$6X0ZC@@QyoJ~O*(H6ZJMb@B)|)83T9_=>shM;98W zq54%zBr@;K+AVy_5;a2%hmafBkBSVxL$=N8@UOq`(b9#}Ms=WJ&T;+fm`rh5xG4^c zVj_EkrE9PxWnrP`Nq10%Dto;qML>{zV&Vv?8hCmP?F4m3O(qJA5_`Vf8jpb;=FxD> zQiN0dZc;AF{-G8ni@;}jiC2TmY^}K-i6(rk_>I4bP}b zZ*HLdd^B`_gvM=8l|MxB=+5O3Rg1Wu)YF~|MoWFqQ{I6G+fV(Y|9O2_5r28%^~+0s zs3Fd6JW)-BuYY-X6AGgI946#~Q>Arqqy_6Ebjuwa87qFX$!jx%;0FD&GWsmZ={R%g zCPNt$aYIMr36wGMlXeN4t;a>&{PYY}+hD%cs)Gw~C)TT3I6Qfxgb2Oo2}6;NrQs~D z$f=XS)DXk0n%_?}`^g-gQJRC?Y8ZW-qjC{k`7O!`FOwj|J1R&PXEfCxygx7~YFw#T zg%EI>obil%fBO&Ia}hrEG-Jm=#dy|K^Fg*Dc49PuLuIk!YoqAXK6dIjoknhmJ)@j^ zQEMFTS>l&iiod`MWO2$l0TialnE8`oe>u?aPIAs?|CXLF{4J3_iMWst-Pk?HwZJ(Z=dTl?I^%9n-GBM&n+1=qEdajWD z0WymbI>*t*MB*7BTuoh!DeNPDP?jn=p3~pg7?nU4ABVopwGX&8T3HklruE5>dANA_ zm%o5|KWh`H)b%j^&6!D{;;B4*>5G#7usQXp^m4mpaz}xuiutc3azT<#2>X%_B?HXo zf$w+*L@bKdxEd>hql97@Ad~v#6G1@-om|GaoS9VKfLKkV#y>lcAJ_PXHcjS)++h86 z@WYXBv;U*3_26KnW~z6|yft-a$K9nbiS82`W+W`-4hvNDBn+bPpT!22u7afl-3bA| z7ED&}1r~N!eRXW7>|~dg$q?=7(Dsc|=f*f5G(W&}q{hY}**#6ld>^lendFcFRVDG$ zMW%V-Tw`>>G*z_#udS5#EACiFNgLbTdAj%EHebblsvRi@B)``OVa4_7eTliOk!XcY zd%k4Ep`8LXzgOo5k+^lS^E zuF4wu%}DhxZzZ}Jw)kRldT#E<3&0HfcjB_ZJaP0JceyA%e{mI%yYW?Q;cWGK$jW*3 z^?SP-P&^P zckHao(6cA~Y+R>76}?LNGdI-riujekD22x{*+WS;j-p|GvQTd>}+K0~ZHMoq#|n9bG!6dsj)=x5lxHzrgU*H4K_Zh55 z-(3=If3@6*myK^Pm|)1y{V3E_t2*nPTj+D}dQ#W?)Om2%Qq`uaU;G)iLIp;|_YO~x zstjcyG6@9;2nn+Zmw4_G7|#L$+5V}{Wi<^$Fs8pc;^~9T_!<|mHJuj~JWRqXj%_~R zP`&mhc;Ap}Jdeey5Rw$;f5*ARsOVKNL95j-5rk@bvaqTq;0QDSyF{f72|m@r)!G{# zegca-(cVh1xuaDZQ}%dV0))qNN5jKs()kRbY~N^UnQJrBW7Wq$5K_AG>iv(64u@x+ z0Kj5_(whZ0R2Jc}_zW1&?f6IhKf$n$&ylOC4m@yQJwpRYzL4_Wj@u@c*+61u&&l^^ z3i96TgDwJLH(&Jp{>=_Fjtq#_uPVPo&*JViWi^&m9mTV|d;9?`PhgOvu0U~WVD!Sc zp5okODR>ds(O&I26%FKr7oXN{WFG|FjTU}xX=Qc1HsGY#Ba`zcAmj-?tj*IsIHIAC zef~($ zMVmIZzR$#RMb97U;nD^kB-n>5Cpf?P*<>91`rGToiG-G;Xw{NBQ&JL}(a$(>L+r*8 zcR?AxORhu4!}@4z+IQzIyEZ-*Yf4mBQbJxeK?)6537z!?b`xpA~)1P zlw`w?%NoW_(oh|rA(}#5%Qn<>n~~Cyx00Bw^S_g$81!Ykp4(>p10t^M=dDVXUh0k* z(a5meu%$;yhM9L9!^|dHEnG!d;Nq{_L~p~v_Q^CPC3t%x8oj=mQ5@uv$87Ky^-qiW z;N*Nf_ww(HN$!HZfZ6c@OA^tXoqK0nhJdjLs2!&ZZMH9W94mkAFSVeAcZPSu82)~S zo;rmdIbHqXyzHXM_y^p0#{d{l?)mba%jHh%Ki>@XELsB(soMWg1%KqveYU^9Ho*U; z^NYgYKF)Kst3NFpfo^VYA}oST@pE%?fKR|-sRfvm5#@|d+D>HZte=VFRSZ?@NT zAWr!pRg5}GA1O`6ny~3OkA*3)Z4_8Omvx}&{J8C!z4V|2OUc*3Ql(+W*@PZ)3vWCPonrcA9${H#$lI8=?PRZUtS_o)ULYSR92Z zjLdpaNjuM*&-*N*?c0NYmx&%|FV|e2`>weOG#4N4K!|MgBF~5a=F3nK1q?ST!h1hE zTKHzn=FZf*bqq7uSY;6Zy#t}2>SVAg8|3k!OsPy5xRnQp)}|cP)s?pm4aG~8UsH0! z>F6dHiIjA!NIXnx-#H`mshj+U>y9uu&AI7u)s{-=GWW)(*Ah`7thj8GJ?t@EK6`SL zDL~gS!U;YK%teceS3#L86md~BpA62cYwfqcwubj2rt`V+(Y=ep>I!`R_!N6d-=8Tl z_LAau%HryTxfQ+U&v%QZdVWTSDrBU1xn~;VO5?l5UsvTQ1aHpQhj?Zy)_QOEyDAI_ z$l^xiIon-uLti?8_QGW)KeO9ZC-?N0D9_UAsl8qBoR!B;-?G?WRdI4!xH3%mP|z%c z6|60^K~0AFAa&Cr84f8c&c=w*lG_@_i;6{w>8UEPIua?>G3$XdImvN{WjZ7^x;IB~ zSLuyEsVi+6D@=EW-2coS9UbYNf7Uy%TsUl2E2O0b{zdw*ZDv_iLktDS5)fxWnxQnpFdV5+W+Toq)Ia2OcZN4idFYW6XmPtJ1O;*$qw z;3^Nf_;#wsSM7HjyW9v-A{QM&`MIwFqcX}I>1!B4<1l|9aXQu6U4uVzclg|so^cw@{jl1n)GO3OxU~FqY`@DJ zBEPd7%2#?iBiYIq{?OUh`Yc9=}rAzEr}-K>=c@Koo~OdK(P9CEZIqds^*Vw@(!nPOD$) zs(l&!*|sM1q!9>$tRO05a6r1mSqHg-2cfjj>09P-|IF{G`H{@&{{FKx`k>nNFzLHr zuNs?cL)nX3JXU5qT8vcor%ip%x!{4aAI^KwRI~3VeRzKFJN!=DlDjQd#mN(1CdzbA zDj9pIgaJeb|GW^wQq$|EbiUhEdJJ()Uf^k-hTd#5#n|!!K(EZd;Dhi>d}Bt%_TMr{I%3SSbb5q9R`Ea$Q=_2zb&un&3*KFdYyG$=<4Y++hDZ8wsE`T zOYQp{o5JpXJohxoEGt)=C;6Z54Jibi?yWhCb4Y^%Y$&Jw3awh#hBdBx(e+(&;Y67( zybP813u+!osrZ{g1c|b`96rZSBwe!j*33T){U8)+0b&%& zBt&YzEfMXhd#tL8A@_ZU^1Zjpf~{qF*%M!SRaYRsrd9}aw1B_-Mu)J~ja3m5r}bp^+10=?c6bc~ zGq7>9+mwV_m#nvXJx;@}Ps?bd{C7DN$m2=d)3W=`e5;Rl{{# zU49IfPxyFfI56pRBIF_N`L_Q%${oj1^DW@%viEA{ykMlA?9ITR`9MbRPlrd@89=)s z87aa+b0Z|j`_0J49Z9bhQ>I1A>2qZjD$cKN_nL}tm_5&%^5(8KJA$$=mSw3{XGIlX z!j}|5}D$s^KOavY8qA=<;TGQ2bV z<42^5dO0f%c}!yIBFY#O`Pmm&u5N8i!ssc-10pS2dh`=DtRPTCEaBsOV{3?p0#gd# zvkoC@i&46n?4UmGpUByKm9S>#whB7m_pgRuC7JWSq^3-bf?-}{Y&Ol$W>f!ufHCq_ z$PMD2uH7E1ZoHPp#Tdc+x>VXx>LXkomt0nBYSE1{_T;jR?cn3oXwMEZU+b?&zU9eD z_eKu77nx5raprhJNCHC)^E|SbwvJ*pf|*!L|71l6W)@2%aXh( zLA6OzsQ9(f>+}>ak}!wr$#C%EO#9jh&vN0*dq?e;Q|%3%Yat_(SM@+2eKnvsUw{83 zH2BzG;qu?g)o%OQRcn;=geb-3ZFA>9Mt&>#pR4COo!W5@0_h`ebo8PdsfL;kI~Yb# z#jBwgqTR#Za6$l1xiArgj0bj*h^TEqeqFvBPagI4sGtwf?^!h zvXN+QPZnEyg!UYg5rGh+6XT*K($%J6n9}(gI@y%xIlk1C^T=mQn{0Xz{mU+mB`QgLKtr4!ItMo9`EBXQefP9b+q^`d1pJY43l zuvS>aKybrW%>$)GPwUj>DhrG(I3`|{9zo2Ai@7Bp`^xq`Q+c*Bhj8WXG45KqW_~A? zCi`q!LQ`}}19b^8rs2=Mbm!qd@>Oh8D$Qmw2w%y>X^Rno`UE^z5sOLAQ03TLgZ$X+ zphImjibp+t@EJ~o$MlVElw_vBXZtl4yDFC}8j3fLYCkTFbh<#OY7xpk=| z=Uc>(KiKCAvVxw{ejcnS)EvB|@n{Lt+YgUj$tV4ohYnUqP7;J0=7#XF6@+#>ysEvG z_bbwt3San2j7bd@-xw|#?O zz{Y}Ms#N0^z*323?2n-}W!xrfl*@zw2<*({;eh~>Kr+pk3b8k&s~*PNhcYu?Q@Zc> zTD;{B#oV#`Jz`|u&*7UvyrKW@Uybfw)+~gq^-qv<23P~%(x9M?vEq0FZ}Hz)V4@1} zFV`wAHmfd9nOlET(Rw;L9rveIT)+DV1k&bP$^F-N^^Y9b5;cZgoR+^E8tKpZS9a2E3Se(2xd?U%n74&EFOI*KDQwfTTbG4=9d z>gBte%Ol9kubih5mrGU`6;~Ilx}V5{Z9$mXArXNl842eq+xctnI^l8d9|q>jMFk8L zt)PpB+K8CQ-mju7c|l~)RK6*d-5Xkj>!*=y>#5k3GC&_$khwalc0lrOQ>c8o8NDOm z=lfJSQcyFBTPG8Tv$%hqqi}4gK@&Gcke-_P_InkdndB4S*&qQXKb ztUgshPaP5f_~N$zY;6;%iD$&WpI;OL$4n|qm*&LeB*3GAk1Pb{{QB95gzo;TyL&t& zCP8*0X{iI=vD&?=Pp3<58EYud^fdik)rFa~#&F58tneBZ24rq&iz89NcS~PY(xLC` zbmRMtHA-v!x4}yJWs{721ulw>k8&o)E)?+LiYNRh$OiVOKzH>9 z%^4rY#JIJdlzm2Z!>cd3?ZH?#mSMXjy<>Ewt!b-bA?%pq&8sFWE*5*CfAHV$ZEY#n zl%Riw%IK2q4M5?x_w^zZF=}(qDOu&nlVhf4^l#pIF5fJXeH>C?Dc~<5&aEG#{(e<= zdF%*}CN7J7*#Frq9Uto*GSxC(82;}V6%i9hXSZmbmzmn9bseqF(l_fyK>;BK2+cBH zP=Aecpl)cmiJ=)3BsLC3i?Do?EuJoL%PdJ8B^M)u+hSVMC_W50zkBogH6r`&k=gX_ z#-gMJ4k#-F1#S;;0=)FMo5;DvSY$SOlCR$web{P$+bo9Cv8#d?qy4#?d=Rf5`8@#X*D)E!O9c|kVvU4j2B5qU7QgA*t-_FZ5jcFtBkb*P!#q^fj_EArHM~b( z^$5QA_e1y5@Xs=Al@5$mw=3eZ1liJ^X=%XXC3#%NvwfYU|L&?tZ@Z{J zksg@MLzR)VwnmKl`gcNNGt0cs<-4BX7`tsN)|W{N)UBh3JsIvvMO|ho{y84-gq%Om zl^6Vbsk88>^lIQLbf&b?zb|Me{Nf*bVjUt#-U%kkg~Ms`b|Szsp^ zBa=1Mwtu^Q|9;5o{phZx|LoboqyOb|3b-&XfWo49Ag*}u(dz7D`yPAy(r+tZ+BPh| zYku!ju1(8vYv>_)$YStr@UGQ%E`z+6!%V6%g-n-}30y zV2bZCQd#Wuz{B_|3-U|sf8H}3J^o|cKqV6o$`3CHlRbc=A>yFSM!B1Drp8%#Q3$vD zuI`XvsXY)F85XZ~yF5eV6|Di7Hfg0~*! zQ;4+i8F{h$eQ=0~$-pij?6NIv?V*4&TX~C_97eG5`+2h8fG{Ra40wqeNF+qL8yod| zj^|rvEM9jTOmu>Zrk&cT%S%p73>Bq$y|jd)^FpOLUSL!EVFwGuYSHBm)?drEWT8ThPJ{Rn` zg8l>Yvplw~Z7*9iDYZ>me-?+SAV6*Yhc7xLP678P&;6ALyf5C+D@XXyB+zu@3w#nU z-u4j8?U#Dm`2Wvi7E+FZ_7Zf2?oqn__T;vggqI!wI6OKw3sg#> z(sjpxanA1s6(_gp0<_60J~fb#G?>yi+%<7(D&X+=AdeO%#9!*P_O|t$W9Km>bow3>78TWU)!((xHRmL zM-{Mor5hcfGp!xLcS#g(E1cb&GPg{k4PZ;D3LBj1{Z<^7Uud7%RFWn~NwmEFdsyeK zXT$prkYv|C{b_4{pQntL!iqukM#O)N9ddnk5#)LvtazBWt=-*fdhp(BzBIJWZj-9n34p3A;wmQ0q&WLJ`85JHJ6oMjVtcel^d_heau^w_O zO4(6`&F`uAdj`i?)I=L!8vJGqpE3-=sjXxc^*s#RFO3S9zB2r9njZGh@92jcUS9@E zvJ|C6sSHPimC&SNxBFv^x&~zwq!;VCemF1Sn{0duBx3vug#IO!rq$Q$li5s5kw3GO zv}DynV<3=G!wLKz_iGH7M zdv|6qk44{`sM<cagLcmuU<6kolny7{LqpEJUpMz5u3NuHpzyAtHBVYj)EfW8+k)WRHN}z!t zaj!RIhQum=UtU`duY2gu7&e9%6G>xdRNJn3Fr>Im>hPKVHeBnRdtK4zSf=s4-R-S) zPX^ddI6bD1nMgiAyDKKYhlJ8!7&s6?bIE~ zh^W@*r~BTGiP6#XE-tqCfye8W>m0(z?fp@Is!l42*qrGZLzr$^2@%mN>(j881i6Ec z;#DbVOs)gpnB#ZK?TL{A%B-bgv?gCVLj7t(7A#W?wQRI8Tw;Q&gc~nDVAZ2DpeM?j zlUA7-yAp+f>I)c95M(Re0<9EBBo<%>F63;-RSTaM5STh12@=g5JLo{pmVg*P`xmIN znTYS2ZJkfgb!U4laOPx20NDt`-{qgX#dd~iGk)pz*h-pCx#PnobX`2a%tV%e&|p_S zK$(TE&a?T-B-I3tJF3wgg+of;T3Ep03fY*BPpfmU$L<16S+o1y;#t3} zDF;zq1*vT(6L0HyIiI%M=9%dC)t*>aac2?gXXb`Kz5-yUUfhU6ZNhIOzN3L*atqR_ z3nXe)je{;k3R>N7m^m z19{`smydzqaRAJW|H1)KrV#MP1UyweEMz0lnDNe7 z)>4tj%q6n#`CwEW*$y9rWWD_Ks9S1Ej*gCgeve;7ZoXlypabad z`yH2uZAGfLBbIwg#UyaZ*$tuai5CNzyu!tbS?!D#*oVtpJOtBugsE~#Wt@eWhmH1! zkj<^BzK^WqzkWG3Uh9&}EcKb+H$|n8QhGm2<0(>?XbUl5t18kZ5=Er~npO2KwgBx> zcmUF}n<$VEVeEG}J|2UMl7svdMm~;~e3+(m4M~WHoC|l4r;L>=8If)P7J2oG!~B#W ztQ|az#KT@u=O+w{eZU33Dh#K@ap5HPfwovzWlgvL&f=$bTVCdU3R>B`4z<&aHa;U> zjN-ik5Jb@=O?LQCxw$Gl&H3RqK`sC4`huwa4soQsd%txdkJI+Sa9Y_&GGyEeQgj+n zrIaOg?y)GgC@V$5IzzE#OVs)it~r$l3K_2?4-Yl{5~rqH7O9Jmt4GbDvL0=Wjp!MW zpT=eh)0nL1CUBF?2AHubE`DlDrwQ6V{PT934!b?BUOczBn94($TE3JZa8cg`}Nbsb$tfQiA9>N?51;n$xY)!p%%y@f`o1UIthxk$_jOMSlJsI8Xo+3R6 zMZ7Do1LyY;eGMxK7H1Zy-p7g89pv2!DH=K4rr#MWmdfHF=89T-cMPK z$oKTmPZf#AYW8rANSC#;@O{+c3k7Ar*atBaif`HcTdX^TkV!+rV9h}rwmRA_Zc3>s zbY4g05#>*T@Zm^GT{7CHrH(3;@Nja{=N>y?0p~I z;T&kl?ib+~wsWN5o?(WBiHeoKOYyVmJY+l=d^)R(tlZ7U`YvqDe1c@B67%hER8l{4 z%DMsoip91D2?v4SEy`G|DR#lK>#Nbh2p}lwX9<(Ev;NXaINl;I9U#znfdB`xXgwe% z@qSNMPT$v>Aa}0ql?7{oH_%e(Wkr}3#NGarA<>gwWjM2Q9{QcVqhGxB81yPO#{c2& zG80K=Kc-sqt~lQpR9lY$+U@I%GkD3zBz-=w(x%0K`r$j`bM1fF9Rfppm7D^WaMPHo9!(#G(>S@ywqEG4kj>NQa0=o1geSw_cpA(-{h0W zgPUVFM!~S&nZz4u3r^bvIt*a;tTQ9AW>Kd(|2rXwmSFfq2g^G+u)ip#LxupciqL_B zchB=pPLvEg7@T&&6=ZVxaeXw506_qQIRo)T+2Ce(c5w469i6LQV#eYu91B)3sfo_tBTTI{l!hwQ`X8^WsH>X-PGQb z1WA)b(g^e%*{kLLUvv2NWBbZ|q11g5uSvbr(Yz4k{(?lqsM*P1IDKrpI)Z}7_hjX% zDd2ITb&KL@h!;tp9i-eMXLx3O=_ANp^Z868+;uJMabD{3`e`R%H|u%k+IPoI%x67} z&4~A;18W%upWM5MB9y$jL0T>zrEadDD+1PIR{ZagS+4(y`0n=hYPx^_&Ooc@R_?^5 zF6vr$#F6)=lPv$!rWFhr5>>dnLQV?np1a1L9?nkZxSH%98c0BF7OX71nZ&V*dOBwl zEP?_#fh7Qd^X}%psyr<|1U$Z!@`JJ+^aU4?zv>;o47!oc+Rn|D>T+PPK(JcbC>Gk< z4q$BfeFT`{7HF!P73RMG$IMf9{6`9$7MDt${k-_;Wx3r>G~gt(S{C(#I$~-L7d!ct73|0E`;l)@m1c{MTdq zdgD)RMA2b?mwb?XjlKiU1~H`Y`Qg4V;4nQ)B=jkl*ZVJW(u!nr9-9}Moz^;$7KKV2 z&zL^1Iaz)j9(!7>ydDX-MNXRN+8$MOFOiXF3*zEMwZd|6 z$>>{(=X(tR(&}+%C;VJv`n;O#w|63n6klvakxK;FZEG;`g|!AUAyLD3qN$Z{rx}T` zG&DG$uHQ-qe$!{Bcu=fzyqd2xdxPeBN_!!$BYu`C=rV*B*1h%A_xK6er^}dvC=S=K zNfe)l0jdzZ*O7)qC{r><;ixdyxnVGiY@g_%c2|&{h{%XA=A||dJG;%NhN2V6aA8+k zT}Rw4L3P|8o2A%E)3^$GAE?@e9vVl|s3^%@%t3MpRjb~RT%;4-ej+bJ-$^F2A73# zwYZ)ZlRNeCDU#2f(N5ut<8xSz%Axln?j~h3b5t+0i_(T*-;j!TZ*C?b-AklAmOINZ@=MGxsXz)yD%`N1F8tRTrb)UQAUd&Uq|Fj^h<54e@ z-e_G3!4D0tYdacw)CW)1mOKmgdcB|tDGi&^wZ30eqsE-KA{+gzhFZB~v7yDv=o<*EGuf81>K3Ua-!_TTs=47sd zp@l)Fu)>j25=0hSgf?l5L`66oMfn4lmzU=j7Xbh!?THLmN1`vt+0FUR*wttMhcyKU zLs$05=UI_Z@t0mElou*=V;^+=b09loU)f#kutTiS9b_%EGaPYH;8T?(ehssBrpb9& z&Spfh3>GZ9m44E)N*K5Un6#7DJq{5-wHG?$d2({zH8hLcb-cG1uTKJF^faT*9MqtI zMYc_NbolW_<*zQ$AVxP6v)PYb%bG;3cX)ncr-9KK9 zTMKB)qRO696r~1kS$vg#3mRBBm==|OGc+G1^INAGW0&Bvp6gb&;$gycPCIE!{5Ce= zMkA)lI@BBtgX|~7Bc49Pu0XH?&&5^VSzclr8mt~PVQ`~}Z$tTB}zLqxwarSK>u7AmT>xr3YI)+3Zv5~710zqb}?e()JyX( zV75M0%NQacvc<#7i91>bmDN8+ z`M39q0sMQ^zW?*=kE=#?*Gh1eU*^8Hl~X0KrqdY=kippHn$%>?YTR73r>bG7mXE?A zBWK;|#oI>Jr?S{MvEs6>;BfLo#?`0DKdj_54oA%ziNiLUpH7dua>>I&Bm+iV29T z3WY3QU_-XDCIk!tKQ1i>CqD9dJHO@azL+=E)BQJ9O`<=|-bniuE1&aKn~2-lchGhf zFK<(Y#4bYyy27=15=2> zQ;+`m$YEy+!9f%XoG~BRJ;5j%9WprBdYxgA*PNPhmTyYeuw(+(xjw?{FlldHRW!M8 z#&U_X?TaGTX_{DGyA`-3A*gF&5n-ddVM_B0CW|J(lpu;?6kVksZe~$^(kw+K)duU~ z(@uqVdMh`4q6WZ+4d0+!Yy)%evp{ggX-;lx(P+of5)44MbO>U8PADg}moj|HjZ7Yo zh3p(1_sn5(vKE%dEAvZxq z`1lASFfAyJn#q<74a-_OH|b?wsmX=~KOrM9G~qoei$~a<9~Iqe%}>&D9CLzh*!&nw z`e=KKl&dc_L-Lo>;0#b(>Pl=k?~@%jsGud2v-4Xtm`mh;>qHWB#v;vpMZiC~6R*Ax zIQ+dgqhkU0$H&V^cDY37L*0u1z<)*wpPMxWM~DtGy|yuR{+z;ZqUi_H5r{nPNSp|3 zWJ&s+uJ_QeEsBi7Oy7*1xbj!_`k7;aQ726Ln_Q}R2+i>ZS zv;s%i_7@>hjPA)yF2ouWwDD?o_6t1$%R1n^)ib>V1yCli3027UAe%8QrfBh)c`iI{|WuK$DPMNW4z+n@zy9JpI zu_79Zv`btlnKnfBR)UTvDx#rdY>y9^=`9^;6;v;C+E|cbw%tdv!`iyp6&teq`^WKahBS@}f|~O^ z?wE)MJEXkQectE1VmsEc6LEe}&K@FB+|!DBR)bmIA=aN8ikYA zF@;Y}vg`53%KDw>jxa7-)kBkCW`eYqOD=y*fR0pCH(!PCHLv^ycX!m&b5%PRtDp;O z>lZF64sHa5KlVw+SYEpN55M6<+&WREfcTQBIGu1*QGoy*B7(?OK6A8?#&Ez)?VK)} zD|`aKPG>N#hd~fagM_SG;JaK9m0$m8;F1PdUI1HAXLZ2F4im%%mc@e(s`9^M$~9;p zr6Vp4*N7(K=MTnZ61)7hIa3}ShHjQCT#WU#`vs64m>Z7r+g5qWk_Hglz(rv;Syos*sdow{vVL)_0qX7V@p5aC`W~2%(U4{vKJ0Vh^3E6 zo%UOv->z3r?=CI1AVZpw28n7B#n`vVP<78Z<8}N$GnQ>)zyIZDtvsCl{lR7K=!*$3 z0%yLE>{62%1~lfD=z|X1NzWxmN0ZL>Mp4bOew1fEy-)oE24G-mNVC0=r+d?Rpuhu{ zfjiW!>!j{GDLFk;WJ!|?xqqEw+FFZ)V4r^p#+IjAa=l}Eg-`dEc$%T$aB{*#zEGX8 zYtgzl@dE^ej!Y;nMFnal_t@lr^wc}B8%potq2#k%wHfUR8BLvwjV^Q$4D?%~Z|AZP zq>^(prDPG%g~%Ot=clIJ>P;m@>$&-~4WLmjN}h_fTZ&((G!xC={30AWi#BE0TtL6M-pgQB9 zW-q^P`+Y|PkS_93u>)=Oc1_NY$yY~+$S{RnKg*2sfNIu9j~X%q#YxR#qgk0a&VQmq zky8$9$Y}`OQugo!hxUX2h?}INWh7h`9h<6a-a-;>#DRIyo_?vhV{yKqp536Nm!DC~ zjAy_@ug>E%k3$^`oz{ZGUwpDSpeJW&-&}b=%?xgp{X@ga3^R!vu&;!d@M0$O-%d;C z7M4Olkmfe}Rr1TUEvZO}-Y!(4M>V(VEpu+=jF}ZyHkf8oFSL(BGnutNMhd@H*Se3{ z`rsXWjhRN`Uozc-iRf?KALEGDRv+JeM-^}fiTY*Oh~%-|2EO_bj_F#5j+*Y7wSM&g zsDwBrtWi6P!su~XM37mQgaJA7dL{Tu7T_U+6Uz;%0|ln~_(BJ)SPXq6}4Iluhv{tFgTTex=NnVn=Wb@pfqT;}U!Kx6TxVYUx zH4ZvJi$T+Z_|l3Jhy$U^`nk2Fo1rPDVhn(Bhqr8|TRn54^Xvt^Ar(O}6I);fW})_2 z7@2V@m9X>3&A$TUcGSq|zS^>@bxYw9v}XM}bW$OYiUo-<(APP^By=E%eoNUav)L{G zPb}g^FL@Ce_^A7r<_KzNuIr0K^uhS@ZT$Uwg-u!~koj>kvqcP0^ktdvBF~-C_+dT$ zj|2q|5y;MkZW_W z058|}S-AwTBcc(NKdDI%qGL;h^0myS$BUnGI)S0l>y!5_uxGEpz>GNp)}BVw-w(a$6v$vmt|`=p$TEd++`Zv9gi`~yd0 z*yM(X!x2Fs=GatV?55pzywm$ZKnSA%M|vVDIZzD){#&|bAcqw1JBvyxEgD5NR}lTo z1QrUu(Zb7NuslvsP|(NlZ5Eloq3=$(6#;7U-*IA57J&#pQo2_b7)1EC`!1;eJ3d-& zjWvXSAfHVfX#BFxQz8%_hvg|oyn9E|vz^cTtAVnoRS`Aqla{Zb4##4*MM4n3W)oT~ zZ`=4gHyTSv7^0Dn8)jL1KQu*?nI05JJ1nfS@k{4rW$^P4;800|yUR*Fx8%*kpiQkK z$TRMY`tV#RhNIr3>FhAD=~Q#;-T=Gn55ozD5`=cXv+~dAqqT%Znt$=1pKNd+?kqhl zS-L-T5=zN;Jwo?4(}!M0gA+o8el_lQw6vj?IKzlPg|wCzac;^#FL0^}3FQH02quOw z7Bs&2b;G5=@+neCyJ}LlIh+C1wC90+csRV`5VU65ZbB-r!SYUlx0S%}GE!%H*l@zL(EsY3AkK_-o zCx1oE!EPf`C5U$LZ4f)I$4}d$jI`x5I*T@05Ky$fr2alJf`RBGJJ?n>5;7boiheD5 z)LcA;^e2IVz?78tWX$Whot5Db+Gu2vH}YTIz1ivw=y|9hDPsR6wi`<`n^+RD|Lv08 zdw%ZlGQFmJaJ>f#D5~{JY+5M0=Y=JKG_SGIyG(8j$$)U~nRM7Vw}-1OoFfF760yn2 zR3DzPsfbQGWo--s61!z@{y01~!Q5gPH`Zy!tZ0#EA|{GU$M-Hjsj$GC=))Lq>Sb{I zYTeG`dfjX!?~68@lZu0)iZ@<*BF)YjPtE&-?s1#hb+__I!Ddo~$a|tL)ZOJ|rO z#b;KSpdDz)M**zn38p(xM_1u%jOjWf)-)aeHM zzhwC+6#70kJy=js6M(68I`|dTw(dRa8`@ z?}ti0ta&yc*(YcD94|JwKCcz|-ywzOp(H(nbBVnMq$0hta*zCtNBifiB7YA)O5e>q z`o~$em$#2?J6w_{(F-X5dx`u;=bh2g5t12 z+}p7%Wo;6db-`=|5s-)^UdclQyt}%({1rMN`H9qml#Jr1j-V`q2afb0=z2dH9EoX| zAKme(55qNhLKh_j7N$5YTh`nKIZ{FPo#(EvPum5;5tOn<=Gn*>tE&mI;w3>3WrbyJ7-Bp;RqawcwIAHFO*Pnu>zpMs&QJ6b5nGAT93d4ZLr(M}N9L zu^W3jZFX`|#P&*M5!+dt5S z0N$%hBi^g$!?DLAUL-I7JURB<*|c)`b>p-cvENuuf4|ALf~@Dr(mvqwMGkOlnme=0 zD~ypA;JeF!XB{atK>X=!-HrT-|KFKyRzL>Gj~W16`x~&41MCbYY+geqETyVj$4K1m z($%dz{p-r|TE)M9KFGSMGkt`#1$cU1UoALFjsKE!s~cTkV|m)R4tTz<`1#ZC@oxaK z9N_sn;9Ml&e1Fb26-~p;YR0|!yjBV0sJUS1uXC$`bg|Jh9RO^md1}9-pdqo~f=%$m zl&eKbk{pq}mc5Uc%!g?^Pn&`gm}eM>bF5tY2hTs{h(VMQ#$TLvjwgr?D_z%3 zUW6Q$Slop}lWqGeZ zDL6Ux`w&xolY_T0EyGMN5okfqm@Ca0gqV+~4kpADfBu(Cre>r4&lV0><&+%;QwA~j zfC`3DQuxqkauxDn+3PM3<$W5Q;pOT<6S}(7&Nk(_bhDq3?H=%U)sP#I`!&*qD?(C= z?oC$5javnvJy!+{Du&x+(~*o$k>XW_m+;3H$`}7N<{f==@7OdtA6|y~HG^EWm|dBY zJ&2q{c3T<@LSwj5(RE>U^JBZHfx*$5>XHI!&H^VdrtnCsaM0Y=2eUD4aHXfd{0+7e z!mysDp`;@Bt!w~?7GV$HlW8+;w}(hhl(ABUQO-_fpoL(E9ItDG|6waZa4m?%K0EwU ztWxZbRAev&8Z%N1USp?k)Ypke1)`bLIW613Zf*Fy7HAwQnEY-ghBSUzsj9um;IyUX?`leD4M|NRGd?I(!VxEtuH3iPMyg*L) zX2yJi022XLS7S7j%kA7w3J}M*O6(guHrQxNfanz$F(9Pbk%1Gc&Ws0M#90843bOsR zS(ZY!mx(KoT2psZ;!Ae}dYoArhS$hyd>~-pfRe5l=Qj_s=k@9RCY7`tn<&osmKn!o zNZC3Dmj7O|pZs&5g4ET-K(PsOTU}(hf{vg$dSySmdhXahe-T@#B#1(pL1j3z5&ppN z8=)dOrw5x*U%+7u0S-^$KI4i146~q<4vFrzA&*M!p&UV8hS1vEX)QCxcA$DaHULmj zJ4&VIsrM@m+-}O|jEx?izgyU`siM7RZ*68(JFvr27ioIj(^7GWXbaZ8HOlRe+?i3dm;bS>LNWx;<{TW8M0;U*ko-GYWg&;GigY|On7iNwDQ8$Lb;%F&@SZ9r%v97 zPN^HLXS2(Ht$3%%vcA^q<{cUov!jPhtY0Ea{X1OCU_>Xsu$ml<)XPVMHzTunyT>kR z-lO?T_;-&AQ{x4RYLQH-`$acT)^w6(+C3+UG!5&qk$0b&4QO@+7b?~EenhP8?aY4) z{w&w(RsLg)0ybU!cRF^=?Dp!MS=#$-?$%CN!@kwc!9f0Ilf;LAhE^2m6!hu?*)3R6 zW;L+pBH5r(2gre3y%^2slD84XqU)fLK`mnfYJp$vi?yGGv%H4=@*v&AT%=@GDRjKFS&r6fHqzwgAh63hJft#bOqd!rq zZ*w8Rjp2tvCT;~FPDE9qgZL~YEyAM)5y)|@AG$a=lnD05wVW7tnnq-(bkLMxr;rNg zB%L86Irurh1yW^y%*EA;t=i6bO+0(Y0-QBYo_V!%;1hv}-k4809iDk_{1q9jI|r)* zg}LHnJr}-En+&0>0x%4_GH63G)pokvrTL6p2HCwyXOas#Lf@R+Mw}G9TK=J+#n!d) zQ4Cu~y!rwyzMTzDPJc5)5d0&#ZG~b+l(Ft9hyE^Sn)&vu4@qm4JlVed^Y0&_eN&1C z1N3EA^d(M969d=TcNrUf43977gZr1bz z_*$*B^V><3SW6*>smn|Efg^9(LZ^>D&fY%U z8L)Yd92Q(?^AHS|)2t!8RLdf+)|6-XKA@M*-V1E*V8Y|2O__K6pm{`M`(Tj{0wmG z^beb@E2HppN_-X2B-bRxk%aG|=Q>o8f3tk@n2yDB%}4|eIlU_}Ogld2VcqC(l9*dc zceIbxvDFnwF>Z2kw{&IJyR>uUEs`)X6#6Syp>&#>(p3R2b3B;qU%0*Dv2f z*_IQ*iiju-V`PA(1aUHyq%+?&uu02lo)7#^fUt;f{2}smAaDS%ev>v7(BadBeCWtV zVyStR|M_Q!a4}6JH;s{<(-Qw=Dzsg4h}bMGCh@a1LN7OxML0(OEnfVS?3NS4i9oo&p8U$~ zViJ*e&}2WuLNxDjy`EYVu_G+}SApq^=MUiP2wjNRzt#nrpKA63w%X+gr?thI%LAW0 zXNZq6XSCYux}f389{_+GFoM9zPS*`gV4#w8=O)5$^dRnSEh|oC9oRR;JaqQ-jP*O8 z@Ue}?>-FQ8cF~srv9&dSPb@WK0=+s@cE&*h`k@Z$n?P2&N0RHc2dvsP!mlc9t5s^u zFC~NW^3u@g4`B+c=HG{r-_V|f*(kIgEm0i-8!?C0Xzlw>W&e82zSDB`Svy2`e!HWm zE&kF;Im!xU`arOZD6Iz-#l!Q8TzL3)|88d6S4^ndTQlqBtX*Tu*!HC~9R=j?rP&*T zSd?*CN^p7@yFpJvoWz}#&!_75G+6nXBtPCl?90E-jXD&U4rJ?1WTY8Pch}CQ$L1H7 zVC4U={TsafkTVI9n@cCQBKiw~X(ih~hX8&b$3uGg%PneZzuBi7tBYwm zQ42798jYxp%^;5`9O*=dl%)>j(4QB|hYWaaK1Och_3+>h>sA?D{HbCf<`>jj;}U?C z;BICB_*8J~wbzj241&J@S>|3$EG}q~#*i|hePq@W5`^w&q7Ibl*vl+3t{rEzxAxqr7B=KtDbir*&->ytyU zwL+`dZ!GaDtrhOhr}1^CQTyzk3I{1E$%GPKHCEdC@q2YHHmhZY7_6fdD7~m9ChWT_ zZeVO)cz!LB(xut#Fom@56KOiccIM3s+_m!R&lc!OBI=o_uv<3`HMWC|DOR0+Lu5eG zHyA*5QP>`$&-BUBN4#dl%5U;J%ZTcHhnFS4<2Pnm#Hc+4p1?_PxM`|W0~J=`C^39n zMi!(bSwkeGU!r7R4ai@tJ<9$0F5Wdg#h$^i`F*-}Tm~Q;+UNwm*(<8mQ7;lk94!^v ze@NgI=ryyh>(oh(NBP2L28}gO0uRqlsfGom3dm8Z#CEkX6zIx#0+1ppr1V21@l~=B zFqe}uvez7sJI?vMru z11i(E_VSpV+}%z`%#dzIB<{suEr4tQ0VGfmrZhV861zL?uLtMG$qSG`SVCrMONib@ zBK{1>f!@feF`)6qe$o>PaAzdjn`7dC0l?mu?CN1I7~jOH6uBQqLQF(1!fnH=C|aB11_ z%5VP*i?!r$RPMi?F$RGP#G^jXK&L&$7(DsAuS11lSh2!Tr|gdVyyjPJE)oU>-!{Vc zTE19;c05*-L|G40UUO%KJawnRleBEMfw9?!!?ckfF-LrJ5SPCs-Jy8cs^h}85r$<4 zwwlal)do{tD8;BDJr?}5Q5=}=?ZKP3ZiBQQ6b;mGKsDFPm69tnpBO)-5L8n;va9l9L<=ypBtkmD}!EtA!M-;nUd|^=&2N^ z!Vpx{Ihw`X-Hum|XTN_z#(v^+6bC>94CLm@qY&Z-j{{Rc-McOntCzeOIvCZX5f}r0 zZLf-^-l#EyN;&5&fMrmvk;yrW*kI1hj7PQE1{_#gNl9wB?T7%pfdFTqbO71ExHdeq zy13VI$Nqh+I4xXJy`1!eiKuO190aWPDngm5vkd0^GeZCn*fDCfbI!_OXOD*kDL{}F zXpwHC9uNeEATBSJ)FKk*F9*yt*PMV*pYu7pr1X5-ONO8lWmeeSvYn-XG??IGc2XSb zWIvCZ@MTSSt5%KU^8yscQ-Z;OE_>tn)J=cC-1c--8?!6=-K=Hj;Q2SR_CNc5yHfCg}6AZa;NS7`FIh#1&0F#)yJD)dDNc*r*&h}*{vOpPL}a|G`!w-J>08X?bP|g7!Ae1z!6X0eM;Z?= zUax-!(V7y3bZ>diW$s@om`U{gzU_8QBEUrf>Y7V_!21@Q@j;elvnFa}=|G=CZ3vuq z3P;j+CzNS(Z>)b})@*0E_VzTtj4o{ysOcv~up=V&OoS*m6I_(dvXKP=x`6DLc+v}# zAA$|^Ip!>c>7qilaR3^gMLD>%UskTLa}ZdzGout7uY?RgtN@To1wxpTV0)(9n=k!1 zQ06Udp@+YB#*UECT%|ti$l)SXH?hO(Cjx84*O3pgP`Cw@joeX33AJ^!F0v=jJ7p$=Y4JkIAq#AxI0tNb*ixR9Sga^*yhrpJ)vO~mH( z0EgXTUauDcz;!J}gbP6`64tY{S84J*sz|p!v*xWkzH$HA`2VOO?;_s(O3C=xL;e$} z0j)>Ie#zC-1i#cYQ8gQ&TwH$D_pA@_+dvXxZB%lPNiB}cw*)?+CapRDRB&KTKh_;EoZFt9%N{k>ud&g`da5)Dw)R`$JyxRS@@>Z>Ou zLzp}lQQfi6)vC54c_pdbuYPCh69XjkO1d>NpNzwg8eJ3)hbqR+7nv!ak;y*R(Zc}$ zSWB}fMk(6Edk=*T#osF;M{~333G|0ql!w7h6g2njU331}8^Cn++Je2WHeKvbtCN(k z7JOWB`t=JERWgOo;eqhiFmIRGS6yV^B>KNXJj%wT=X< zdhl=xyc}9+?HKt;DsK(|F^G5;*dBahO78AMyWi1gH8Vr>tal`wYx2I zG>5_)7ho)#+lFfV6@E${_qft7f-*8?nFK%n2uozc=R;}Bs>2Y`#sC94?qRU#eg14s zcX&OTZ+Fy7tXuJEc4@tY0|4TicS7dXN3W!s0DM&T(%8&Y(VQwxH(JvuDj;K#?Fb)7UA5=2mM{{-;R)ats zD;v$yp+2j$1)VAL&%x%iEDIsnxe+6udgHPc=DjvKAg#XZM?$l%#*R7>|DBkM40KiK z+MiN5H03#-Fo~a9C!yZ?oD>=$;WRHnL7c`L@n{uJCWu@!OR*>(csdfaO>g|>P)8mb&!>BnqcpsJ@nrGc1>w{N+=>-Sz5Obg`= zOg4gXe{6HJ#R`PbZ>8+`S-yMul5wmKwGwPJ{sDSw%FHyyfQeo-yuJ^bUtAiSL&h-9 zNb1COTkmh-Kh)kTjVez2^w(2b;rI4;%^2!{Hs(~GXlR9wxho`1%0Ps0#kp1T^X{ST z7h`km6!#A;+9jr>ZRZn&%(MiB?kvmb^h`7o|DPG4**$#hq7^S~+m2R*n|9HsXpj+A zuxA%(#|u4^ejJY@xR8cJH4}PQuBc7$fbrb=+k&x>8b_YIv`?+1>U=fn z$HlaD!X(l~Tx_}88~MB_IFFM`Wd)FM9Nt!>1SM)2gQ`ui{rCFqE^7D-K{Ba+&Xxup zK02%?YpfMYhNL!C6GHR9H}zzrbmAF(iL?(kqfN1!db2G~TlQ4%2U++_aU&6;sOP5l zKjxMk(KoYA8O%^W)PB76<5OWbz|vBrkI}}`l|HU@g)vO&D@a6C!&Wapvpj}gS`GxL zq~MJFWUVEI#4E4($N*=kqkiz3z7gSs*EHVu-nn{>-m`vvSUKiR?$k>bLvGpHboNF^ z))($1`xuJOpHu7`JNdJ|T|c=|Upj*>$Pe0?DD^#~=REk72zkVnr0z{t>TaRcQcoib zqVd&Y>6cc;yhcEngvH*Z)8&S?bmQu!}ICyLrpLqQo9+bxQ-Ooj!kCeE6j+`7<5B^MnS1v~R z5SF5(s_SEV*gi&9g+GkMkV+CRxLP+qu_DJt$rx@tzCwwdGqX%1@gyuOCOK2pQ;w1P zPmtSq8_H*i#!8M6iB$Of8HH-)`O+WsXE8Na3@YvG8jR@RDb!~spvE1kR)Rp}Q7WQk z+eq_4VvVEC=QsljM@46PyfHF7d3I{uS)?EuNNy?1l%k{^*Tca>!OZL=qU@N{;WUG* zSJmX3rYqAvDw5V!{)@9nh%PW@;a>o!uqVlNLL>d_fB~EHuWcr%)oC{E4TlIXDHVb`r!*t z5ar@Ug_l2Fld#!6^jPb|qw#Q(Jej7Ky7CgZ8P4Pw)Ki*54v>BJz7iyik%>>+?r5Tx zjdI%}h`Br~bR;g)?VvaJk7%4;*;^u?fCgk$%;WEhnTTqX zFw6AlU;i~?13;K1_|WrO_>^f%c23NZP(TFB=QL@FvBeY9RYXnH5*ii2?)UkKgdSszkoIEvfbT(WczKom;+T$_ zHGT^#1 zo>TVy%-!7`ke(b9(ssxZ)z(&Dg~wH z6TU0AChdDvrU|{L0SSMtkA~y7U;}{$a9b;KwdqFpXo@F0!xbD5tC?-iTcsx77EwXQH=SALECsD8=m(38>+Lcs5|*w$sNk z55LoZ7osp~PM)@}>P<=Wj#At!hh;9=OcTe)U*y}wQ*$>k7fW8rU$xal2278XzveAI z_7smNhihtmY^ZbXG7#TbTr>wXdu^tu)E4*#+Z8HYtbK$xc6N3KY*w$-GyXr9i6=ht zz9jM~YUMs$)R*+wp!K6S<{z`J`}C(+un|ic{*kxrUq2z>a-8o|QL9bhG%tuH_@p)Q zF6$*4;~?z|M+lc~#GU>_%&2~;My1}@Ri&e*hd#4Du_q0Sf0^=}UVvlTyK-BKjS}$u ziSAV67&M3O9!>wO!G}lBfe-l@bLVsW7$KYx&A7#eLq%AQM1p#6_g5^ClYoztz&`AK zp`xvR-q=PVF&xH9kgN!O&Px!cG>Wvfg=;b@+d6m-D??2S$oHhWK7*sXbWi<>@712ki&^K*Fxi7nFA;iEGOmsZS zjM>{|I@O)N3Qq$J&~0||g_H;&3@2#8L`Bkj=q|+u*9B0BxaL3Jb9O7r7A461q5O>p z2GfXpL_$~SNw)!Iwn@_`?C$xbrYt%Jjf23aC7|MrugM)I-02uFd?47pYU>28awsHM zH3q2+sm&D?Reg-KRRnzR@goO-oBC!2>0NT9I5^i+xgR3%QFDxdW>mCe@5IyTy1en^ zEU=b7H07F$-?^VykwrZR zGtU(t73GqQ%iU;+hiSN<%%e|snUc`TeNNa6Nu2^#avSYkFTvWY(Tz<^qy~$`cs_F? zv){44Q2!ehSOrQCW~VN@e~H8oar6U~v5ghJd;Ick|F12l3_&hb)gU`sqtwcu`E6AK zJ|RDqL`G^5tKzELt@t$asYsF;r=Rgy({*%qa9NK^#ZH#chl$}T;b4-DiW#3w@Ib9R zQ=<#&*^_s3mDIX$WyKYMB7q*Zqy*}y2Jj}Q`*?;&51@!8SPaRm5PF>R5oczFEH=LHm)^fApZzcxqoku17zJW)JuE}DeZ^^QQO z!{*`d!S59^cl|dF!HR%T%7y89gu= zWk^xw)|sBMwuB@S;Kc$z*-DaoXQ!)-i+z)->+rz(3ENR*kyYA!dZx0a?n60&nNKc9 z&Ti5g<<%r7?w^Q{Od=vbHpHw=YB4x5Z=)VtYe6F*mVdS9zyjnP?yrAsqR|88`kV%U zFZtN_pK}ON4x;Ad>P0{maYhvPI|7kWpHhC8O5#FIGd`C-QqT*=gyQO)3v1jZ+SWxX zJHA`d00z}_-9U^<%$cchE3PS?;K7aHQdD(zNnT}*M|=tm%{@i&GHNHufY`dkWM8OSk*4FYuq{+f~Xew`E)h~v&L-m_qC$7!jDRF{s)Yt zmtHfpCKr=dzz2Jg>%hFBN;R%J)n;zQ3$A%`BP`LY84@sHa?VgbLHDR@$!mN~*iQcc zuU-l<1||y8ZKouN!MELXa|}6o7!yHr&X_vGjPTT^SC1H|JJoiggi+ZNKX(GMc4_ovp|BVey9>ioFnD)r9gZ{7zw6mf1=V?Ut7$eeb z^efm1Cx*JiS+z!X!h*0zQF*lo?t#t@AHv*MasslPeVw&KpIgo+z9C6ETpXayy*${U z+_!g~zbCAH3Jc=o-HUq0@*f2o{DYv4XX1kD&G5&e51CVnPi7)?wPU0Vbq%Vr1jwy~ zAHN3*M|CWklx_15G(!1lP*T}i-Orn9odrWpZ8ECh=0IC1-8m9HF zu}-{Ttb(70GrAUWg3pM#NBxACP6Vci+9F87el6KV`&2%o9sxJG=;cu&~a={Jyuev-4h*P36si<4EV|93;0}3@qikeYF9siCm_z>G_n3@1{-q6 zhUcW(J#=W$d^yNd$@v0Orhj$&weGZM1b>FP<%h z?!U+6^d5371Uqbx)hJxOckBEniI*fqs6jvvMY@Sb2W^)sil~SqyJ-PQ_Q0KCuU5Z< zrK2BvYZWCvdpq=^6e5 zKT*k?WP_(zKc|Sx$m7nYK#yI50<8C5?)Q?fyN%xu?fpomP+5N9gviu^#*)u9Ph#r> zHt9mPjljv()hLf|H#E7Vb|LmW&pSv^R1Yo|l_d=RPVyTKjTO+pq2=6q*4zmyzl z78|YEBrfaU@QJllKrlKMmTHrRSJa;rZ|=F`#T=3%{w6-$@txiNc<6s7^*h4ORLejW zc>dv%Z}Lno%(rF@gtn@PmV{afjROfS=4YX6NE@9r%|OZ8zBHLZb@%+ANcT; z^Q)cyhis)P3&F6zzt1O{I&Z{nOZjCgE?hPN?rhO{m#*`!(IZC%*F8D|yXzyj<=4M} zHbJ;N-_x_RQ1RZIi>?EPyK9T{xUTrI&b5CQ1AnRf*8R#96@I4?#Q1o?``S`z2{<5% z+*i-%b4bTDv;dZNRjn0#J6b7FJ@+t(UIOdj-%&-#nPJsm(HnJg?cy(FmP`OcbDNT0 zVbu4fuTI&d#2GoCW8`sqst-O-n#Mi-8ut)@pCT4jRP)rfvjokWQ6^C`>~|vCO~1kM zjftf;;MnoMO$?R1^xcNcV2%~4rQK(;hwqTKy-nnvZ;pThK_(A#QQRr#Xl1=3L*L$@o_o>4ia!39wIo4u3v_)o;!F1vGB9`FXU+8J|?#$enUeb+1i?sE^|87y?Nueu@d}kY4V(b(+JXTg;q! z_K_dZLNj$Po&PRx$CpBX;oHASiRl?{!UDf_`sS`M#4^ZRJgAN#+tZ>9zhXaICKqez zJkQs~^B~$(dHg;iEXI{v#D{QCrWndX@bSPcZGD&~-XMLR;08Nt*Zh3u_orW-RC!FouoBQ=RalY$_<-2U z7%{!CL^fmxc#f3(rSHr)NFXD=P)_d5$Q4$-#aO$3!Sh2 zXj*|Rt3Ar+TYr?Zm*dt{%G}Ye<-!e5F@<@t5&N_+I-_w@X0|uFH^Uw`TYflDD* zyCn|!^1%T(GReOi%jZdVmqITV3ho|;9x^O^ufZArZ)J1*r1JYucxY{CMsD~gHUw}dNlD~l2lfs~c?6Y>c%KYV`|><&o;wnyu2`D7Z17ylagEi0M00ZHU5 zHq%ss_m_nM8kq+2jK0Mh>H>htnpHN0kQ5Q<`%EC``lOeV{via9D(sjbuF(TLhNF+3 zUyc&JBV}hlRq(%a&K^#UO{!ZXt196WFum(=>y$^Y`-a>V?FtjnT)kGcaqga^?l|@9 zdPG2HjVg}(jgjr=;b@JkKU%)pRIUDM>QmCXUGGKNQ8Yt&_4AuLXKtQ_;G44;N0kd^ zH`Y4ef}j9;>#{=7doW|SFnMCugE-^Iya2IJz@eO4|wpGZaxux?AdDWpcM!NClu#a26(Pn zZ(HY-zH~Yid46{GPqu=e;GKzJKRBagjegRLXc@&iWXxwG)-@jucnlwrLV9FCDW)^q!$g4=a-;r*dIhSl{nZK#}z^H3kCY<4HTv>F~%JD7(3Nm~0#V-s|>+mwgE=X@^-FUUo+lHBkn z$II8^LJJQSKd~PShZzD^1# z+j5YIl|Um-m$=^9#P;-etA2Lr9W2O=;t``uJY(1oSwAo0-LCcsthh}WywXzC0FS7% zD>x8JR@|?{K9Hy&rOsADAMM}uTrCB{?l+9=9{ULm4AA~DT3S%(U{sJ}*4JKK!VQJa z?1b#Em^6*F3e~!`wVwME4Z%F#{~0+Yc+0%0_AGzV*GU9` ziPheV=yZCO=D>*U9OsKJ;cIbB!*7`M%Fi1<@rjBkVH$a4Zk|c+BePgvReAG%2ULQy z%45oA^qz5YtZ2t7YIVj4myX26H9F-T0bYAb0JtS!q7OxACMFJVoAZF>(_1XHNqXC| z83WxH9I%p2>$|_*2VZxY0rgCJ{QCSOox2PIBD6=fOpfIh5wNkTtDget`~g0mrkZ1j z!wDgyhvI5gmah?dFmWkac^(jiMgSvB_)BaIvT)j=S*1E3623F~MXP*`g}DHiW&V2N z=g(ESgU>lpRk6A99e&62)bBs&Z_x*nR&NHRkpWnkhwjHvb3|&a0h|LvqWa{H{v9w@ zQeu-o{1OwmY7Q~gL`MgTeA{Io67LVZn||Xa4n4xp=IxU2za^I8xyjX0sL@&WduVjN zowvPkc7kK>x}2D*S;!pCD_VYe>6ZE{G?CT6yM~5}=#rpjZ?F%TSN2_YyydC8n6SR+ zBx?Z&=v?;4n5i4&Q(=x(3aTylJ3q}k{W^X^;>cNFK|fy5h-wA=Do~CSR>iRWfcmO4 zk4(+2AzjaLxgWgFn9F1^k^5}_SHIGjqFFS6oKNjE-u4MYx@n2tbk1Q!DOPX2;bqq$ z>}{1H(%AFGC-9Vk(qyD5K)8N4lV^ZzLH&OB`d4+&yWQo>`Q^*qq^(@Qfjg73C6Uy; zTaH9}sXB8e!U3|f3qpJXSArR+!kn>Fd!hWd&MpkZ4}2P54n_|{ z+&V+9Kc0n>BA4;6S0Srfrg6@^5F6OK?6a+~nsLVbVwR4UxLN3YwfggKwj|_ula*2S z(O&Y)Ss0tM(F=LkHT-v4WM6>zTQPdxIJnHZe6w@6b3YcJ402_Lw(=b%v+$GNb6*K; z@!Mx+xjB7sejTz|oef@+DbG=f1V-?}`CDi>IVrH=q{X%X6>E-RzWzok`L$eGS`Ls1 z4Ko0=>)O^pUruB56oz^vs`$x_2Al+F&_J(R&&`--1A(t6+id_G1G)cvWCZBtxCH5| z%IolUB~C%Z#M#~Woe^0oET>;0bfkx?Er_$QxvR^_(FaX8*T*Axc4|%Dd-*~vtWV3> zmugP77NNH-=KM;q7mha69+Z=XB{w4d#F zUI~ic9hWL})SL#fSJPlBp8KC&4y0goS7@J)h2Yf82X; z0Yl_Rs~m(G-G>W4smM<9sHTJZCiVi#8ueB7|G^wNtl+{wUh0(>8|cc+THtq>LwNct zXgToX*;{A~Fqt8k8zid#Vb_N^Yzogh0O2%vblDfg7(mTtN%GCCP6iX!Y9XAY{+i)L zW!Xw}w00ReF-oETHYIR`VSlj-SLh<3ayHK4aSWq#pnpqNJ%?x^!S9|F#f%&)>w!YA z#;S^4KlfUlo0X={yN%F)zPCR`WTN?FJF_RP@-hNn0m{HQy|&Jg^4wgP4^kP~2wjX@ zJK}oE_pKXY&YGAG0|S;yp(yMB2rHv!!&lSuw^nX&U@y}O@1lVv-K_2rhhHV0zZGz zA{Vx!V%ksWKoj(><7pk0>lnfQ-J|`z`Zn=@0_w>!&@WvdtXFPK7A1{toL5g@6#ffL z?4!t#YoF>wHuy-o6e{DuCQKb>I}F989gZiRvVv2MroABJvc{yPoUr6- zmsoz9aYXft3kNbZ?bR#xwxiXRJG3?) zy+|7&x#ZV7s>$cpdBGzZdeB2+kuKMJ61y`Zwie7scvQ@ze-Pa3Ty-$eh&EXN<6+>P>t|oBZWroTuI79(Fi7LB)@1m z%0@53L34ZT3p^>&5Rw_^H;Q$!E^*L|w8fveRP|Y$DOnD5$FYjV1{;xyS}=g-6VJ)SL$(;1jt1R65wyKD6J&CQaIcBx1f_2-BAo)e56{2Brlp+`Su z3`IdQVCGgp;*?16cEw=) z6=i2Eg`v1z^ycTxRk=RET} zF(+E+=ZEDf!WbXB`7;5fi-#`--+HjMo0fI%tKFB!HrTBnU9F=@n+%)(TW`8jqt+E? zXQ3YF6D>pr?30H*pf+Fj&L0YNEAiJZBnvBcv^RldH`q_p@RAI-0Uh1R1OW%WYh-Yk2x~~sM!bCpcA5w5(C0lu zs9%kkZk${QJ&QTucdSyl+0^O!msZn$bBe{Q%vWH?aY=VOlQUx15s47F!`C*q-o5{C zeaFhuYLnA45{-{)g^`94neqc7|7wjr@+`M>4{9$Z>oqXyPzf`2(uAQ>Q9FJ({b&GR z#^UOXgC@p|{JEbI>IF4ns;Pc8d_YSi<+0_#_AaArjsxteBij#hZYmm|q!;DW((&~+ z|2Vy%++ke@%a>})@2!IU{af;I@sUd&X{~?fZ&Wq-oEoPHJ^2fV+t!p;R#$_c!C>SE z+ZJ+c15ALA(yfjT~-Fd^# zNTB8U^1%=oH?N4lo#166UIrKD7(U$P--*@S(0x1h{06t+UH&m~JdU`-t#?=Rz!l<>rKp&>z0CRb@#5{|9x7_}rY`Y7Z|X=$K3Fm_@@zCwk&fv>OeXR})@XcY;hE{M4?T{T~hEL|@zz0}sVaNU=|K$$w)%Th@HW|~X>|l$1 ziMe6aOdlk$9?Nz6rT|NJiERPSN+F4xuSXLy?7_~ZyKt6)sU9{ON51X2ll6ciGAKFv zuz#+9VwDRfDtek2!*7|zTjkxxdV0!0M$_gqPY%{W52lj!{8g?jj$%w=W3_l|<|^6i zIaOiYW(HKWUx9asPx(yjqsz-O=bBjuFWvzsUsr%=XetcpNGvt>EF0`lPl|Wp*HdN? zPxSw4N}2ukqm}9&3*u_W?9j18j@fhZp8vOqQL&lG4HSZA;&F2&y#OKd-QzMo1IzEg z*+ADEBtYw@x>x=Kkr`=if9)*fyVX3A_XhXt%{#-WQatY~;^_dfqyTjJ^VVioeR4Fw zAdU2UeJX7#3W@F>)pC3pWzI~&p=N$^U;R~rTNfuNOlll~CE7n<2@)l*KN3_t zPEP)i+I6wF&Ho}vA4>!nbuetu$#+epqDQw4MpvZ%lX0sAxaV*1@-pylf7gN@Kf!rq zW-apC*`Q*P4a226g3G~IAG(p<onOz)t|M+yo~?_B>mBtTZ5(jTS1LZf~) z^JE0v9^2mi{j@IwD=+@)tCehzJ&W_m4T=v7>*MsRqPwp-|57G3CR(IuSQgsTW?H&x_tvMn62eRle-#IzsGJ!$%tw8THcl4ZrG!-~gq zbZMWRC0Ev8+PM^HwqvRyD=j}72Y+l=PDhy(ZgCLp8adtar5Qq zSY$>R_P{P{P~M-=W2+hV2eAj)ON<@WnAgyL-ZO!7y0jk zE8N|CoLk62FZ=V>bNAP52ZYXp$BX+xXBXJ9%OmwbJDuCw*ar}CRYmLR7lKzmBHR9@ zpkT@711Deift*AZny~tk!xCZb^67wpMu)=vEBKtGh8VPb`!P-f;#5^UydL1G<-$xY zobh!LZO%Xu26Uo>#r3!}+K}eQXjTPQ$TQpz^T<`@mgsa+Vb00xt9Mx`xU%aMdSa1Z zU{=iwSX{PcyWP&yPk7*=MhI|3MMidYwd8@>5)g5#2N zR9xI2OhfG|4A*&kYK4ik%E`v7EVpfU>w%cuD~a}_%Uh?xhl;tSkC>NzIwobcH_z@4 zyfQaJPjy1^;Z*(sp7|vnZlP%im)28~yK@Zt-3~_KXwc&B5FgU;e&Bx__j2{quI6(E; z&o?lDApc$mQ2h#Zx*sfEcMB9Vj2E=Y;vTV+{GSC7Uq%6a>W(uGCBY^5-`R zrY#u*=KK^00BQ0S$ji}goiR)c(2r_6Ruxa0&UgCCYY2$r#CWNdAUJU2NcKm~ypnIm z0y&*jbyZ*&LA3sGox|40zZHiHe?y_tG~(BqL#MB<=>{Hz6P^Q`lPhnlJ-=={%+=iKAyGlfo;QqS7h zsBd%HP;z#KMVdd=VoO5V+3%S;Yycz0d%Gw2-fB=fS;Qj{Rj-#v-OZYFc5Fj9bib*7sr14SAF#QNr;YLjqY*B`fLX2RkMw6XRY=X;qu>S zwrBIf{WmQRUE~1vpo2fROG|fK78ex?H*@2iw+%J0WF7gNV~guocZ-8bZ0~^*InWtzh1*_* zYv#MnyQ}_E$~_HyA_`+8muLc4-`}Pj0l=Es8{C8P$5JJgv7{s}vgccgI9uY<7XXieiS{GZKU;~W>M1*GZNX*O*!J6gG(6hBSC+2F zT9oY*+_snqz+1|+?+aX%yzx{NqZ2@YN*n~CtJE)h9AT$D;L;SB(-63LUZ9n6Rg7|? z%>#e3ec>qy(~uXYDN`0Gc3nI8Yq{WxNRF$In?fb^&|2jW=sBYQYuE|*%TA%{0UJ(@ z&GASqwR}R2%IeHTlcEM#f*I>2Tnu2I3pJ-7G@MXR_E~onz^@#%^!}?eEq0ifOM4+& zz7kAp{jeEEC#Le^IF`2N|Vsh{~oP{Pa-rhvq^+g0oBF;zro757bwsI*-ss_-*JxV2#H4-A}Bch z_Q%K{4D8w>AL4$cmhgGIi2bbph!7VhRadVtRdpQ0*yh{JfE0(U9arH<^X+Z|#XN7j zR~e2ziCI~h2z1MEPlyHVvOi@oJXgh9T@kX=5xcW+Sn6@S#Kp;|)%*I@Vb8j(|DZfk z^6tf4e^1Y_KM6!oirQ)en41ofPfvx?nXvC#p?6p^QhliYzN3PC(fc?#>*X?2p0!~B zi$M5m|B!FC1;oGhe4!$0u2X9tVxqeQF>rcPh*yPH{~P_6i$EGXsb2pF-6Wv$dnpV2 z-x<=!6VK#3Qvy?WJXqVLCqN;~CIlbXYR-6K26lb)imWC(<50xbT91lE>s6OuAox#K zJSz&Jt68;=vPxLmnej6y;Xp+B=o+g~_B1s?INusylAfA*6+-6;9?4mLw@hQ?v58 z%HKiY1L&-+kG!Sq`IHF5eO8*_v+X2FhKyo^kB)%&)PImjysCWY`4qC#YV3JAcclaI zZa@~~lK1G+nOCLDiygsf+jDU7Ncd}%Fo9_M;Q+O0juJ)!TNiZ3>_(Zvz+i_HIqxt0 zkNu~+c0Iv4&}V3?AeVCaVqiPb1gdi2n?KB8E559#9fORra^EpHISaXqzMFKrK3u-d z3q7uK3qIOeVUd4zJ?ktniVmR^Ka!)Qw)ko0S8$(X$#kT1lydcz)_$z-QryEoe!)-b zpB+9GGExq$yZZO=Afcw~s_XXbR`Twb#qB;T{y4zr6C?$n$za4nuMY#+L(V4zNnb+H z+T*u73OA(+*MC>1951Lsu6)@Pq;JV4oAF5tjXmvpa6YI~(KVCQD3oPlcO7cBPt{P~{-f zSknrG^S6sMdete_25gved;nk5AW(@faU?^x?ZR!pJ81R_2aX@5PFBWBjbo%}bZ5kO zSY)h0;#{~fy>c3*aN#6X*egLan2rDkp#Is~|8FIzf(H$TCAi2W43QixWif?u7L^ll ziNtBrRXm}>*0~ftIus%AO%IZim2PftZkMuP@AAE`?h=uE-JaA! zGc-lxE%wlox>VB&e6LOqf!3Oo2#*Q-z3sLe_xJQ4p^u9t9qp{xAr3`;wDy%Tjmm9I_}OlV^a3ei+S3;LMWb) zM*QQk-xjz&zwThaB?a6rx!v_vJiPP0>j^!NyKR5_nx;|c2dYzNDA*#2>(=^X-xbf@ zg_%O&`zHCw?L@SYheinHHT$j5oe|*tOhLw1vX3Y9y#6fYL8l2J_(;Zc8B zmsR@f#AU3(rEIMo+{HMUl{M>)mQnt}hk;{i(xLI?lW~}%DaRqS5jB8}Gt)%y;`%tq zEwpBB;aETv2X^37M)r}am7&^l?q`?sK}PsQ)sQW%FM&!X0S02tlh)@W>Qho7v#n-y$2_# z+M3$!FTzD(+i%n)u|8K^2mEFXoERTth=udIZF-{3QgIB1#I3*%IYB4!&gQpKqR?M%R- zZ>-icdFEQEjUS!=1~}hE{f*I}19JK#AkC{w#h~nYi6YG&T8=(J->68(X=x7DzZdL- zkGejr&t+UDbma1{%zfK^Z*fPnbMXW$9-_POgW*2)ih0ER!=}4j@4KLOc8it2x9@nj zQ3i7BTda8J4xz}D9-_Ke_zb`P1{i~yK6NI66B<%bFTxRTQ5=tH(@kT_*T?{5Phn2U zC;jjiXM#!#AMDr<*}>n%mT1+f)=q(9wf#rG{{_|0zv)A+N+qtY<=Ma$-Iw%fx95tr zznb}g|5G#*Fy+Q)?$AdpW4C8A?$M-yMD!jHidorz7yFNgn`iJ#q0Apj`B&zu3@nTv z5TFJNuY#cS@~jKS^pX6mFZ}P)^_*BelN%Ehe?$&*UusR%Eo#Tz&kQd^nLI9?ZRl9_ zXv@P*o)S5tKs&kWY0?z>;$2-{{%DtFCi`;h53jU$2&pfB<0rv_(5l7LdIdrMHYbX> z^qHf2v@V2&L163s%!SXG!;co##FqqA=e*Sa*WRara_fsLGBBt=%ZSU>iv0oF$ekC2 zGL*+Y1_Bs;rzW!)fdFl$`$r|tn8b#gaJK}k^1x2CN{ zF>SO6pza}rTQ3HgEcMfKLMqzgkhAo81FDr@Q$wboz?}N=vd=;Pvy*w;+@!mL`L{QD zNWY>gas>+<{J#s=qU@+ecMB|bH^%1HewQ(EO+D!&P zQw!796)9^uHpZ26snO}`b60}bBSp@EDnqI;)nm_KFw~)CM|HAW__Ftg4w%rp*75(b zbnfv?xc~d#oRebYl=DbY4r|VHN>g$+M#))C&LQXXA?8fUVGc-lV5PTJ0Bx3#&j*Sjr1mzg~S>ff?zORa?&Lh6Ypskf^E*y=^9rB2Sr4F z@0Jpgfg&LQ&jbMcnQ4wabqTV^CI>|t1yvm&R*BUHPI?2pcAsQlf0k~+Iv#8OJN`-Y zoKxL=$OM^hYRPxUiT&C1*4ii>OaldFMPGTt)0wt}&{hdrmsJ-9*llDUWU#A-d}~sf z1&(a~m!lGg5WAjPwtPg=gxxfdf|p-&<&l#m*O?-ROdM-fh3-71Qio<6%R2GC!*t{J zP!Ka9V4nz&aY1QCMYZb^A>ed#kS~H((2kmm5TqCvX&&q2I43qT^d%R2En;VyvOTi! zPCr@eKA+#9b48tR|KblCd}*G5()paN?L z17ElDG}9PJCXyrbbFJIl?-AZiWoJX5`Fw6OO$@fr-oI6}8|>h;5`|u(3hdU0Q!>vn z;bl}@M_A25%F17vr8rlizEb;JojR9}UsI zS`wSI_vdx=mc?u9`Qn2UQ^!>TcV7!P_2{~-jqI#X5B&67>?lVOd6N2TpX{k{2uRtS z_SKPfE|sruK<2J@Uz{%D!`cExV;PFXsdT-zlZIDIO`b?JJjohxK@scH;#y5K8}E~I zap_>dun#|op~_^=(t+P@rglElM6o42m6CQmf6**Qz9%ij#->=%82U`gdcb~u<_lt&S0D?lb<{kXZ?LM2 zeNpuy_7aH2G0(VKxSyC6UW#7HiDPziABy4Xxzi_B)T0Z=IiX8rg%xF`Teu4RvyF+0 z)IXg1xl=G0+~ub9F9QhjD_df{1Yj)6MTyv%+aTWRFw>wHm2lHMv`EM{rhuN2VwLU9sk)dWhW3tQ>2(N6;XB& zXDqJE#q$uZs-WR{Rg#_}ZWir_s3Ky=b8uNt_{z9pK1n7*%3f{N7PKvDB(|@&%c!1v zP4j@$#0yYP>J}YN7(O;oj~I*qiE`AY zPkchI-y33DdrDrDf|+?^V5JEe0Hpn^`*$k_E^H#*z30P$;4ao(&@e%9q?$W1 zgj_H7xI?V(@C?@iFt!t6uOiS7>C4_gsQ{4F%AzQ)!r|V4z<`=kq^cs17k=h&*q*S^ zFyTfpr}@y>HbUi&3?Vxe*P~idBW=))FDgwntr_gc)5%Z$B@Y&bt$5BPfBk5bh&`lb zI}F0tZ?{y6R!28Q+WO6+sRxu4Oj4Wri1Kfdxl z;IrNI^ZX(NM!^B1C=MEUn1`ee$wwmsAx4*{{mvXN!CwP6aT*dw&GNDd!9+#X)5O8x zp&WbiltNKtTjLvJc8?@au`t6pyvik^5127Z^j7+vdAuMcg@H|rw{oLo2Y5DjaB@bIa=?C;RKE4Rgx^^ zU9Qr9C@3#49oVG5vdMdt?!4bX|KMP=cO=TIxFopk<9YWE-yAyn~;wAyY=U z3(Dc#Eytb%J`${a{ObZ#NU_#HIASQrGj+T@A9q$jtxZpV8%3wS{h{z{?l7{@abi?% z`ozG1$SGkkzt*6p)(meC>CZr9ZF*)mA0$4EGIZ7y+1(%rpVj|9*SEQT?;WYpn3(y~)ktUO3(brk^2Y9okuNtF?F*aZZ>EZ~Q`q`TVil346&C!ndIxB^mm6{3yVquNQ0+xk4 zy55Ig^_sxndK15ZIMFP_$CVuDXCcHDNnDL33u&E@j#;O774G=1jzx1M^L_^10)>hW zHius)Ujj8ckW740c`0w&qk9E2l>2_kS0&ok)q;Bvg+2G1&2jf!s0#18$N^p;GWwTH z8V_g;wT)iC*^%jmDA1^5*HO!!$l+pFL1h#n8OSqXq_99~|8QRIvG z|7q+S+h6A#lr(P?R9q%jjq4xY?h$c9s|zOG24;n?74~?E(hvrHv35Ao&ioWc{|W@9 zu|IK|<#>xrT3DL8APy1%XqVHkK4Qt9?(-@ITm1^l1n3&4dvrxD^99Z0D;%jormtNPODgvyHK`4XN)4nPL&7wxlbM0N*R{3f0Lhub0FajNS%Oh7P`XO2CSO zlX7sH4So*O2Rh$6rrugoy)^UY zBxit{MckeNr)3|0Ta})y#!lfGLrQ;5UdtNgG!U3QPvfY+nbE&tR6F0Rv3;31RIX?R zTg02cW2DohQ9JQaAae#Q*K>7>89-%#dWis?U&K1a8#E@yP}b5qt<47KaCLRNyVce4 zrI*^1@WV2F?G$#R3n91Up|4K}-h8U(Fa36jLi3V!3YkaNEU z@%ErqHx+GisfvNcc7|}%fJhlCZne&xzonFRBx|~#+sEB4=CT;@CpQ4!$yi&sAg`nz zYu+wmHDVGf`Z|@+K6uc3-a4&ZJWCCT5(OhL#WD`}XS`eK^~DA%c7*K8IqLIr+>aNP z4gBjBVTw=J%Y9H7y;b>DoH$k#e|Ja!tptMNazNKTZ9!p|hz9yT75S*~ddJVfQ8J14 z17GX9c<2Fu0-IxH zzh@~8aL3HHpt~FR33d5{rC`fM%(`9wos$akQ|Ysq(3egCnDtH32qo=zmM}wxip0GB zo>$e}`ub9Y(ly_phM5ctldt4)glz8?AY&tutHC33;oRCr04=dr$z?xSq;@H$x`ew#fu!rryX2vZ`u*?@QoFR> z#Rlwoy3D||qzH^Kv0d6*RH701sAdrz@9LAp2Ze>4`AHo*^oJcbsP(#uMXwiGC{#3k z%ev)L=G>qcFI=o0*>`UNe z6#B(GmL->{>p7Tk+{Sl{_sUa)=EY)^@tiByTN5K=J0%qXoE8yp>M;$4W@`81v8`>sjpZXI-Q1WMwGf%yS~+5$aDLct zJ0Lq{2aE!TWj}+=Ra$eyXQmJ@#J9Q|VNoF*T5u0=ql%aCO&7B6{k!e4zbGXiEYMx@>f3&+GF z34?HVy4e;Oy&xFoTkM1JWS7v4@O}2^Q|VnR3zyWFWAbQa4r%G>DRHo@t9qyCF^dY| zytnz_yrYH^6b&H6%T#!kCiUxH3LlG4?|mGy|LkyhA`tIXy0^S#)w`4b$2%1r=?e)+ zeN)Z1UTN~YahhdZA)WcX3(H)+b!b}_1QagoI*9Ag&RYCcY+%;yljk)cM{d~Dan3IxcK|)kRr`ze_W6LplRS`=~1`ZfgG04h06L+Ho;Ma-lD;@ zZqNS3v|~A4tmTLTA$o06GA7g3mzR7ecY5s1ry16c$5)troWr1Jl`38u2LkIGngas7 zKUgM;9(`#E?EL=yrXN9ae%*V6U4ELG&>6VfG)w609$gpq)5eGqM=t>PbWe7Hx*N5X5f`_;W9EqSu) zmi|bl52<$tK@#+MV*T=N!V?mG*Fdg$JHLK)OyijKM3$6A3`_BtaAtj^b1#vWpr4iU zTfNv3W9*1oo|=^4l$euYDl#E`GcCmrnh)L4D_WQF%V2WuYX6xqO)uJ2hh_wW-`L-S zlBD78c21wClFkZfe+-mgdlxx$`Z7GQh1zX4{J&1A(Bhjnii83zS9o@*I>+-bHH#JT zNqpcmL{^C@J3CEIe5N=-GvDQbu{Zx8m+5vu!f#9`OcdTzB-fukCR1#y6(ybM=f zyMM2D{a4Z4__XY0dG4CH{rP0>y12x}5qP(P`IYmQ)ZeI6yQMR`=)lH9*MpbK*>bP^ zYQyEgfcz;ltEQ^&Qq@Nu5N4i9z1Y*dKP?aOeQ7ufxUe>Xr_ z-F_fzDTfhNm_=MS4N4q;OHl)2-{vp*-}+T&iup?g&NT1R#IL>j({sxXK5K6wc^yz< zhh_+?vITih!^K%yQ|%p`!VD34#%`G3GII;B0zc1`-ow0QRwZ4xi)6?*_4G)>h_d`? zoon?3-JcjiAjF-<_j*x{_rh{X$#E1OOn>WVD;U-zbG)XsXoFnoDT!XvV1lsxP`Ckp z)idoSCMe4e630K?HAg;bO&h(E!9zRhaueV@VW?fF3{z89esSW)PpWZmvf{HBs(yV z)N|(l`#zE+a27{@w!7fSc{n$FA^yL9ope%cmS^g3$rc-T?vD@2PudwIIH#@(znQS^ zwDfLg(k?eOei0Cnun=!ksEn)xFPQ&|6jI=1`4AUZg2vqY1;)Se)e3viYCq$ToU!!OH%&Nx=&)OdMKJLv&Yp{b*&j?9e0BwDS&En>Z zp|dt>2}j*ANXX`|#i#VGgy-d~JoHvNxSbr`LCBT1UEfgh{CY~gq^{Rlmys~V#lWJz zjrD*jo~exnSVorc4EJ+cCAsZ$6K|)YT0oFUftD7Xu~AKXg5uC`nHxp(k*0&camjgT z1b>5Xy^k>I5|EdTb_Acw$F{6MoQ8p2CQv!u)z_M0YG0R;&iL64Mmoj+Ci=>|gXvyO+e+f- zqByA8>TJbPGI|~U1YOAIh+bnx$Y+N>nO;q#GrKH0R|sKfRU2U(fzh z;N5H!!mVifhh=XV!|oa}dHlVDkLx-QVMb;5E^|4HMKxF@xA}yuZ-I*n7$<~wQocV| zBO#owyp|-vD_oye;;;o+Bu$}dbx76dP^9w^iv$8EFcigVmF{D;B~a@Qgf&B zt_=y;EW*^b`I05%-T&Ilqffn&g|W6(XxDi@n0h9nOVOQxi4z)~Z*!PZn>PV@D1AM zbmhh5py%!vHc!|?w$Dq&(Is&RfDtWK`7quH*g2;Dkj!-{bZ0fj#(Y4g_aFIU^BGKE zabzHVJv;Jr_=_+TPOezDed^0woZ8W^e@gyZj1l=F3|dO0Pzm^d)buvv35N9@N4R zSGLCCm6vSXGBECAip^_~hU1Ou5B4sagP%4`jfQX>R9To6{aB#hW~m9v44Dm}GmN|b zh50v}v!VMrA@2&4q~u7E^1%IM<2>VDO`q-aQMg7Fi=GqaZbWnoTHhq~W!0K)c^bx; zSO?%@&1zLB635XA1b?xT_%U{LRFK@W+weQ@3r$SaYsEqFqrZ1+JSgLvA8$@1sWi&3 zQ&G=;4(oP*Z~tcci1vU$d7<^Nnd`4cD z`WBMO5NXzJ+JTT<3mQ1|zyJ+>?+nZ6J+E4GE*;1@NS`uLRWNI*@pxFq0Ydi&5_+by zabO(Ut#(J!qkPp){P_?Zq$%^@XX#SGr@dFfk8~fN=)le0NnBJBlp<2O{LUBV*6PX9 z+Sl2brLw4B8_sqo4UwCSPrvsW%$s6j8<)?z=a7qr&8NQ)4&5e2_kDHp)~%E-*UqS@ zt@SA#sY=Pt%=W_C5_l3u+`i>oNYzd_Bn>ef=IE;NoFN~6jq#ziS-Xed=y77XqjatO zXFUvlM-#^Y%EAevTZn68ij`d%6YH(5Kh$HTNpFIiCOM>E5-GN$q@DekNZ{4_k zlvBp6>PMpV#}$Y|(Uz(pA*^@?r!(B*4(xB=dBkY=SOvF-_itX_jjYzAe@b$xS(=Ht zzIo`Mgr$Es4T|fymQjsUY6^xRfK8OeYlgC0LJNqo6GR6+nYw-|!)hcV zt_gPy9qRQmg%d>VS_6%A>cDoJlr0y1IeNa;e(9>8jy&RI_UD_;t3OPXM zu>AJWR#dQAV40t9WQlOLyH?#4e-;omI}_4yKztgg$51a<;!i<~NSRJGp@R-vZ(baJ zln@q00!}tY1cG;N6WU*(icmgH_LOgO z_Uy>2E#CZ%7r0(&ySl7$L)@DIDK4yCDtTzB^IL&k0}zz1S8efiKtXu9BOoBCp#*%h zIMR1brP?<;-Z}YnLvO8m!sROY(pC-Z4*$lgLZGC~x5f`rKA#TXtTroGe5JP1)9~-7 z*{pa5^6Te(k6c~Pi@f+Tw+WT|R4YRm(Z@_FK+Tk!Dqk+}$isc33MM#nKV|gf-U9%Z zHg!dlL`+%OFI~wurDj9YMqy*EzQ!r%2ePGBAFgDf@DJ&>p6dS2<_6faKv@j){ zVUd=Fs8|c4(b;J*P83qtJ~|C*4E;=_j>2Hq__zgUD^9qbLHm=P->1j*%lJOB83BIQ z34-6=E{bLW_4mNpS$Y$)iO3?Q8y7c( z54)uMN*@EbV}C;xm)OL=MOyD!@fl>YGj1Jcyvw(#*M(LBLSSLV;6LYg$*% z7kg4;cb!~+Z8`mCu1Oj4@j?#zs_}y;(EvZuId!BA0Ev`ENg>CV-@9z56sGxy_A_~D zs{2%oCpF!d{G(8UwA+NwDmUZF`v>1Ywy98iB{lDDd~^>!gOm)J$L2D(_H^1F!!BkW z@;oq?q3>|6yD{zpyc_s#$uO@f4;l+6VyUj<=!|ue{dUrcYKf3w>2S`fa-ZIS0{NII zAaG~e-##=0=H*$VqNFPL_sxn-ua{(flqTsL*$fSMAoL|dMMaT3&JYI1|Ff68t9F@8 z>xa$5n?L8e3zXz+1(X^`nW(IfJ9;1-+Hz zpTVBV8MSZgk04E2vgfQr`>+I)wTf(D1Anq-HRr&_%;ZjACC6a%3-baeahn#J2T8xy zO{i=Pi=-I5Lv}gEQ&z^Z{kPy|NI7A7+TB@(Ys?2U1)T?RF!-L+*VMt9O zdE^*_QuWHKF6qi7R-3rN1RBj!9eGbW{?wj*_W$vLmR+}4ZN~af^H$}B^Tks0p1Ya_ zufV4D|Bq5$d(lc$V#NIxy>kaUUp-?2PzOiJH^qfx@ zTEuA@@|qpKQs!Q3UP!?9MCi*mUpzUb zVpw@I$49KJ+eI_8!p{ziZ(8y+Z4v)dzeNm!vjt>Hsge3`ccp1RFIqJVS8`_mJAAR1 zTiKj$%pdaz9^a4p>8Yqy9%Um=%0_6Wcb}gb)n%T3-F3F2Y=z?keN6X}=wShei z*0(a7JPcV9cy-F7d(dHF*s!a=>KyV$IP5;65IWjVUWsam0Kz=4^YMoQu$#Y zK*|V$QTh?4H_2z`f5;L)=G!!9XlVdYT53GA>iH{`e`6g!ygMI1E_#Ay{8zs%Dd|zL zF}uo~9(ia%vvQ=~>*3MDKXTK72TQB;p$7tu?`fL$P#4R1Li}?x&x*R;U@w0~89hO` zkFqNvWGuY3)e2_tHqKS-J7={qnq-8_ilH{40NxVDe_?xSBv?)6~fevxrY~{Qb~rmEeZ6B~|lSYqvL2 zE_p%WeLL?orR>E$1LNgKtEZIQ%(8Y>%sI$y8+(#;&pEH%Z?9iamfca6hC+=JRnb~z zJ0b`;uqQ2z!MF6bco#oQ{~&y@M;qkk*Do)|4&aKeTea&-x`gP$-}30y44~B2Nh+`k zukQ*{n&^C7$z=)XXD|Gb*NMWp?Kcky2uLS91sDAnb0&+Q|nON zyQD`ZBiUO&$snj=ZQZwJj(9ix$i5DBltA$A-WIy!*}XLAi@8~xjTHEJ@IJ4iNb6-GBPB|X z!QJE{{gI!BDJiI)64Z`%ZMd7a9*`UQ95KIxnCb=xs`U~+xC%opb6h)Zx2I#4vmXCi za)d{{4-Pt-`-OsH<@xtqEojNWx%szm_Y4PR6wJS#pUec@N9K5mWyE)vqcLJF#Alo& zF%?xSkdb6Qow@Tw$`S_K+v=1kuAZ)5pM31+ zV7XJ_x8-cYL7v&pxPkSJL%U1W_3f_5J)g|bT5X!rKD^uFOn)}^rH>p+d1z{Wi~KRc z$)HuiPlCOtpPUgs0<#2)0H~3Xh%2u$jxV8p_RxjVXeCA1La6TAC5QdU&yRyUQK1pT7F?t_{17HliT ztDNC9mx37r1An8M$9i@$SH2kGZ9n1U9L8pf%~vcuCumZ|aaCK{z3GC55T>4X`|36`u1NrnBcVANmwpPGi zYL7um$0fBmfP?wNjD0Q%w2uMm@YvW7fXxEtB9l*aIL+RcI`t=7VsykPkpf~W+9y#y zco=faNw(K%oInTYNdOG?C{`2@g`mUW=B>n!lqK_2ka#Y(oILlKIxHfl^Z|Xi5EUx* zKz~UD6*e8HE-2!8Sj|ivmviYaY#N@ZaRF)P00fU_c}ImH(&HV6jCU^ad{9N z(@&V?2a4#FB(d<*`+t9bKSA#&vl=hePZqR*C#hsold>aVSY=8RXe%a zyp-vs&A5=OQz{KDVJ+B6PzRWo$tCg>+hNgPmleeB919juY?n44fWo(CF8|vyWXXUR zl;AQ{FMNvZxvx0&g;R}m;eziIt*N%JUe#x{Zh={+cD8L?7H$osYxwX!1bETp92_ZS zeXka#|Hs>#;H}np`z-Y!@ULZdc4NCo=LFclzRj|J3HXy-(EE!PMfVJP4`3IgW#eRH zv!pU29<>~NnE{uNFk#pAsZth47M7Hn0AAJI0>S#~HVQBDaZw^pNWE&-f06)AxUuBV zXLLj;j8V||&67fRE*7j}m2(uY7j2V{_52f1-QJPupq%F$#u1{ z8dp>jp5i6+N9H+T<@ocsbwXQ@F0Q}{rUM4s(HL1)7FX;{L&9il{E65HQIuQ^FRQKC z&>+K3&eya!z_x57GZUNk;FIB@<-ujluhz&pYi4nc>nhi3dsC zK%sWOkfwW-eNmcWZ+3pYeS3B`v>^*hx6nC1ddon*%{5c;_`gQ5h)QGED|hCD2&0YD zzlry(QF+Y_8-?9!1SRIfq51!06Z^-du|mmxGfN)akDRV*XM9AK5EnqtSO^a4MJ5yo zUjwB)>9v@BE&$ZcvovpK8huh~NZWIb0iKo>cg)oaiN%=gB`ulc2;bh!dc=$D*POXt z;$S1Hak^1YIZp%=oJEeSWX+<>TQ4#A>2b);zDJo89-Vo%_Dtjz7TJy~p{I(PRixWb z;$N2yw3+=Up|h#GOY*?3iy6B42z-ki#Q{j=F;NQzVl&OEZ9`o77@DZ z%YN^MdxGs)d=wG4gtc*17WZRt9d@T^P^GL8E^kCPy!uuVC09bk9!eoJrvPAM7X zrs{X=HPH*>W)(s6s$PrEI_sP)p0jwNb^Qn@DTLT$Ew$QA(B?*DuM876SMMles@~( z8{C1_kW(*mYR>kRZZKyyfPsZaO}_|znEN)@i5>F#l`1cvBe3}X`9nzm+opx*fsy)Iz=^@+3v%b+eq%14_#7=b{=@;Q?H;^)vgn-gp=2r8xuMq zs#nh%PEYTyPR{l+ul*gl@_&hRCUHh|LRX@1l4q%bRLA}48RuB^RE0-JIIsY;)q%Rp zSnn`{h%W`*e@P4^77V0&4P5#L z12?AYr~_5C%yQ>Azg|h{0}ixx(7ZEz98`YeV#B}yxn?vZ&ren)Ukn~JeX(+1a-@4p zp@kWFZVVK!nzKWwa11^E6?i|=Qr&K@S*cie|2+{OSGGuBgmc#z1Qa4VcWCi5FmY8y zp6=WtzkDN7k{4be0HOhGTjIkSn?3jAhp?nq@)On z4zj}PWNvh3$upoKpu62kSthau{=^}Z zJ}E5Al+P#khNkB6rzIE@AOPA^noke6x&sq?qa)^J^pYZz0e}ISTGya``WMmY9c9^S z`TT*mm!&Nw>ubo)<@0II<=C&yGXQmoy=}XA8VDUV;C^b{Y@zmqZ1z2-mKZ~4xoQub z*~bQJcFK7@jyDT!UgOyKL;*H8EU^FmuyX3m5THQA?1wa@PI0VqNoLNl^YeW2+h?m` zHq(oPz@;41GF`98ZY&JYCr?gYElJ!fxews6dP z0g~nO@b!;7L}er4PM;RMur{^6kp5=ybpPGH{GJFD?ke$mzfSmD-<37 z>o}eJCqn0>0rRI&(zosju9{y^u*pNRdEC>1cbQ5n)5Xjg(9`Xv41{2 z_P92S(Cz*kLP9@?JY}vCXwxCZq4gS*dw}N=7L1vXhCI5w#0~nQA13dQ&J9#^v)pIG zec^imLPn-_SHE?5AOFG^sdK7(@;&}beXZ|iR%sg&e2~R(aCv-i&8L*Lai>#nHMaWwGRH;0oz}TU>5o+EF6ODQ!ED8ZI&xlCNSzGTk0U}cIe1wPn|!jXKG3e%3XF7g@7sd-Y^$C2`!zrhMh z)#f9}^!{Rk>%uXjcMbvonIsonRpP3UkVbhN{6@EOhGP!!r($uzyn=g-BhjCW^u{?) zr?hJg@DnoU5NgL5Lag6(FFb#FN*2_Jwx*edV>Y`1$Un6K!R6 zt7yjNe8V%txbwZ%`?M75Co6k|xT@lNBnXuGVvGh=fkcP#QU8{#G;6;l^ZoX<*l)kV z5%=R-N5sL=-|F>k#A$&kQx(F+?)IQkWP~ryP)F9-n3qI((khZt!U|XPGyCyEe#9r| zJ2U zx=n#I!spo$VfFBKGaaH2ekGuHXns7%s;X`3Y}%Vaij{iC=VkpI=fU5I-S|7uyvEi( zGJ`io(;1ag$?J{zaE}^NgcLOu%M!vXk$uLOyB-@BMVt1LM>IqIQ7s+6pqo zAnWw>v;vF)(C8|n*Ih5%t)ey0GXMi}R1w9D1>iIgmj$z~vzC|ws6^m&Rw=Rb7#*ah zEIX~K{f`71hBlvsbT_Ha5vD;SLyEw#&MFikoI$_> zLM5NGL>mg)r${ri7r*y*XQz5@Yko061<(?PF`iblI1*(wX20QMIg`{j8(Ga1SAwIY z->hyXxMq7^o!*Q0sm@|3e7Xw{3h_zx5~7OgYN9oSUo!&OyP*v=iwogeQFsPc>3hK2 zH{M%oS(lS3cNRZryu?f`G^-eU-Bdh)gDvsaRZ(U5tAFS3vW!Vbt>GS^P*M~2sU z;0HfOE(X9PPxdF=E6<5)$I{QCVKv^m?Qq8Eu)IqEru;NI~I1k zm3*(<)mHdb#_3y_)q=KT-n;0?%1#uC1g-BqAMulhshTf=yPwxj>0{$;v<7SR$~`|f z8&an#B~@qb1^Whkr?7OEEJ%tZ3#-5efr#5kqW*{w-MfI08h^4&9`+NXb#OWCaZR#y zsEH;X1!riDxBa!f>v9LFp2*kcaJ4e&Fw0l+NB_N@-Dk#{$i1mb{=7W5=&Ie^zIRmE z_y6SGWWy|X2EKKgZHcN>_w5eU?<9rQo^<9lHWViX>D9grHaThViS;dcY2Arlf5-lz z`6uHEU2^kHnG@RVx~!VuV1e~IA^8TaJ0X3;m6L(WoSvh-hnx+v$Oau5JNXcHU)g&h zA@km=HM0hdK5|6hPvIYP;le(7cZwakutEn2HZB%u^-~$+a*UHZ9WIOp+oy*@XMysE z3&d|YfIuLW&-D7MhXqbpB-{ySS8FUoY{CWO%SiC z9f6UEBLk8XuUR}YwA^g42}6MnbPJO*l;*t1^7qm9lz7NLC;W?y%f_-p2C6{?D9e#o zmegpm#hO@2n%_!S1}J#myM#2Iv;Mbz-L4Lt+13m0|ID%~wjaJ(`15MYnUEaP5lJxs zzFt1HhN^BqOo(Cpul24imc$1c&V{L|&r3Y0jpyI&@v4~i0OcBA)w9+Fwydlvv)SH% zjqZe;v_$nW3`l;=W}!a27(1y(J$-YhkIg*tDyrr{bv}1eSotm%$6KO*{X0vEygC5X zL=O(Srpm%BkthRJmXQ&hvNZ8FTV%=Ne#`8u+{WLdiyUc*%v+tCGloAlYbpghB$RNSk;Z^|YM5TP-KO%ysZ zY&1d^=fWb6Z)~f&fkh# zP8$^ox)|Ho|EwA;*TEZsp;gL74cv9ZnjOS^;h=vAr$p7;J9H<7Kb8pnEgN~x1(uz3 zp`(%Z7JV8&;`w4(I;f*^qdTak^61EY;7=34$Uq|Z;rI;CHWqV4<0sraH z{B~`eGHExV02t7Mgy{DDlS0`^IMfIKkT3P)EPf`#g(diXlTqflnP)3r7yjE z#Rx;$%09KX_Z2qd!Qfw*0~W-aYeP_s5Kjg|8x@043Yth5m@~=x*Tzhrw6*4V}OC!xVo`r%-z)vK{zI4y6HR=Z;R8-LS$;Pfur?=RFYo9^e@gSZ!9_ zXSGg%SgVaqH`S}DO|++VPPx6K_Or#V?m+!iLT@I=K6L*^5S6G%m8+mi-x$8WOYJkW2d~#lnYs^lp zVrS@CwVAV{ICg1cc2=nKn!Wz6gW9*l>|}SH)B`&@8bZrYG`5C^Atm!PAcH{JS7YyZ zd^|Ph=Tuxrhk^!r$abm&RFkMdZrE^Y!nG;EE0=gZwG|JFVG8-w7^f#Xu8CA5;HB%v zhDi3T47#hs+0%SUWgBvo809OAg|WBQLYnMGLoD~%;~}ie9&QjgI4(T)67V=p7_Ogc z&!|WXpzNZR6P_)uBqKk_dS?g`gjJ4K>Q6)F1e!BB_Tj&q^_UZ^Wx@WV-DdEv!$lLe z=2n-5Zk|wN@rf*7@I}}UXvo_qJ!Je??bWl(_U9`pbGHd+D$!eeSN}Hq3vceoFU<`e zWw0Jg-O35o3EI{i-{o}vb(q~fTNZiR`RK|yN<=MS1^mkU-cnQZ1erM=GqjS*3j$bt ztt=93qY~`?VwjnEf8+(!xH6)?UYlATzB1$`LI)RJ5npHl0TgIZm`*X0P&Ai@wwM=# zhl2gSEkn`QB!)Pll3Rl5<^losu_onGkN57&89@U>O~a@cuSrSOdRsCd5bDnYd@W*M z@={P$J6nZUdtQ0SsrY*~jV1lT+;S?LRb}D^J(a+IPdBCQv4H2P!5prh3GcpA<};|q zv4K9uaCs#y^BX_YfSc>AdS*Dr4QLe`-*$dl#;Wj^z=eK{iBd<&CARszH7I@^n^E*> zRf!3LZJ2URBK**mQVqf&oXYu_Z_3|T>Xlg|c3yKF*AG4U<<7eNygYRCY|r{^=3+Ip zhkjUXdoCb~t9D>X;3&V?Kk0OIXg~Snfm&V!;jp5Bp^n$S%U)DISq%8C1R?~gC`we6 zjl?px;|I?dF8B1_e_*2_orZ0>mg!VoBm?hhyP9Is{zH^H?10}p4NG~tIy+8Hj84@W zE6-dBJtxdS>A|BL*o*T@>*)q^4&U@ zMfW;e-nv}q@#!a||It#2mIv2%Wytw4syR*6X&Nr&>!_75o9zhjbqr9J$bgiXXK>m5 z^_G}V8^K3$rQ;*GRf2jx$drPehYCYH-!{3`H zs9R(xaMW=!vu_}`r)OBp;O*m6)%Xq7U*I2bw27vhn|}Edrv9l*z=Wn>uE#rvsJ}ll zT=SZN{9B2z3++q$-KJvJJl0<{PkZ-OW-j!V87}4mH!ERRW-`r>NB+z<6?$~elzVSn zw7Dzup8F`C#6Nn?G859U;XVk>&do3I&zwA$wllhoAAALIDU!HSW5c zSbGbqT-F{eTbw3FBTZ)prJ*;57<=8cLs8kigwl&@i`DVmrSLwz&}X>kqF(pomp^k; z+^9(GINT$PFAUTP;hV|RurY>7yk-Cf^>70)=q%_w%g)|jbe7x3K4D-SCrw$N5RO|C znwfe(IeW{w3qoqwb>%2U_S!Mcqj;mIX<`SWr>A+TJ)FO!<0#6INrhp**VmbSp-NJxRL)m_mRu)zaKh6MZy)wJ9a=H;BN&9$j z$iZDc``_Q~wT^flGh3>c6S|6!4Q8)$SEwF@AhR%2x4FfYyd_|(Ec!cnE0-1uOH^MD z>$SC!!KZ;iCE+;6{}-Z zLNOZ%$~@2o@YzVLAMNdjo~d12GE~l`beK-gPUHKoia$VyeeO-AHpsf@cps`pYnp#H zm+vI>83S%ze{^3^_NnRFTLCN8`spQJeZq6C@Jj|>XA48qJ*kvGyc0wDx4RY7CNi1;ez+JgDgH1p1DdV8;wy|t_}a(SwK|42phU=*PcVFekZm)_OAV}4#k(C9`v$*0GZ64-x?*eBnzVHq5w#xYsQ#8vz3lz3lcTLaes80oEjDRy^_33Pdwtn3 z9Qx^KdD{`tKl@fnRL$D%n)mcSUCo=gga-NLgNAIBz+-p<7|joAjDA!O5ONR&S$a2; zIQ6e=*-OSwQrg_6p4$SDh02jpBtL&@R6TccW4|I~lr2Nic-*s7Aq(OLBSZ92t>IDZXw z9fh+JV&=w9m)bOP)HasplM_!p9dM(H)aRtn*D)yswV3tJ9PZ{-cczUo;r+ zkm-yBd0aY$@2})R`-V(}tg&cjnTxYpjftn{FbADadLisvyk`9cmj_=b!Kt`5S0bh& zhL{Z!XA0fG``xv~1&Fq5-D<}%Kx#SBsb+!x^+*l?zPo>LJEcCP#AYIugU!o?6B7U# zrNj$@+3(x_m`A}aFCpFh{!|~%D^5@5!Ee$N2x+P70qO^AQW=WSoqI6v7`|cK)^HW1 z#HoDGWhZ{#J13J;HXgN;sTlR=`(K^?S7$?_4z_Z2|ETMPeH%7Xh8U)W;I$`i%dxGcViJ$B&{)VoGqI%on5ncQ z8nS0QJh*na{~x126W?{uL}b7I@bAChf3)iMT4s+0uOGzU`qeg9;Hc{vRcTH?u_v+b zwI|Wmt#>4HGb7wb^hsOZ$vO4h=4nyjz=rGlPnm^k-d{P9>(3qc>)uOsU-PoYzZFjn z_>W0sBBM1^PYUQ8dis7TUw7jumWQLk**Vm@Q6QBFz;Bkm8cI`=5?rjTVH$Co5;WmB zv=zV0{Xm?!0q3Y02P(VHRxqaQdKoN+)^(Dz;p54XI{6)ninTu%*xgiQao44jrg-Zn zC)qNQT4C>{+NA{J{$%X))0ND)O^(NxQDXkOX_1BUFHsvp>+{W@B>wQ1u$S3j>!OZr95);68T@C}WXj~};pN<72c90!9t-zBQ}2fFnq82Lb)W^VWK zkLqiPN0;#nG*#`y3)8CdbAJlC&Ze^goW^N3H!3m3a6Fn!6_H`>#M9k)+A3Eka~-rV zt+k%9S~^^H{Fi@_c5Jug@aJLYT-M>0l>hra7oNnTlmIwN;5;7BM??AHsZ33BNVToVeyRz6K$cUMELdWI4lF{A0>b6TgFKs>&vU4+O3xJ^k>WB*$ahFWK|+jWqZ^6cLY`#|`)2AvT%V#N1D2*WdZFv9GuPDM z35(1tnPkr@X612Mku^zX-koz@J_BwDH~FyeB$$!usdI8Ix_>drgD&f0{hHe!hq~Xtmg^KvD<4 zF&ys*?`Gc6Xgejm!B=vkE$$N3ZK_<}SP%J)@6UO(0GF;Me~1K{OPn(igzWaqjk&BA z!d!5wG*aZ0a4ooOt@-I5r?&yEYqBiZq5cjNM&?1`q>c|A+@(IT&o8)uF41mGFnkpJ zGnGc*DA5pjJX&5`PTt$sH5?e%eY3Z}`0aO=%H^(0-okdrwX`N^o9`IBzUP)^K6atr z5xe?w{56u#qLACYB+FCM9ErTBH-^I8P#-E|YI-_HM48-I$&DVCE9peyMai_z+wmhN z+>P32(ysVI@s{6a^VkCPWudu2zU@xbf=ToxR`A%nKZ@+m$GH1Zo2;d~R zrMt)%Z`)rRIu8Dcq@VJ>*?w6J;e^EZM`|DEx<1;9o)|?JW(a7^G>!WAmo%PA@mli) z0}vr)C9d}bL!zmu^Sv7?5O*~66O*Fm{1JWDGGC@F1uwshW=5e*!FU$!}#k z^Eu|+j|dC?Ly2|_`Ezf~B0Q5PSuuIe_($@+^E=y$CEaafnEjI>+X@o@>^1o!zpd`o za~=8^EmX&kc8tBf6xrLj5>ZQ*Gc5uoqd1kW;W@ZmxMtwsz-P>lEKc7pNu?%kG=>9P zWa8%HTW(;2{3>SEE$nit-2q3s?!Z7I;L%xPeV|DPlg6`6;t*J2VR@IKA(qzwCAFSL zd{{i0OnRjiOZr4NvG?h6Vp4bn*q$pmhCq$Zt}sk$&UlZ+y{<=+{{H>@_2|#L)K$i6 zOQYhZfXju6FQ!loYT9kT^QfPgshR(4GX1mYF92g~7p>F0?O?6|3n3%meIG)`7_Z>(SjD^IKxL zi&u8nyF)939E{2=vr+mn$4NaH3up;GbTimImTC$n%vtWO+!19DXe;5*0>eWB4_U#S z?N4eJ7k_7v_}?bfjr*=;PVBF6V$P$rTc#+MPmPt8RgZPia5Nyc4`YB^2zLZ#;Fd{w z?*M|EnF-`J3#n^{A@gG0rfMsV^KBo9!!Q@#Ha)U3Fq8!svill2xw+ZC4STP*HML^U z4%09xT@P2G9Mp9_o2<_!3GNP0!qnpfU07~Gm@|@ou7wNanQoeAW##ib4tOZG$dhb2 zAZMw!uxmYOdKpJ_w=?SZSH8n_JtH`Kj8cn=$JS=W?b&fd;kabD09zMg1F&zF3!ue) zdme;hAnemLJfh_&3cX7WiMPF%LL>z?w<3BlipH1`%0s7y)=N69r=~ul@s!$Jy$YXk z-p#V+(E6x=2!q@yhK(fBRZAzI)voohuuZGcHqK+iu5;*5SN4 zfqy@m%XP~V3Apl8z`yV-K%|^^xmy*K5Df(pvp^;|5I5ZGEao=)T7-Lyl||RbWGOce zf=#mC!dY#T6;G^WAq<q z_{+~bYO^B8A9?U6?5CX6<--xjmR9X)tIzf7S3=faYgsQFHe{}`FR7F+JsA6*$rnqh zY2?>4;t*(btzV7!%eo&{{w3){eHKZAzo-ipd&^W>*SeBY)|7Z&0w@&)g6DowBT#BS zi8Ps|mihd3&?o0n zrDF~Olr9NMDy8@>#IJ)fUM^jN{{B89$&yCi}YB!V;;(RolcH;tfi-d9b}sfp@Hn_11- zpC4fd2$Jo5o)U?tNNm7gDp|X1(AdYctEr)|@rK=#Y>sQhmp7h43~Cb1-rvtP=DGev zJi0a`KAKysU?lj$$HKT+7|O4qd0fF*cD^W%m`2=Q{(Ek<^G^%A3XrVB?(h&lWo|R)^A_1sSX-u(D}<;FJymx zm(fl_Pfk@w|J>a4f$}S!Nz z#))r+dx*uN{GhLHNr1SECKmvwz^@O}#SPAHGNh=~G6j9Oc+b=ubFZ|$&VC%`-I0jM z7V9hL_r57k8!G-P8M~)pj;{?@rKYQTxmL=!J2YL_MBO z%LM3~`b`dT?G_}v)$3#M9AjVJlbFtK#AC~;pZw2R|9BuL*OP>s^r5*DJo@CyXCQqh zat}2!ZXFHWL2whnmKCc9N{YfgD}`!5V*4nG<>-x?lDqjWO}2rmG*|C&p9gj$`jSfK zt`E1j1c)6g^a<*mhklIZjoyjhJ-85^3Em-<^1WYgs*05?qK=M^#Gy(r#5^Hp2{tBP zJ&OvS@ViE_DOL;Gsi^q?0;d7KamgM}$}$1&c19AE@1L8ak%J5GgaF~=M3ViLNdZ&b)4myan0&Fdx&+wG@~#p*=xqkL8z8(%6p!=+Kj z!D_Ai{47+3^zr$hYH}?+I7&H*l^2si5a@uo+O(+k{c*E0pVP?AOEGXR@eFP`u5)6 zC6}W#R97y_;0oc+MVX{)j-GuY)1%F01BC@iKE9god40+Dd_-+OY!XmlnJuJhh+%i( z2-e!$7_f^6&bwH1(@+LVetxrD`n45Qk@$8R^IRqBff>iOwh-RkA64kXYq z47}d+-qv!i0%J{_9psDUEsH7fL4Z`{e$N%K9~d|hh;t*?Fbr_)c(k0!>gxV8>7SZl z(O99de%6S7cA3CuH_@MS%@d{}m35;%7<$byJ$Y+nfr?WPdo$9L28HXI4CeowbB_GI zJ0;e~$Dj6z*0H}jvG?@S!!Ox+X41-cH%i8as5y_p+IGOU*N#4 zl?GYL=&n4A{pP{6BA#+@xrX2MZ_@!`jV=!(WFcU{TH?oO?Z{{{)!LMgP9N??5$y%_ zaImdyrqB>a-veb%2sFXk`3uVvRtzK(pp`)V6eyU*?}%k>tnZJ!lz z$merS!5l#geMa@d5yXe{pJ@zFBkk%{w>Boy1v+-u!_E`x7g>iQG;*Wku&l^>9o3Nm zy5yIN_Q@Nk7~!%pzEg~2P&y@%i8SVy%8t8kbTrM}SON>VIoglYOWFT1%@E7@Vr7~w zs-a1|oC4x!pHwIf*c{xYmfQ&kwmNw2J|j(hl+QqHcS6shQbjF^(PfRQ*1?WOH;maL z^>t5nNja9t{)3;B@{=@Irywpae(6FwN$mCU97=Z|#RJ+r!AmJ?EJ1h*qJ`M4U^p;- zHNb4Am50wA@RVZJRh|E_f;Eh2Y0aP%<%aS2y5WYq8_Ug#l6YCH(d+=i3q{Ztg4diiOak0k?G}EbGtl zGZ6_R(Z3fE4&87R#@&3{wA(Ky#+KUzU021&Pc`G_Pi1RHv7@2@K?Gd(U4u;7wTw-W zNlnZaNuz3^#s4%fkrT`FeD>~`FlT(zJ~J|kUzk;Bde=W|HAnEvayn+r|NFPH_~h=r zsYyBBT=9+m=)`dx634Y`u#Zn)^cT;70gf3h8 zI1B_+8=>Vagh(P#3HZr%G_+n3#r(@5)RIjJ$@mP3X2C(NT z@k^@bK^&!N0&wt_r;4%`fkcSTK?ww3gm3KmUg6@JEfBRT8a}eSayqt;@!5nvEaa(x zBN9BD#9-{1GI&m%QH7j;z{(!MQee=-RY z%VgmbgM%{!)cGyW!0cCQ7nHh6#wN6HGYin;5Res?^0;r{CQ0j;2$Y|rL}{7(vQHJ%!ZURoO2Pe19UY2e*%}<2%(n$y3o>uD>%tijacd+|A z(s4K(>54fhiMn5xS7@@E`zs&*T#BXCMVP6cI(LHFXTpIu$C3Pq%{JG^?kKoGfz(eo z74%)Y%svgsHibdGVU=ZBfivla9KrcDmUkSM-=)Jf8%w%Oet3>P7a_6*UI`6ledgw- zf_Ur0Kn_5*TU*kPlo_N@xnosKlZ(SK)snwWihQPV;Ddzu)z1_nUX^J+EaOWf5k)fZ z*kB%Adki=k!U$bg?G=nGOu5rI#Mnq(SZv`Xm{3*|I);P6$PaL<6m=Eft}%TW5y)PV zfC&|0yfj?pH_GK*yde1(<`+~XCGotbL7A840M6eu#Yb#lS3WS#4V zRN=hcn8(vhF5_scF7ca%xQ@?F2dX6qS5Hbt(CU(CLBSGRVMI&7uX{nU2pV7Q0G44Y z%nc8l`x@LEbdmCWvNj1r*0O)`@{Ds_i>A=85h`UalF^dT(x^$sm5lG+`K$lq|4@6wRn~=59%_q?^S>HS?lrJm6RFW>6xdu&6GQoc7fiz zP^VQuDi@X}4bd0&TfTY8V)Kq!s9~tPX^|?I>$ zr&e04pIz>!_0C!FjTVy;FK*pqdr+7^npX z265a5$Bw5HX|IR5-e;Gm=mDF#kFqMViNEu6u9`#x!!s%;LZsibu2gygA5Dr?7DCzd zpMMK`wsRW94(aOc%}KH>-Iy+W&dYjJXaCnTh7|gN-9WG6y>oRQ)DLW9Fmq@xCt@*y z{!WGQt=iWpJnY}PC!5N^F11Ta)2CSN|M?w}@^fM}HBcNzleA1N8=e0bzQ?{5#kKR_ z@7%f>xxExj`yQ^|jTp7GR+vYCGv&OV3u*ME$2Z77PUy(}v}WG@a&szN^gqp73h0dO z9RnrceeSGM(Zs|aoRF{~)RW6w;N{#Q!c7zB^ew``m7nVMYocSyMAP>4c0=sT%Y((Y zg8Lco5I1+?RXLgIrpZK_DF1m+jO`ffB$B^`UKeU- z7q9-wGcO@2<;V3*H2L(dXN+P-0JyGbJh2P#lq;NdigG%oX zR^HOykIYsZxS8==a#O4!Cd}?6COYh+22Lz+GXK8A2teWx6c8*bl`|F9*p5_nI~Dgs z2ymaoLF{kft$z^gfu`7-3A|a=iX73+7w_=SByKsmn&Yl{dQdnlC+U-XX_FxCNpT2z z&e9WqWCyP41b?ehOiyQ05@OU}eT~p`81A?Uv7EhQabLw2tj0xtVa5S8blk0Gl6s)U^&dE`A<{{I0 ziEyQ0YXLx9fMD!Ja`Ez7zwzrR>_>{H6uOI%!!1Tgg{Ntlbu5G*(QsuP7uRd-i2UPJpd`7zje#eL!52_x*$$sT1Zy3vUAY=4Og@y?pxY z^l9NWB325V%?;X5WV04Mq8^ZnL`pBpjChXhzqRO}TkwF&zEw-e9ShA<>kQ7}Pi0Gz zo6S|lNv^?M!g*u5vCH;ZZ&4;BFjeI;SIP&mTD!LaL5+*ChrM?vUA22o%weJ(OZD$^;uct)sSk}mF(O$SF+wts;7znaYb zrw7YzMujJd3ne-aBSWJ4(-a4<01Z?fG#W5-y=8o3jE9ABBE~|ChY>NvI)N+5-I4dgQO8D%n?8FLMaCX$56UHrCx=; zDOboMk1m&_x>{}8lv5QeKuV9J6AEk<`Ak-=tn{OmlmZPg5Ws#}&XgWu=Va7uqbgoM zdW0SuYbg8vyW|k*We6Ym-{&i~<=fvXBFYqESDnw1d7wlmdvjy4fRrTYl)XeDQjhpn zMT6RK8;0Q=;Us_Q?>@(vqytVY4-=Gl-+P3u1OaaECHO@ zSV>E6e*SDI&~Oxegx92$$1M@cT4F-N{VxSLz3Jv9y=%;6swr~9a%4eY2SSwj^VZ1z zNRyRXd54CWnasO$N~t33NF(cMja)2tPU%Hnv{%^XHtB=9gsLikrM1;t8~)E8G#rjL zaFZCS%s23^PKsrdL$pu)w_PW19Qy0~CL3$^$ox{Hv6cHB%-b@Vr%w!MInN6HbkMTH? zXX8Cn_JWD=EpT;^u>^ib%P zv&}5vTKS>*;a2Y)ydym7>ywUSFV+H5Hg859e5lO+qW3CtFkpqA6Tw?+)#8+`CJ1!3 zmxM-yv<;K1@1;yfH7#PfacUgOUsu)cWUc+&ZMl1QEOSCOeheC0D_^`#| zaY7u5##d?d^sM@!)Bx{7n!MD-Zvx6&8DAg(?o9?0=62jwX5hknintIUE>rl)ivKgn zi(l6X%~er(K1TVaotFy>CRJ&j)b*8(I`=g*!H){QAto-w4~EEYcxqHXPq=ijmBC>w z=!Pa&xuw}yy(t4bJ-n{P^vE9OYsbow$}*1K@*ZgF0yZssQPjSsC|BP~RWDQA-rp6g zW;nPo5Xv4ZYbq=2w@{Wz{EV>7B93w%LDHi3ppXjLB-HzhjDha3jYxTgwK8D)e0hM) zUAP0pZaQe3>PEKf(@nUcmba~sVghEQ=;@P{qqA!{LvUmok>0T#kH2zS1q8nF1T3JT z@zuj;@@^u_EwM{BK6lVamLXH3q9fmJ3Ib9m#m|$*e_8GHvPmZ5P+L8=8vM3SDzN?# z;Bq&`dA}G?BJXuJRlS>tjl423K6!cBqj>T6z!=+P{Oj|M;<3FU_RksqGUGT$aW1nF zJn2)9H?pvLd)3K>Y(K)#NVNvQWyyFs;}5Q|1as*?4(pR8m6S(zdJttUFj&bNP?2uO z$+*fHyDI7NFqv>rI#RYPQW<73G@o(a|lxTrUe{t3ZQC z?NqjN>F=nRrw>-M>p??Xrj7NMiehnw^x%v8wwHarWaHe#Q*JMXw<($gN7gaCH=34y zczKbRVzFJt2^>WTy(CZHr{6Z&7o+X$|6Pm$X2pH}RXP5pl?uiaW*eDs%bl)ZK%EOs#wt#?`sQUB z8OHh^Nb5AWHce(PIv&h2rVo}(eYV-pK>t={3$`crU}OF&9e6vDpd8YpBy%k(0j?k9 za2C|s;z0Z)rV|;F6rF#u4K3++Wegst_iR)4@CW-u5`2E^pRd>lZJ2*Hr}Bw3OZ&0Y z>BS#=1uSuIMop~vUp`yemJYn4tfe5pabAG`RLW+vmFh`LlZ2F#AkkOE9=MgysyEMj z`y5fCi~v)J?wvJOmDk5X)$;)prn=EE^0AA7L?_Eh6NSc;%31xS#xilN;A+%SCpZP? zjQlUl1s}3ZU2?cyc{QbWG|muqDmAbDW{wQF$gsu#3tv}qR{uBv`rMQ&1UwwcP1ShA z5%i?l=B~#NH(ajr;g8-y)BeJKq~3j1cv|SK;R_#fI^pt-9Fz%QDFyo0JL&Z>$?sB4z3iAhs>pOTksQ=AXV0N)T`F~znI(Xr}Dbe zL^^?EwJxhM?1|@FMuqvbc9=iq8;tRwI6cD>Ak6tMD!)y4NpdFI=cKFW9c6!teEiHUpd@nYvq7>gZ{(Oau*|3~TkNr&f2;3&JPU)#Y06a$h z4pWMUfFY-zC%CT32SIp=F|?UD;fZ7l2N#Pl^t>Poki zDjXfxSbdl9)Mlxv>It>1DO(VX78KaF7NXeCztPFdzn8!bT-slW)XHn!*}sd7X?!~L z=CvyBqh`ntP1H>X-!&GDY|z!$j5HT}R$q07^VG*GF^?B_Hy&x$+B10JCb1%ni^VdP zmBopDH=)y$-t|KbS*Z*EW_dw7C8Oz+s$Imcosc~b(W+`Pe9%jl{eM~_#OlS3zp=Th zDd3#Q?Gzf`^S@04=Kpqjg#$2R<5ezNv{ozu6X4-v_gKT56Ba%8h4_gUhqR_|p-xOC zbjo&7TVHG})oUAKN~(t?y@kL5dp|AEUgmjL+TLg!KZzHQXs zMaO^te4_TNZ{;7{r=fQ@7_=k;gn%PnHGLfGUfc4VyDwCQSt47}Ud;?t?fQ7)KiP*4ufy+L8`c%-alAEvsnRPJx?aZ_4;>RjI-lWe~ z4zG`6{Log>2r!{6S{8m@IXC}hIr3P%N6m-MhN}8Ic60~aS!Z65mNn?5I-V1DQ76Mj z&!jSe0+vc4Kv)JqC~l*iUH|NBQXt1xN6OO@o_u9Q^5JO1*&q#6SKk+_RS?FvTBY$fQ5W&d?dg>89}|;i@)=pj?gnxS1*A(DHt4!T=5-6 z3toc|gjxj8{CcS@nFA`SNQ*Y~lg6SYFlFPD}vZkVsX1hIsVtQ5G6SPS@`;nMA}2Y`v*xrLI(vY85?(h-%F0qQz$qy|kHh%Z-M~K^rOEeb^SUZjlp1=O z3>WdgI@z$3{Lk;T>~kT#GCugzn(&Qpt2;W)x>z^S0QM=PCd~X4VW&2PO%jT!6Lr0A z)_s#3)AO|!)tmdQuY2?CrBgrms1p2LLXA5w&-V&>kmZK6r&(TJUp%#_Y_QJ7{h1Hn zzFa!^;Uha*MCeTQkJ3o!eU>AW(&%*L zdN`G_e!@g$Wb1);#Kz(PSH@?Z2c7?)0recm5e?)CW-HpUgdaI$O3R&nc?GRvO zMWvcSs7&ZeElJq!o%&GJg&>a5rm9uB%shR`xKc8^2F2YM#ksD+i;0Db303leXzgiW zSHZPq4$dAUb~7)RTc8d-8Nm}8y9^?aMcL#RL7(Mfb z+AL{+IfLekPeHiH#+v+SQA;wym46w1<`MDh{=={u7bp?xB=+t^!E^A)M*z@r@1W5E zfLo>=5up$ZWyV3yxw#P#t~`0_ykxRX4pjonyTU5WhGu=x%FgcNAd1F-3bX3mfDAB9 z6Xl$ggqynPL{e0Y8@p%Dd=VHxu%Adhb$>hha~?R}caiP?@&!yjWxw{qTeL&5(Tvxm zJ^ynzLM%$-!ys2?g#-(qKD(U;pR3JVsi`-uonWa%rTBm?;NqY?ZfLFqE^?GGMCyJ9#WHiLvd9? zw=xEbicOW4)TS$wOgcH?H@plH8tBjpVQdyRJR>ygr`eV0IS+;p-ba8mlEkJUUmsKD ze3AK{MteQ(VrIe%!`?2%NE)0kvYD@a%}m8BU5PEOdQ40p&epyTnOG&c5HVGoCb6h_ z(wFX$zZ&zI)yFVBn>8!G1HaPa`%uNS>BFh{!Kl9m-5}>mGxomXR!ewTXyX$M>tpcG z%;+)+q2w$^^RqsEF0_*TDdxX(CtVKyTbXqmCuy?JGs`*GJu8 zzO0sT_v__;&~nf1O9OrYfHq7h(z>OMtUT=hNnvLcblP^=vgy>me+0pr{|Nc%i@b!| z!|mzt7$_44&7nb#Lo+?2KTYx%1U}rqNcS}PH?-zs?1Kzp!cz9|#?g#ijy#_$Zlx4@ zU>QZzsRBJ35y(Iq2^UpqpQ7pGy0l}(nW$^GZ;o2?c_{-eI;Zqz?)cCWbWLOdaX|{1 zS(q@`>3gXXKzvE>bz%}13Q+56^L;ASKFBz@jDZZL3@eUbZPtbq<$keW%2Dq{WJr0s zMcY}Y=}KSQ>DAteKVu;%9OQN`8E@3tFyAg$mk|dgr(7KH=ZX#TVUdr2tm`C6Tljl* z-DaY&nJ2=}@t%q4ECXqvVVV~n@PGiQ0;Jq}_k;B&$6iAT)g~GjN^fn0gS&$)~Vug zQ+#SEH76!ZYpYD}uH6IPj*gVxAcw`>{?THC?V%-B0eiOM7mvHm9Pl{ps_QbNp;+Qy z;5sE3|g&;^B+1y>J9O+_tw`zqYg%)X@7UM5%6q-nRdwO|8ZQnSZgx zOtbM3u{r$juC&hI@Adco)U^Gj9($oJ!#b!LMTcKxd^od^lxSQe?}C_Ez$IF7j;yz$$2>R2`-1TIoM z7t9#!3VVjt%39=amf`{Pjotegz4^+wus-%U;_Y_qe9{5d_)EK$%X^xPyZCv zy=Am&=w@{vtFCBGOXBt%8nWz8l~GwG)+026I~#+9CE1CUcK0C-6o7pZEa<$F&4cDb zySdy>(Xe0=7&+IAOReyFE|SO+IEjvwsT~D}d{t8VefZu!(eCD$a6!JO31(}105#wK zwzKF%V?r6p{S2UbL}F{aqgM8 z6j=4B5HGJ_lOA4Q*+t5Yi#U0Dy0%U0)ZRzpWfSd{x(EK3kY+wF#*ni51_hogtigO=(66CE7HDN9T&|c; z&vGOke^2|40on`II+OWYW>qj%!-R6G)0`;Mzh6M2JJ(!!qlvh9A@rLil1YecSbCB>*&)3%=Cy zbLwIbVoJ)7!W5FT#wZY74$0f9)~XgSjfiGSRbCP)nnyf>?2h}nlH+}yi{Ko8+~o*Q zy5pP*1NK)uYbF$o8z;if8aw=)Tl}-~A;|0cn5b?aCb(YLuM_L!#2OesrIGguCx1qU zuGxi?UJ;Gk3@9t^x9~_7*O{=$dw(MV`J~YWYj5sD0yyJnau2ytSs=n2BF^_rr zU}g`tuJ6;M?n8=i&LXdEasf&yoxdJDTu1&{{eM+jt)pN^+r`thIkK2%jrnH96*}># zb6$ZvY+$00mUjPs#F2E88lH$m7O1X@OS9UoRF#$14~AD{nprtV0g5R4!13_3&a1%z zNmkUqXD6Ii@9DIz1%1N$Vf2+96A$PUt{&uaPOKrC2Vm&R8=MMoG2oK7_GOu=$H&bW z`eC~Li`X_c$CkjFuBt9}&&h(g<-N6(=(2<$czRYeM`4A%upR-~X@7)3Bqd}c0{dm} ztG8O7VZupxB=JEFqx((i`1kt)Bkj3(7|I_ym&*N_PLv?LOvoPo0!3}TSFq$QJK8`O zwFu!-!6#tI>F_>~L6_xdI}-f3UGp8nOvnol^Jb0TR(Nk>SR_?>b>|AFpE9&XBlFaT zbV#7r-JH@<4f5U7t$)4^MqW(*#$eFJ^hbE1(H*>m1UgYxLj%EXp(UCX+nJR)im;Pn zu1O(#^BcRoKt?f1JPo94m)Ri35s&On2l>@}7#nM@VmtYHq%iO5#=~qlY}I9oo9dkV zG|xo6F$OU|eQp~{k5nl(cU17L%Ls^k;VKyze9zEg#OSQZ`SUScl3>S#^MyfYh(vgM zjr6ON;lVYf!H|j0l~{h_!?q%-+Oqd$@EJ&$)0Oy7Uh8owChnXr?a(CJ?ZPD(>WxVG z_`dVvRp;Bfu?$}o%Dd4~oX}*B0DoZ?|K%=i+~Tdc0ZTLEGw*{Ga_Dc6%Syb+4GrIt z%fQU;`L(*xyc5i8`cNq1hS$WZTRj^ysnN7}evI_x_wT>Gr`wj`Cj$*NpX#msSL;lR zm8pErLcO=j&KVeYhpNTasc-_iV8IctS{Dzv#=YQ7&7ZB|-(k?Y3AT@c-sd}dw1n7F zFW}#I?r`<8Vh(>+mcoDMrgNcoX4e{o&lBmq&ntMk_K*UXezScR4mpVrec02ICPw0up2eq@QMKwLY3y_2JRTAv zwX*y7YDc&kK8=%n{FD+i2XQ)sBjDM=AsVnXH+uc6|LW6avB$`P9*57qR|ABA^?zZ5b&N^=WGIKTk+bM|{u0CmuqmBp zA@neX3uE9*bjxwUBmjV%!K_&)A26mjVlCnVVd{4A@qUuoW1ROA~HS8I*gv>&&p z)2hzJBbO#}Iu&&yYjkLpwX4206FzD~P$#Ip7spP;z|}kuA;Em};n&mL-#`4;jCu9J zvj3fplvQ8l)rwgbGKQMHxJq}vnD=n!c773msE?1romu=j0wUd7f;#S7OCfqptw`q+W&48wI{dJte`j)44t5+T z>xxBwc_X6!bIcZ>Vl_JVa6JDw*Q8%x&T4ufFRCF-p>o)bN$g5u^p%Cg#CR#p-`9RU zV6o&qo=r^j^uofRa=qsyRL3aSgPfeYe8iGOZ-?Rjai*lHjY zhn_{~&fZ5=@-cn+y1KuKR*~54_VPGB z2yG_Y)EQoW@19wH%Xrl8w|zQ&QDrPh7$4z2EYiq~oPnpn_s1{46W*x}48L9(30)7m00ZCmLb$?$+#MC0p9nB5O=pFcNRB^8`n<0}qJ!=x6+sSLLHO-)#p-$GX<CXGFO9Tyz(l0usNnl zm=sro_g!i32S4WbyVYu$1I@nmuO8KtF$UM9OWjbtHfQ+C$)hE~6qO)HTRkQGG<(VI z5R8YEkhht2Ky1YmMlcl=KjfjdNvRd;-2S&xyX$dF6Nc%Ylcyw<7r}LTSyT4Q|DIiP zUR-|yYrslkWxPBnoOPqJ7v^wX$c_C~pR$4O6p7AnLq2w6>gtr`^F$A1NxGEZjf}^n zl3d`m4cjsCJIA)31#lwS$R8v>-)prFn*=z94NZ6|OZawvuu}z$tyoUgO9~HF%~IRC zQ--Pph9`hPgO7JsJy@4qpOTsD^sbJ<94$=nGIb6c)6 zM2TGHF88~dD5JSwLio5%jODt@H6rAG7ey*}Nx4<}==0n6_Yb@ukN54o&NU*o(DyNgjm#bHS=1jyW>&kRa^jx9jw$ zs(oTg`}um9oM!<4>zqfU2y0gm2;|20tM3o^o)=WGyRG^U+u$aB@3KJKtHY?#jQ^a| zR+K?qIo8FGd}X~oP*x~Y&DjhX{)Q524M5= zfTBeBpVO#i^Wb~+x(|4>mewBKpf0IO12{2}*JAe_!24eDdR(_}RZTEKeTJayV6(Y= z%F$8#Iac;hi^qYE)IR1F{m})g5t{46*d9W}Av8|&uDEW^Y3I)Gd`>jOp1`;`B;@-o zr*o*X>wI@C#$>Cje7Az`DaZ!#F&N{fTF>fg+6py-3H}`In$SWfA_ey0w(~GEETJz` zNr{c%=51jfT$^vJNXHFc#`lsC=u|Qo#f{(ouu3NxoXp_QdU{V;IB+DaE}irVEPL_*KeQtnK$E0ZRj@_P+!B1<+H3FS8s# z_5*nk9(KV3p(gz>=JsSrd(Q%AVZGIT+~*#B{1b2o5CA*JwccQ29}&qGn6d{c59 z+^FVSRB#;=cqbi9w*&CLL0#N8;Nd3C2S@@ZhsNqve{b_NWES*v`u)cRPk8x7a0=MY zGxY=i@0mzi63>i474Ch6N=;0yk=>kme`b)1w5Jl3AJTu98)cD!ggNG&7FxU zijC1#;)xzgF>npKI_AeGkmV^W`(`ZS&!n$OkXHH& z3`mHU|E9!s|NGkVq?>Sj>;3BN-m9iMqtP%Uj87>t(mYH){0fWRtBxz*#wR)*Q=cnX zK*lFpgpzuQYfgpH&bv+z+`ecQj6Y;9c&R49Iyw@^p=B2EMY?0hX}DD=E84N2$W&*b z1OV`$p7{C&zziMpeN=R#n``X?@7%y<6+Qt|?*%{aXL~kyOM~R`d7h;#DT1)9#ZO`}5%!kZNZqTq%vSJ0?-T5Av>b zM*YR(p+D+G{{K%bVL8cfMsq7Qy#6Z7D=|L}|5wR@VVSijEpFv!qLs)DWdatcly?A6 z{HDd_#^WczM}N2bF|w?o^4E5Sl#skxS1~5gh5x?Y`N&!kC>pq-kvwdUDVrNxZlCV^ zq-!Ir*AV_HF7iX5;x(WBlQf71bCI8G;Mn|*FMy z)Gd{Wh8cM{i_76m`H8~3NO*cth;;v>L+A0}Tm55M63Pn%Q`I#Oo;9>mS+O!S;WwLj z>8rb4F4s~}62u~|KI|@;u!O42>3>Q`~;XSR=tOOFvqb z9#~3ER@15Kp~U{Du!;Wdf8!j6eRp=3IB(85_l_FDJSHkq^2P?YT>VC=q+3epBp!wt}0V~5X&>xynl zw=b`?(Zesjc%kulVd37vAj1Ic)oGQ&o2*aeY46zoTmo$PQil@Yw&N&cfNO>HwC;;S z=9dN0cbxYw?7%{47aj(6ENm`hv7h|md#MFzPyPHU$lOP%WnRR?4Df01{qe!U*PWQy zNSA^eG+N62#2RE-!X^v=PQj1SLEIxw1=~Tz6f;{=w4i~vywdNM-5<+)K8{6gy0J|; z_Epd4t0q8L$8g#_s1}hdd&TX>Ij9#c&%Gk~p=(H_plrBZlYLZ6Q}rsE%E1aKpCiaV zJIsDq%xh&Eb+|F9zaTmyiTt(-K4ZotjYk@qv-bcKVE=vMA>E5>eN*}C*VQFWF)N41 zo0na>zvXE{8A-c$PmbPx3i|hitD!;hf77Yfz_-V*o?)Wm!++0l{XZ@{{`x}-fIZ`> zK~l%^B-XFO`T11ki|X9dmApok=cBeBY8j*7qOr?)IWC$JNl{QOwI$v&8_SGSOra2+?ZTVCc2;qVo6AD2!4VqM2D z=p!3`yJzF*kVPfn&hf4nyALPvyKf1s`7ku;C|(u-6Z+>;QNfe8f4Jo<7n+Miw8D;m zs#d{}yg&nSEohZ#g)4Qb_1ti*S2ZbIV@KM+^aDi`jT$JWw^C{2q;J%c8y|iLllYl3 z`l2Gbv!uU?F+E{|O6r4cZrXzT-|C|g6jCvKkv-FA=xE~azsb8d@1Fg5V((GJO8C2N zbydc*$$o)SkONC&1~8nO-rgRS<7SBVmj3KA)Ci=LaZ6kAhsDXGh_$aoUM5uXG-nS~ zRtZoc@=}P%*Yv41KO46k_!P#hLIym5W;UMKzs-tW)c;2kI@blwh<344mFi-vwi z2R;7^NK;DV<3z~4`m4W)11PHnFXyy0jNs#rZ$kY%mT_wU z6pM63^2y}f=4dN^O*4V5;@#3~^5CNRSbcl)`}cjF{Fo1xzx{KJj-#$W{FFQRBavtP z-tou_hOAnim(3U@X+kjg4re+@lx64|qtX2Z&D0`c;?FC$EJSTK3t?jycq;4q`LAU` zd{ho_3Je!ipr!$BJt53TPHr^LsgeGE_oCP1&ELmcoQph2(}68TB+68Yrdo4$2_lBrfs ziY99i8YzWWYq-Fb$gEe~{pw!W@BYW=kb4ale?>Fy2Mx&I-oZ>{eB zqTiKy725Yd9Ogegk}j|pCm>6QUEVrkJzBok8=zio^X`;BWXq3F1GmylsRE+B&TM-Y?FGb*8L+j@32e&a)Em;oq> zUq+cS^j?!TYeAOPmx(5WHU3XmQ)d}o9S>D2*HLI4Y^3{xdhf&{g zMO5ZhP4XAjR8ul)K%#=c$bkb?O_Lhuoo>idP;7+sgyh>%H8m{CE%W@4r@>FoHMNESViR$q6V+ksu~&vD&^jFEqd>hCAXs z(0Cg=U?}=BJ;iq-9-#DQ2$9|wbvOU&>6S42e zBruShLMn82PQUYU3{YU}U14F4?9b#?oc38wd!A0}e@v-Chk8dZcQts6_4AJx=%|!)C5TkE^vHMApZi1XNP)Wh&hp*wD;;b4`M^v!?+TCe$5iyEVCKzYPeR7i7?D4n5NneFr{T@AY1Ey=OmPVTsbM1~3v_A_!hKKH;Ga$SHc(qL38gIJ!=@}Z|} zDfkK+}{77mpHrr!TTyuWuyo$;f zhlX&PCmOwGT*}GnnJqP*tfRIvn76L?eMgY@<{2X>E(Owx^y>QA&HXFWG{>MyYAR_6 zUcz&%ll*m%q46fxn9vrk zljj}&@A>$`QOu$BPcPz<0M>0_rQ#m=qt}+?O?Uxh;NpSKwT<+xTMfc~PZtC^Xp=1U zat;?)fv(oS>JH_3iVJ?s+u1!J&BvqxFj1W!Ph)3d&E4-DFaR#VSZ zl`Auejo!TJ>WQmVGf9V&_)U-{jJfOVQNpEOgt7frfwPo#e`*gKjgCv*m49sLT7Rw& z8kQs_4KaM7QSn z&D1x0+PrIuu-(3Iv&nwJ4Cf>mw{?;_yG4+%+a2-Zelo-eK}3dv%`r~$6xosN82&xj zqShT+-DQS`r1O$;mLeqff(8C5W7Uixzj)uvhB+$DtC;(3ArTS#ChfOX;7u_Y!UFG{ z04XrkH6KWO^yhP$bw~4^^*w-u8omu8S!E2Z!2SAa%hMbgT^i$(JaYW~8H8z|c0 zu}B^_x{_)jZXOQ`JcWU(xAT2zc$FDP-`wgU2y$uqg0uy%t-U2e&H|IUnPT7G{Ja$3 zkOgyBl~^2}xEux~TFZ;3-m+_(^sUDFRfdtbiZ52Yeft9=f}SqA&okPjyK=OWOa$K4 zRc40D;XU}-zUw7HS}g%nu@hf`@3gN$4Zg4Z!N}88qy`bHhwzm8FA;T)8F3?E5ELa> z32eM7)0Hs_XOdwVBMiV}86k4gD6A}K=rAliOx4AQMxHnGg#g{cj_bL=j=uMK20Wk= zvn-{;yz7SGteUw%2Ox1IX24%O?t8ixW&>kev;%n;tM0VmIeB*XmDv2r_fgp3R>=j> zF2kHsX68iiy@Jn4>w&Bj;8Vp(*S0&ETknV#nw0$ z3>cmDX~0!MUtTT#W!|RtyAU6r)%evRr|pQk6j0Js^uBI*v9D^~cI^g5-kJPk5>ExQ zCgNm=Z7r~i%~JQLf46J)NwMyH#35(ZIKykBSBWIY3Q5d{wSA_Pu*1aM^$F9DflpVG z*VhBHrCU^fQ|kC7k>%=Ux_+M$2bZ8d_V(N48pe9tVMIzyQ%^uLvLhaeZ4UE~^Y^4= zWNF4wAV69M92Oid^|+mSI$$MF0%tACXzQp{r(|aPE!eAOjprSgg6Y^?^+X^~j5F=% zc=rs_b=WJ!M4;J$;c=Rg-LVG=DO3eRR}encruQi9&+xw-n4o8)wqJBjz$k-?+ONm4 zM&`DAH&sE;IE;7oeV}t?E|h3J)XHeHzfbLM=TC&UQ56IrFz2!$%M?T+t!UTfZ49NS znc%9Z%{2}ZdHJ3Kof&YOgh+J>sbM}Dih2I8VSSQ+E2|WNG?fgozc)wS%?BXdP&G?m zxc0vs;dhtf1OW!*QEvU4=}t56uHUkMw(P6v#opVo+GAy@>Y$ytYBI1kIQO4t z?Mdm#@TQNl%-5hs?f%>B(tSboWEilqH35=a(KAZo5&cI@eB_FJ_xrjXkCjHZgzv^j zT2$8VBmr7v@q>H@is^ zLQXyyma0rcSF5VdpGk5-=Dd44QG)#XU`}E}LT+i1w{pGZX~F4f9TOl~L4^p9leu=o zPJLnqw)ne1x_xfAwlv;Cgpws`)T3}MVRv}KmC@*z;XqB#7DxaRe$f>_dN>-bIFjwI z3W$~*c_PcixHLNwi(Q zSw0_bbx2Q%4T+YLa@$ZSuVwdCeP40?=FOCX?BT@|b8739jH;3CLPPacRP7q;!Gwa?b zfvhklsv;o$>bKlbKJmY1+EqGe?}OAG>&$+90eKTNHR3bJEGbM)D<`< z-iTa~k;|z%yPu^AviCp&3|6-U+*WJA1wycqVLms&286_0^D&v)eUQ0Zu`*k5s*7RV zS)ohP-FsRf2PZZ-UmwcA?Y^Na=}p<;^fmd5=~i8lV2TW@xWTe!s%RLl^QAx3DDk*S!EHu992fCv)d`bi-8rGJakW-K?i6NSIr_04lvz zCfOuROTRrJtd`N0ldFM^R5^Fv>0$f%yff9Ym@_y3PCGkA(D>o3eO}AB)I-Ubja6o7 zv$+tWUz->GNVg9qZJd_jIokBGVPJ_XAonLH0Gq?p+twbzR9;$jMOnp!wbIV94N`H~ zUH{O1u6zpX7f>S3FSbhCa+Gy_c3F=zsRqn&<%1wBa^x2tlZY^6*%Vk~AeShj#u2PG z^AMZ~^Hi1Xw^ucF>1fKB~`}E9K<;~03&Y2qwy;$Yz<+I98WaJ zSb}0(DPZDam#>vs0WrvzcFZm!JW0#|+1~R5`{_QP#L{Ib+{pSXJLczi%`O7n)_QxEQVBdS&OgS|@-Db+Zf5r@ zB}1aDf5*VvBwK79eQ)W;c87@B4?dBm3~ebe1-WuVA%_a=@Zj*=;7MaYi{xs&WA54A zH@-Sc-mHnnEm^`fa0zrriQ0RM{hLJ;2fzy z@JlUi(^!?NO>XocOU8gD)l*OXz#{=~?6o9V@oPo$@cX?t5`@ozW+Ak7)4X zP|hB`Oq;CoJJI#}S?+d@n@Tf2c8dhb{o|OfTW#9Q=FX3d$Yg-E<71>;00}%9$_eRp zd}3iW4)=9#i=)@eadVmtaAp;%Dlw>nkhin8Lx!an66JzOU+?2=vY0H2TyMYiGz*TZ z=0YhpBuY0Rl28ys3ysvPGT`?`_ zLP>+9Dd8Z3sA15&&!zJF5Wlw_244$x=F)V4#C6MFcCF=jc=*)Po3l zSt`qEpXfE48aNtHO3D-tP^B1ONEx@SOv&~*-YcUwE23R1?c8|L^~v2MY1~@S3(%gJ zkAc$jZ>(L+1P$og=UD-6rNWg0O!#?u+!(>02f>EY_G31osR0mZ3?~#Q0F@8eF~1Z_ zf)3Syy=fZ8%1?3HdR zt(F8~OXL7%OR-Y9E> zi-LFLAJ?jU%No$ilr&^Pli%3#2jB<1k>muR4TUe9(DpBKH(faOKT7U_)Mx8*^ZhNH5mwX<|8W;^5hZi4y zap$U}|Lk?Vaem%=d8m~q`1aqJ$~onf=i>`~I`YVUEepJFD-S|R0$o(S^5CU5goC%X zP}TxAQb9Gy_9av|*B=;1{Ib5g7Xu_ES5L1RdOW*4p|+&CpF5v|%VO?eD19?Q-0(`8 zf2r4!)Jj`Sbykd+e|mYhcX{(I1hC&&(k2O<1Dxzukka#VfmT ziOHQ9`6 z%z*Z^0|1~J`blZmBSimnyD=DbaD;D}5dzq_8dD>0ABSFGdhGeu8Um2DoA?a|7~8s* zmgvT<56|6d5Fchj%Fy1ipi|-X>#9;K7j1LE=q~|Z1+_sg_goyR3UwuN?G&ghAF}3u ze6cl}y6Na-@8r@JD3aEhwIpRhPv8vMjDKods;PY|`emGFiWWd-({avlKdYH?!NRGw zzovcZx_k&n=ZiGLjMU3(k`tZfCUP}0UN_gt@xfE$Q(JQUrfZ-bu=^gQ?Ij38O7 z13lFi$c5oj&pWWLB!kPWQH}PK{!-Xl7$T`as(NmeK5cx_jJkU+J9j?ZKQ+}2516WQ zlp2HQag3jbPf4-r+s!}haY|56HB>S_uA`RLIr@!3Tcv^F4820P~-f-1vNEuYL?W(1U9G2tLj1&0$% zJqS{!yp?$0YYV~?&7)!Y`I%r-`GB4WbDx;4DaLO|b(IQMs`(DAB#4eX2Vk|>Pdyj6 zMiW0`gKC;hOIf_9u>w!MceEr0xSLh4@!GaQ3R4;t+SyS+v$Bf<2l0eN?8p~3J*4g zXo?@5Mpx=%p;=Q)u`c#2QpO^lt*n^J%1f-qeLpJQU1IwX^NFzP7L_#PK3Kp3K@wAg zeKEZ)s4IfRNC3=d3cLoK-iyEMF(ad4S~zfTfo80Xp}`Hi_|3ZM_IJuD>2LvC4=nGp z?^eaf7YGzPbhlXnT2A#}E09Xz0T$Bd&nl8k$Ag_G_>p|L3ZhmS(g;jSk+#5ReDlhU zEau&QsNSR)`NGaqUK|0^&@FtEDZ+3nR83WdhJNMxJUW_dKY2mGKnlZM&u_Gm^5fqf zH3e4BBH_*2`VX$FZf6W(b{e+UUh?97oolR~F0y<~3m>V1=VKL>jB40ANLkFxhVe!+ zG8m_l{5y2KIaKj7&D_%F%sA+7xVn(b@2U0`$o;AOa+KP@1Hakj&+!aZoAfj^fw^_b ztVNd__I{ws=iqc#@HCOSuqTyL2)lO0Ik}4eHYoH{$UWbiW1@vG<9uxVI5I6QG=u|Q zbbh#8H{6IC>+f)-Nmlgs_!>fPE7hEKeS7_H^I^G+V1}rWq|snT`YT4_n86y1kHT9? zpLR6NuuA_&^X_$7j=IA>wi|h)C}o~g7Qin^{V`?;J~CZhJB0<_pD(%+UsBVv;;ph3 zo?_}_L@KC4{AzAp4t!NA%m*}dj%U7;HW_}9kaO_U63kxqW~IcuDF2Gl>U9@oBMu&m z)>9)E@W=@Bbp?W~jB>&&=c!pSDh`i3RC zT-dspuiHJ7yN?rJ`%>!9Mf(<%ci-hEr6$-WXU%(KvT2!0n*VClYoTGvbw-)&MXpnNMy-A+3 zG0XlR&vkcB^bkZVsmu_Nh#Cp=FkWqUkz_`o(Aia~jbhz2%eeW4bRl=sT9|<@F67Lv zH};PF2nsfhnx85A@UmJ3R2kl~SP&yIaWI?b`Rb}f6`_OD8mKCq$Cd70qLt{~C6B1) z(NhXPQM=;|MraGR;xN=K5vi~h$%+>UGxWC9SSTg@qa9%5d)0Qh)`aZ@^#&m85j>|p z&(+z9DNBn9Qa)W>dW$Oy+$4uZD*O0yij`KZbCWYJkhYu`9lxna%V|piNS==UF`TXj zprHdefG_;ZzZh#GadQ7LE#h2CuD#y(gAhTqr{n8P)@S_XhfP;yOmDZ$`K#ru3;ZLU zVm6B9k=qvC2uUurp6X!C)w6i!*7*VNu+lurjMGye4lof7 z9?fcW9dbWHF!8c5+U+mblbV~kf$aM7cKPLhY0^^{_3#>p~W z4j=lRr*KF6hS3QiDG97Mmfg0fbB8XOtp93ZkGs`AnVWuQ_gtOPrtJ{MM?{mW0Ek~f z@l%qE+qHxs0VdT$(7Vw7-X8TQm@4dz**g^k6&g13cq!zSi%%tX*WE*^v-{muonH)Wbq73&l{NTY zx|?LXHU#E#Z?l&Rs*&qx*J5IVS%6WRo0k>@>I-e6i>hj$?aGrRuJQAR{V}qcr}GuV zmIDci&2rd%-37XMd#P}O1XES*j|65Fs8HpNw0beflH!TmQQo;|qRz+;(>H}N)4F~b zE(r}Ue-?H;F3UtCL9919f%nzcWJh*J+oxEev~znA%;0l31kS_^(CE#Q!)MQ4D5a!x zF24psVjBeBZ0+9OXr0b7B&ZUfkE8xjIZVsUtN9M}7=0sU6cGYKO5su=#KZ=Z=`Iw9 zNzk|f=W+j?sw^#gPfuFLsA&ye>N7!J{!#P7-tV4N&8P;tBFz@doDlhpO6}?X*ib~9 z^i~y%b3Og=TfjhR2_td+68HzBT$)ubS3OFw6M9@G2j0ytMe~4u|R5W?oEP<)51Qtr>J}@SPR1{WwC~Y zRd#sdCJxFWI);^5CV86{&lS-mQPsMe`erwS!g&IZDnsd94^)$;`Vf;Q7%!ZOPy(YVz z;bMSJD|*GQ{QB3{4Tj4gbtm$Vr{k${>Nty^sD!1(^G(5y1cyphifeG&;0Fua0B4E& zb>|Xmx7lgo`67U@`CXkUCw*6owcT^KBo`jbLvHJ?M-$QL1PSeZT_rSFzlnNTfmH&> zXxs`_r6Gwt%PSHgWMXf_Y~L~fV^qa2s+TKA>ujLvFK!>PCE|pPNXb0(xYgZrXOv~+EOH2I&m+voU&(0c2VEx?rq4dF`m1OzHg0#aV4vELFf(^*o z0H?2ou!PK=S{DYE7PX;YR1^c=1Ve=GZxVkDh+|jhiuo9Jk8^!m%P>i1H}ZV+#$2iw z01Xh|v2jP4;dL7WD^lF?*fxj&f-i(@>+a~t>P35ttCYQ#qci1G1Whog@fQG+tM%=G z*56T6+DS^fQy3(szP;2?HDw+Htw7c{2;!X(M4nz4go7?=$5K1a#a3UOW#6+&xmTG#f&SieR5v9k;Q{!&|7 zSk7n(MhOEsZ66gH#Et^}m{G@j4N7*}UoA4G2I zuAeConK660$}|WjVfg^C68t>tMi0LNNZBz2?0|H3`J%cXrp@ky zQor-^;Er{^DEBZrSPDRfOQJ?>uE^QcvK@=098OD0{6dGdCH2j$j1E?!) zxUA@9{Nnv3&!czO>porvkZQy}H;dipJ9vn4LJc-AxV-Gf*{5sWPct?oGp?EJwe-lp zcW(s%z+N)L=;N>Hg1j}nYezh71dQ@7y#0`M9&sGAyjqDY(AEhJ{}fllRy5yU46f8;$3vP3H`VHByjp@_w8Te#6sZ@L=$RldY zu5Nox*Ir2H~1MW|4 zm&p_Y3qJ2yyG;)9?Jve`7CVq;a>gL#8a27E?N#bF>t>vUXb|^~We~Z>l({oF7%J)E zsEnE?6PrqJTh>CDq@|gRNr0+c!U+Oo1g_bU13xg9eS?}`Pa)OdHxebMvlgR8I&G)? zJXDj6=VmHB9gV9b80J?MO^rQYC5%ZxH?->n9Eh_x)Bn^aHpTf|H13T54 zY7lhT05}e`O-U3t>gBNZX4=#Mj8rVe4v=9<(`hirEv_b(6b#KMY)9JL=Xb2IrDsaZ zg{<~Km@y}uDdiQZq%|g|U24UonX*=)V~3OdXWER}NE@}|W&vhFazYL%c;CQZH8iJ+ zXv#5im!&4p9-Rcy0x$zjZsegVru7Z8q=cKgE!B{?q6^10tKr$xvHM*n$Y~n*SpE&; zn1Dh^L!o%WaRn|QoA@@W&dnc*--~c}3*j_Fv4I*B#dxDPAx$;+L+_qg`^6|bB>9vw zua>>vJ3bdMTmH7w|KaWkYfz1Dc|gx)(&QSyU@oW9MK$Fyb&F%bF1wxU4^C>N7RI1H`9N0QYq=Sh>*)jTWiz+PuG)Ur4>C4hGnQP3NHo(+`DK^MddA@S-_3B4 z_`txE!Hw$kf>#E-U-vKw2;%?djXX-znPO!}D0ei+tz}g{zI?fV==kwJ#*%ebqZJ`O zEkd;22)0Ch&ys7?tjJ*U!n5#n(Gswp*gqm2K|Y>JGKa>vBSsdg&!dXcVKJcG=CCq9 z#oc)0x}D{mWGXX&h*MRWG0(w3odl7|G1%I>A45FCh*%Q>nhckg9?b3!0^M~Z{`dy&QurI$?|&%@s>$+i8s6vH=f?~^Zy%a-cXdL9v7 z_2PqJ@Z!-*J+!lWo2bh75gnDJ-p8%3?;U#CtP3Ux?ziMv%0{z?m7W2?=AQ@&JB*&P)#D zuhs%vTrKGq9tjBb%xCSp?l%6uq^AykT_`(;Eo=IVC1oX^l>AZ!i=bb=_THcgg zWnuz9->1>?jk&sbi|ag30M<6T0VzL6ZJ^4r?y6-R2_$ z^lxtSr;T!AH{q&>s%G?gDr2~-|%}^AENP64-%R03jr3pl7O0 zZ$5Oyo!qmuR>ccw%%3rK4&xp_ZFa*5NDh)l+cj!Zo3(>Ke=px|%F9c)v5rzVUZ8tZ z`kw16a|Hgq6aQw|}zrE>Y|2&tYXZ?}xiO7go0~2PUmvzIn5> z)YqFvs6KeG9x{1(2DAAUc-@CaeEUopJY~J-_^UlY!`KsD zKUi2-cRqERiHJNvkdwx*Pn_A^I|UIioaqkkzBT6}o31u~aj$QU+5f_Gvs>M|im|np zYb9Bt?)VDO!>r84K2DbW@OSj!t>XgWr(!PfbD*XWyD&Jsu|_#F)fA?F|=Erk}* zr~QmAhXaA9wA?yoeZWv@i$dM{A#rDEy)ub)ba864A}9l*S)=;4b)J+2Lb>U#oHrq@ z2D~+MLk>a=q&)W71?0%^TpU&wpx`Eycn+RBJ+FeslX|c8ZyDBH4#HzVnO<$U)Ldhv z0YgOr*^xiVWd%@F5iG7Gb5qPiJczKn$hO%fjvr@HlJjMvq!SEZjFC1lY`{Bb>-0So!ke=R z={%PZAW-4EaACV{rl2MD_yLKNIK=7hKGwPj0*Jq!#n`*FIwgPU%FDa^>ihUYWk>FO zaFC}DZGC$?BHP0!A7w&XVY5_Gd3D`~GMpM4-#{-a@(0~%h}4FZ*TZr71Ysz%YH>@i z76o4l1%`ksWz8%k!<`;Gc>y3ohO>^;1O8zqCoO5#P41@)`ETt7WEsBm6l*tLN|>j- zk(2B?GlsiS`*mb1B+VXG4b7!{uFEPr7!^vfzGKGRu&cq{pWN%1m5^o08eIB4=jU8e zW9wexK=D&2@n34-hr1UQQ4gwk@1wCQY{Z(h1HerOk09cZ(e3wRt@Sr6@^D&!=zVu` z4X2H1YcryHK*~7nMR<}oO`gM##syEqLE08B#{mqsj_P0tW51F|4A#RN@Th<5w0El+ z*=*-yztTvKlx*GWwz4!1pk#lH)bpQU z7qS4Mlo>OnLtD?gJx<}V(TL&g6rHhVDVqhs4`nr9?IOLKvpiDlpHXk>g18X3I-lb> zsWG6_ru^~4Vy*j!oN!GhCKJ6l?_x;KY>+EJM&1NV!5H1n!{!b2pg;?IdC`H-Zr#wX z7T9R}*-iCta0wyXZEO5q`B zYntn)^#}9ps?n2!bxKLVinr?fJ$o=!rY`2~@G!>(LPSWQ7uWg3zr)jRb^?5SId@9r z4zyFcUf;~P--7`8IlHNb*4MLLzcf}OxpjK(W{E#ZBXG8<`CNIathMZV^5U)tDpGeO zg`V#4-)aIfX0WL?LIo&6n%Y|Xj>maLB=P_l$4UZ?#%i>EQ$Pz;QStSH&wX(C{h1gS zdqs<*s4I~`>4PM4wMgNeZj>~Gd0{LfMU{I*T50n;CqExj1hc?GgBS;-d|vec8ya27 z4k!)<03b68c5+;L=p=<}n)iQ}{}pwV=Y+?9FJHB6$N(Uc@bWp?_Hq)LNH1FGd4o0Z z6dShJht7pGO(wU-T(eIV^ksqRA(FR!fj6BaObpAGzK+#Q~uG zL^PsOP)WxcTz+|$B-KGvNS^)Sx${t)!c!1wHKBZJbU2gIrft$jiYzFz_$v_{0+J6Q zWqMG4qw6KN4CMjCT=}WiLX^CRFf)0MCb>8t_Sq6L0bWHNzXcE98; zceawlPw?^rk&U=2x^z{KYaOr8uO|~behsUvMdO_w~EDwzd z?aU%bZ;SD0QmRn|&queSVGTZ=-bIhlO#b8$Btg&yjhd~=K-9t`;TMMbMi2LCWWri>hhxpmsuivdeoY7lC89{2InZ3XlGLLqKJ{(Q8y{%1|e{k*E;iJUG!jmKXm(yvYDWW#U z8os&XQuX-&`*Z7SRJ<-)w=X&gW`Iu8nJ|^LziDT;20^|XK2PC-ce>~JqQSuSE;**+ zEBDSmMZytPu%@i1d50Qu`s&s$8o}tl0BF}S!_)8l6;kQP)U?*p;-Z}}`(}lYb&}34 z$!>fpQ;#pZy#KM0sDDpsYhp}Plyy??m#E1EAXB3#x-xqGv&Kq9_Ry}>Nh*peW?E3_ zp41!?B zW0>_l$NfCN=Xsy^ecr#{>+|vXT)5_%^E$8NJdW@8dmQI^%I$7fSN-uKuG=K-4a7dP zM#efCY}beG}LH$Ut1-yb~)67W{lIoTG!1{4{>7)nL6hh^mZ#%JSvvBJCl%6U@; zRF@;>AZA>iwZDEvRODC)`NbZ{@Jy!C(PY(VNhAJanXdc5OzkJCKeC=&xJZrL3%UKK z=k-H^h}?y1*LL%#&ddgKx3j7JhHVxX z-hC^vcjRJ;nDB6L!a=a)aqrN_=qi8?KBq6m!FK?dkCT$88UeXuYns zO8od~V$j6WBH0ESQ~Zh>07y?LmabZ^j1*d;5D;ap&g$>^X4s&Qf+rS)Ta* z$b88|R`-XgfjNr5HW2$RK)kBUG=j*RV%HOUmI`+Hotx`DlyYLan zKMs!Xfrqm7jQYY4cIYLG?0fv|HT{W^xP{5v=hMPRO-vMS$^}EDj|boGtjS&5;ff{tG9sB$_2sdO>+%(rx2APR`=iT_dq_zqN#Nq}5GC?!GO3E0XP! zpQH2mLmArs%fV3(b)^MyoBM4d!rfubHx{479uj#O(5aMulYe4~{!JY>WFj53r?aJO z*AMT>MTYN7r`XcL=DtsRA+uo5WS8>5yZ5gn$7@Dv?7CZ>MO>~ObWObY+oeO|SNMvl z-FHlkmm|9a*)?yE{}jeNBK%%{1qAW9bwo(WS*4Zs;KIpk<&Qq| z75&wi@u)FFwSjX$bss3P6jMRBBwaaQ^qlhe%`^Vv?fg=AuRkBzYe-c++y1`FEbUF4 z(35f+*k?ex%1+Rws#0h)BEom=Zp4M}ks8Cb+G`4;N(TpH^r=sX>`5a2jgPUX18Lbe z=*^XPqFpKZ%+Bp{`sW3ic=l`)o?S1|ijRo@oWf2u(7{l?j$7L%{iS2;^;+w#Oc=Fd zYSPF32E&+NZdG=r;@#8=!*k_~nS}&81vD@>2@&#fz5>9wNiyIS0qrzJkeM`Hly{hR=v%7ry`aq3N>I|&)XZZH3er?%W`_q&6^A~`v=;$ zR0OisQfWyF*$c6K=gU~&GgY~n2q@1ax_K+cfA@01sUC}by^u;)c;fm*eE`k!omN2Q z0qP#bWF+f*7v$$VMH%eF^`W93JC2S#I$qe2UvBfTNcfgfzotY;;rN*At^6 zVT_PDxj4^&?#}(LOWaNtcflG!9!DU-q7|XDdC2*G!~?!Y^#k+IZ&EcM`1?;U3?BCv zT9)(lwzAR%cjSdi2;`VZU;l7mwe%b<4_%z074$aBdVV zBcII4!fyD+zh((=vkU?}LK$tcj25v7I=zPQ1Ifu#X=YZyrS%c~5Y9Ie(w$nsXCW1~ zP>??3;sRD?7OrjY6;p9UtbOJi9c_scKI4c1u8726n4%@Ijig(1Z^Axt7SMc9?968@ zZIr8fY`+`}%gI81(o{k+)h_R~1?xHshq{Y6yrM`WbYv;)+(8`?X*QKDOSLe z!kU@Z5p&jAnVI_Qaa>WzJ)6xEeHxp~RN)AO)I&c-V6k;|=V9y-t+yQ=9gb*tkKhd6 z^Hr9$PGL$jr&=q5{8S};jcsYbN{%7ex`()Wf8=axp4f95Y)KdkyJgx>OQLbBG?Pr4 zLj-VcE^XdRrXo|Br^{4f8a9?0x~i%c#_8$lE-Ra}v%iU$UrQW?nwy({^@OkC`upk3 zQW47E11J=Vc=0%vQBTA?1jW2579~t9dq@S#_%X`a4!};Ve5he1QN%bazAwiyBL87g z{fN0zl_qkNC8Q-od9<&Y!4R_DV)=&OWw)+ZY%&S-dy~r<%J^K@8O4Z=l86N~=S0zW z1CAoWX)Q3d%~^nI6B_fw1a%Cs=^F=Pye`a zUT1RH>19yNxQf(; z5ciAQT76Cz+R0o|A|J#o?WGQ_BD8pw_iIcnsV^@}Y?ZT44MQR5h2;0XmX_wQ^(`03 z+N@}br6pR3$!?!XfzjG$a3>xLl+Y9YG93z0f@;i2zQFIAQJ?lD~4UND#uE zC$jKZ7ML{Z<__ilbYfAiUcCy{d+6+pKsut zyMX0__d}#~)M?+-Q+hlG_>ArI$ic&v{TSc#`{j;t*2!!aE{)Eq7?dj(S>MyIPstE- zvi<^~->;=BbfkRq$w`{aagOXL29Z z+Cu7b7mh$)Y?F{vVg|H5$k&rT!v^0B)>`&K7U+Ea>>)0kk8-qmeO?PZ0Z7*n{`UXe z&|qsZ7&%+MMi0P-%&Tzf4PZK_dvf;KIwzu-Nyyqo_05Aj{uW+R7*ILVV1U>j7B3tr zO|?%v3)Aom^x2%yI^*@JAYiq66x%1Y^l)6H%Gz&rEoyiCaUq>Q3*PQ-BC zJPT3@XS`pJv)ZN47=+g1%N@~lJ1kpQ1&auBFIT1Te9Z@^i0O7!NL`ROXU^I&{T4My zsb?q*P1`&+HkdZ=`x3k5iRF-!du2EqfEe;|+UYepxM8(7crcBgrECe?&c6zRMqO|S zW$%f{hifOZiL8l*Nw5$=U!$upbnC-@xz&L3+Z3o%L`Jq`NJOxkj#;|+=P=~l*XkJA zh=&wGr!e+XKxIt2d_96D0g=+ybIEJ;r~NoiMs&dj)J6z_j=WyTxS9nP5J*RDS#ueq zI(dEbN$NS}EBZ7rOx&RTh#A%;Z3ACX(!@4}Wcl*^R1zj)Y33KnkmmXyMP|hTIDM>~Xs;3PU0wi|>(qQokp#la@Dkb=olkPR^+&{ZsS~?}iIVZG1)eX1NSZJDq+Y15J1IpHD?^;GkRXjC0%+5^tSiqS1vor z9CwaFZdMx9Mw-Y!J`C^8d0X3e&G!X$@*&Qy23dJ(Zz!) zmp89?(vq~!JWT8YLW;S$?UEtC-MD6F?Apkk-;5tLiV&U%zDk$RLt!;_b!#WDj2Cot zJOw&St?8e;sE0FLhdtE!B00%+9_l$(v=J6zW=6E*?`Lz{eeicmot?xWtGB#YaiH?O zq{*`-Yl7=?UB|;93T`w8V>e!Ux5v()N^tb~f(?Jg?;;|{AtJjTSNr(g4^gfz=zMX! zGN$s>3XKUF_(C~esTS${v7BULd~CvhgsFL~b#U!@tVGgCD{U$L)-BtmhJc#Zuzsn- zVu!0$3++}omq(Wi#(p#PsI}7-dL@}OKQLdKFNV?utQof10(*6IGpt4`25K2OE#h0k%6d?%xa14X;!sxYY_7J+xHK=5UhoX z!BaSste&2eo0if>zD4(@-3B-F@%Xdh=KH=zC;9q&_~Tv+JKF(w_I-8>44Pkt2gs3h z$CHnMG1cPnh_=Od-N14LV=8pvgo9Jm@3ZrgK9^6LAM(^aA75S)GukHUQ)8Gp2N|eS zwHTlG(Vp)VN~UIpDUBqk9(J{QKJ2Iw8!IY$OEjz@eXGJ?!!!o&sLi}mn)+2)QFBo8 zuM`+#Y|W>(@;s)gZesFbx}eG%{OVkIEruoJV@1VexYy4KdHH2&PNbL1<`@qd#+Hwv z;{F17p%9LDxiv&F1l8F!?tHtdcs@Gow*kX4)1lvau}av`D-Zno?^&e1u@WzY=hZ#r z2rmBS$2}i0T`=YSZ*(=}uMqs#x$@3#w#sexcJoSUSHCM%W-|0+GmeMY+Za{1gflEN9CJ#2` zQ`?6!P+_ZVraynUa}6{xsX8kwi%vNL#z3{FHGai!5mC`Ezvr}%*s;s$z2YYvEh6{nU{Mlx-4^E4c-iURceDX{V3*Gh??AZEoYfMlOPXIrY?6Q|kd*DhHz zra(BVIP~OG544-+8xQln4mPs@^TzOCDz{tM_C{LZ)3GL#!f~Hk!|Ru91jV9-4~vOy z=xKGzn|;dNtQNw#d7?LOpUiO8J3Vaf40cdudfld)rQ^b^@(KV_pf{Cm`3p z+AU`8*Cp-(I(f)T6YbDgQ>V0tmatOMC+V`f0xE}WmZGc2YZJpWZuVlfAAtEO(ai?1 zwU)Sw3Xt~c(}&(s)q)>_n8eJ#%}P9j8BZH*WNO#N2-nK*s;b))yO8akpZ)UXTXOz+ zzn9rg5!-Vh%v>eKp8ixb;W|mlqvg}}MpmfJewD%hJN)EQPi-+K)0IF41BaVC0bgNRZm$qrV@1Ap2bC zpxwvq7m`;7P4!vJh2&6@jQ-5n9cC_eu`R}3Xr=ib6rfpCH>knJ7hS^kno+GzulE~m z{jJaL2Gj!R*Lpwtr;*!M)s?1N&*jYu2O*DRWI`X-fn|t^yC8s)_-yb0^KRAo$G{*r z@iQp~`SNBro@3c~EbLmev`*l{VhNG{8K2)!%w`(=+C^fSf%h*w4=3sJz)mIgxQXwyxO6Jv5X-UA#rx;I7GX z3h8{SLqm6mY^UA){x$>bqIP_|4YJmu65&Tx`3$-c?SvJAK=syI4&(1v|7dcAZ&~Wx z{vJITaO02)W-SBe6>|6PdXiS3+_b1ACJb;Molqe;$OQ*9Vq-SWZoZ&)I#M>Yrg=Rz zCE~J0WMfvq>QK>D&)sw4GjlyzwfXjMVe9Q-zv@E5&A&X{2Fvb-oMldJ%w6?-e|~;G zIXUwmem{3!vzXc?)$|Cq(?0@YXJm8&Jsv#p*Ghs041s-tacMfsAGnQEg`S#X@T|dw zZ3Au}c_oDDgq)Fr=uro{^X3W+)|S6LqOwp(QUY-UC%aFMHPz#e3f+JyTITcj`eOWi z?8>EKI`rOeWKYf9Bol&{W(+wGF!HU6Lensi624AlG@%jOrDA8UNRWMo$aFC=v67OK zn5$s?gZ~HNPsZ0;U3J1nuv?!dC|XF#de!f^QWzpI&dKD!!Ey#{XCf6FcPp- z7&z>=wx&73pS*OU4ZoCChE@GBpOeusIaesV{WnZKW`tpfojbnN2iy9Upi*8ISTpv6 zFF#zTUn~Fm$37!&mRR#A+6d$o0LX)tO*icP*^FsxC&c1AMPfkU>X)EB3t-q8Y>pN7 z>oa?E=8V;0Fbx>&cL>h}18#i4H3)@!Yh*SwbIprZJh^1O2ob9VJidNy2 z^m9phf@>@?myNt*e}^@zi1lPgM7N-rG~yPUh`iVr-}rrFM4Ilr3+)BY# zM@#{3Qb|TSu@7aP@g>_fDq|-F?!}KsPk- zL-YJ^kR056>hVhJ5BBAzM6_5RPTJ;vim2e}I1RBwz!kGVQKaES`n^L!etZbf z9bu~zT9Bjtl!^*fmups56bdDFi~0@FOLOm{)Z3*nmewga;a)f6uqN`aiK1WP5|CsW z7;uHeikQ=+kmi`h6&R>FF7>;~-`h)DNr&b?PoL6cuX|mx|2c9!g>(^tq3OF^)%@QOPUW}?>#$EqeA`_Nt>XyE% zQq?RCG*nfaV{pky)jxk;>W4g>-tvQ-hp$RvH+_+L+1RDVW=a8{Wj^9(yKncqhg!;j zV`0m)14o)fGMz%^yh?`~{O2}qS;914Y8JhJkB*>qfYs!5^Hw7)%#_-jjCXtZDcX20 zO`$v=oq3a7(El>Tkzwl9stpzZ!^t=}I&RasT_pPE5wv3-HuO;h+E(&FyhUweMjK{M zM^to%i$!juoe=BLU!Nn9t0d0$Eld4%9FcWH+iZ1Hjm6rgC|bN6!x<}*`cY_K4C9xl zrQUizV{^RH9pDxobU~nW^D;~dwZ*CQ%0dZ{XvOc6+XOgl`fu&9O)C;>b~Xwi4FFAg zuLahQ6tMfmd|=l!)JR&~wChIg-2Q%cYtFd^p!M;gUxr(ONrhv_R&QEaHE|eAVME_D zl&vjZp3g77f8+V+2OP0jdX*MhS!ued_Si=~$HiqP>r7r&<)vjcFu~^ug@#5t=vE2}fBAvYD55ZS--g7h`UHzi;Y?U#A4UB76I3JC6R_|`RM9t^`?YpVZ6~l? zV13{s=Fsa{wjzlC4qre0;1W05VP%6J$tLkOnGRsR(s3_Bli7kDP(}PV$~_;@-NRnKo7e1m+Mp$ z+7n66qYDM_N1R>Iko0ASK8`hR+>eaAzI$O0)sVbuA^?w34dIFSf!Z{?sN|HT!O zZ^*Qao43{TBD!9~S+lfvi$<4JKaSYgtpsEKdH-h~C9Jyi(hc!SO3G~>4E(Xs-MvWb zepICXm^fbb)cEal#Jud$M%FWXZt)mp?^9u|JtOdGUHJwkl|&z0|FbC0 z**hWkr=Wk0lu{T+?j)+ga9NV4fJ~n`KKKzxbv8G5#4v!3H39MlnEHP^`*JC2Iw)jr zS$SyRbTe(NFr^!RaYE7^E$j>fZ_E4pgE!zG`KtQ*`j{rSsQFOi`l&j9F%_ru+Q_=B zK1aEB2>>Ufgz;(;NTs3+of)G3oBRDxsRsbi_i8)KIUh=0NIh=qoS2Z100gEz5MxZ2 z!XIMbA~{Wf;lM@1XF0({CSmkJb#ZaAA^%EH7=Q~;#T?&$3qJUiUpwq+9SIO?p<~BF zXH!knJ8XI}ur zPB>5J(Xa3CZWUhbd#N2T-<#dIAeuoVmCrt1S z9n=5(ctwivN#FHXVLg99rFE*@x);BdSfcb{4ei?WiGcnl>d@8PDoSsqETL4mMkv;^ z)++#tvX)Z6a`M=FbhB;cv)C6l4VQU0gIStP2{YZNBT>OyrpOT~of^gRBQE)&zuuYO zep@&;*aFXT++wSI=Wc#9_Z!_OH?b@iXAt$W$#6oEhwA#jX64IrTe@T!1(w)tQ6#Pp zMfB6XpW|jz^XbzkH}!9J64Bp1|M@xC*w(wwIHBbkP?a~8c6VP_wDJMCi@AWO#P~gB z9@&~W$-@Ss-XWY4?tC0}4Q|27KnAZWBJa7Yf?lBZ_FhAe=H}&vuXl*mHg0=BbR?9~ z*rut%+$v2>qr!PdY-_Yuw6d4$zjwRHqhWt!v9I>CVUtq2j6DVom51Hj+#JJc!vHu5 z4=O}*Q#wE6|8yd>tMy0JacY@LLGGt714%;IQ0lj|Cx@BwpXLWG*)PcOGcYmn@PsR^fuiav0IdWQDyBx4x?~267B%@z4LryjKYZ1c0Al z#&G}EH)8&^{-*UsS^rVE#?J*7i`Cj{m={ABVEmcDekVhitDHDBoi*eRx^MbIDwr{W znp27RK$#}ho)e9%N+xK7zNs8yp5*s@dV7B*2uIN}c7# zAgloU3n29gmTbs`0{uT1H$S^`DCGKzmwd2^=)rqR)Q?XJ7UFX?nlmzM>oV$~bGHKS zhaL2j6hrb^2c2m?Bkhk0j1_h!f?+Lm%uPRRbD1%R+U|AF2jO>W^0iW5o-VvrwoE>^ z<8*b3KC8u)b4N46gAeb>7@}lhspKM~)fFKT!yRWlIlE0lAvxP5az$j?D;qDL>Dd|b z)~2Pma=*^6g>NO0wT-ORJgwxwFFsMiWz~gPP}``LU2vVhLhcA3$U_L7$(vWiZZm_V zPK_k%vsVHvk&S_0VB>Q5>Z+>mE6wH4!Q`g7IoA;MzKYY}WgEsudTtby1m=*N^THHX z{*?Z76*z_5{CtJifba<$T3G=%0kBjtW;AN-@Qy$G`L%?!`Tkv@B~o{{eM66t$>Oug zu&JkF$%b$5^sa@DNpA?@ymOaYAYuti@w06LRnT0H}6AH*MwwCJ6IgaS8QdJ%OvB z!ps^Bb&O+~Ng&1^{nrJRm}LFyg4Bl8rXvEbQ_4#_ll3wE>#upYJo*fn)^X#nc6Qk~ z=0HKUXkwmzIN(j+3a`El=!elKuBvns|CC!5&(M4$`o<`#4r*4NIc6X#%W7{kU{uZz zRKV`z#3|ozS(>5a!zQ0t)K5!~=`IS(wdW}w0i)!0GnKW)r_ULHhBI)eEzckhD;aP0 zO}*z+M#dknb0hX3=EtE>-_Zb9-@4hSM6My5C}_=#8&P*Gd86$0>3%MisJAZ0>FdUB zK>OLVDa)s#^TCmwy~qpql`73!)6q)@T&8nR9}&zMov5=B*wJ+~08M7b_i&0xoP3{T zY4#J@NgDw*H8mbqdnzCn%MWJEV*6r*_&{cLYQ$&S!bu^+<#KJ}IJ~AQe#eGWig4cMTM@+?>B_JK%tOx8P+~aAFgQb zWZSfk^Lj87yH($pfFgc9KOi6=kegQx=A|}t@28DP6v9VU>gNzk<(EmS%yyD~u;GRAdKF`U{?xskInC@9HDID}rcTOZQ zK{lX6F>iTy6C7l#AD_>785PeOG*FioEg7Ny^S%c2ZHr#W)8{X=ro1T{@fO;yzb znwzTlF$ouio#RFQsUCb*CgC1ZK~eF<#(}y+Lw4h` z&leYc4R?F+!c8pRL-{1Be5|yJ>bTO+zQ(Wsef}{rm3=ZyxyQP%-uYRIrMZ;$yY#jbUe{hiIWMZ4l4Qv14Q%2vi-A&;m48WGZiDz!mAZ+%l24m0bDu+ zdkw-$w}`9~qB@j2EX&46e*T$GWbbQcY=mnlLO?(DYp8m4~Rp(3|kCwNvDFrP?GJkOt*nF*|`xPtPH?Ic+}+(Pvy!GSs;qw(suAr zcxYf;z-m1yKWwomYs8lW0Fh%Q&xf=wv`&>xN}ic$4;mGtzX74o+|p8XaBS=jf5H3r zAhoMSL{MaOd*2hYv$cPNjOxr4CT%|4Zck13jbMjBUgW`88J^aws8I(UV}4bD7ytEl zy>QmH7IMRMf|k(e`>)UQ7QfJD{u)167ZM!S_EfTAZvQlAy;VR(N;k+WC`hxjuC6Ya zY<^Pqr66JWh=$vlFy*!wdyUJ^zd?$g*IFg6M_k630e@h!0}1|Lz*cyqG1IyoS-B7r zZqeWvP}eM9PPXF3lHm1YBC3=XL_S-n;}~VUpIh4Yp4nVqal3RML^kAC>S{grd_!M4 zIea%nCUoI5yotf+DW9+Q1f>K4*r4m+x%_zecGI$IZX3nPRphi1wYRM~Q}rlTDlD#m zT&8h@<}rYo?*x;9!dkqO^T{o5yGY!h0?6e(Q1&{P5f*cm10(@oO?%2By@?Kfva*rO zzAPvpYB=#qS*D`&v8eM99tio@2NQI;ohnkm3x`v_86cSX9_B}=Irr9bUInpR9nzF+ zCYnBkvx_V_Ux)+-!WOoy@nZ%vmdLPkFnVVRa>1u8!ck3_(05tW*2{Wr_3^TqO(yX?l2bE^xC&m? z>Rujtbl*-uEn&8{%M$0xU*Iu%>`g3U0nd>i$}6ku zxq0iyIqw<=?Ju8uV)gr_Bdrg5wq#zThapGInyZaHzX6u zLOQ8Trz=A9^x29;EZ%`D_$?nj{bFYR7Ec|a1|BK zAgfj0yrMG;2?C%JwS%GHG0yA$6~Ws<1_>*tee0w|ptc{CfDzT*x+kv7^XmL^H5YgM zyYI#J*Ge_jX6Vu54es0=UjL1x!|QSY(uL|Rfi>*f z;ik@i6%K9 zl`kJAebl<1b`+JDy_~BL{K6iQGvvLqi-A0vS7MQLW{2jfx!2Tf&#U?Kik}RZqjykP zpvMY}pGV*Tu39)q0t^mDAG)ey2HyuRayIA&RM^KgG33{~k~gxv$J|NrtUA|9DgDZJ zH_*etPW=*hIB&0SuT(9&gH~RG+vZmnA8crDjF7vG19TR2jnS3!JAD*2wih7S$2w|F z#Z^YJ%q|1QI}&Hm5~j#L3O2!(KOtoZN&L(3>gkxeTf9Hh+qf&xWvg3l_Fhx;d z;dB)Rf)DNglM0sZ8G4c%*gD^(q+0c_Y;du?*S$Z#$vnyT z{P`+j_<)BL=I#KdQWH-6;$vIaIBgM^_EZ>u3}`sy%LAuYVM_veT4i;0=ClF&o$Ttr zk_6;@%yql-~*HCR*5=c9x0p$h^ilL8(Lr`6~F~HEg0=hxg zf0b{CWHjRERq1ENDk6XXv2ewy+Mt+z=QM`>+626?YIxRK)IHaWO(jGsW0D=f@yv2FjE84)QT)k ztPd*}u1igZV_drM5$q)=VtUXf1}8ov>HDP=^J^7WGFW7E>am`|rba_q3-GwXXsAjU?<#>#}urcN3E>1spp>N^A;c6xQL z$;r`C#$lsV(svfDfvcKYym))R?@D~-WU%c@7&Qtd->~9{Z|8Z>=47C{0tnBpPEHQC+0A` zoF-ds{j+5+q6>wjC?eY(uyxFlL{&=|?R)etbqvfS^UiI4IiI-fB2ga{?pB{&MeY6j zX4>R5pjmUv5R2REPz0+$mO;%mSRY+xZA;gt7vIlxRaREUvk&X{UK?Exl)eLPThd5r z#jA}ki6v{EV;p*v+omz9-fVUYfK_I@_>z3pY=N&6)OV~Fe?{AOJuWCcGxIqmpZByV zj~Ox=x7VD88BXOkpd5~d|4O>=) zcxdJV+C%&E>n>f%JP~+l6yr+ksF9g$5-gk* zEPcyUKKxoz1D}j({Z~l$(6ScZ-2wy_Wi-Yg0)3c}O7}K@#PiV8LFoqoxa)CZ*^@f@ zeO;v%8se9VcZ3xm`gqILeBRZuA2(8G2mmlDa= zR#sLWYr7knq{~l*YolbD$B}`-q>M^*mBb<&f5cfJH1b!4sjMVnCFpQWEvQN;^jw_} zv{lQX4-gr4$ffo;(ZZ{o2^2FxGV>vS1qpOr?YZlR)SNH~Z>smF`8@xW?3|p7vqeR7 zVas(uLvNe}Dzl&8RD|x3hU~m&A7Ri`82+#znx4h2hWsEspr#gj^6T!9|_#QjjFx z595UA;gOygZc`Vi6)xwlc<1u1ECkhD6>mb^-~9*P1FeUwfumDA`tdE zmq4L)T@AF~|9?dM&8c@W6yMQW*L?4a{u&vwPm?@jHNF78{2}(FDcnCijxv9#|K>rk zA&cL)1Jv7YWq;7)#Anv9%$b1#BhSp2|5I;is*35?l~5f`trBM5w@Y0;JZkU6loN{8 z5aH%XQBIGF8BSc3H0>@N1PH2OQ9mX&Hh5t3>y8F9*}Qpzerj_(nbK}&cIoN@ra#(s z!meWS`$pf*L7PnTvUJyM%pJq!mc2(7?otudg~9Rh@kXUTqz&)b+UmepUt&Jg?m4#V zelS$oC&+&!Zuai}kSZCM7cMg9XH(7`$$Xgj;bVlWTo4GblZ;aK--XZM)L$)wB6^z8 zWa!o(QIAdq_q--(jP@r*mn>=72MA8*eNu>atW;Zq-VN`Cg&xh7-MIbSbswZqB)}$< zW+>MlR4(``Mx+}QsW#s()zHv*BJsqC7VeceJ^Ur>NUTL-;e z6}6l`F(W0C3QhodO-u8`6a7%CN9Fj-?CknRAqBIv#l`!^dO^!$K&P7crp4Lv@~<61$4JsX@()9>IQMc;BYaWL$_nU}@`IIi=JJxK z+uufDi5}|YZX-|i9DrT*^=`_wpDxE;=n@yZchtUg&hMM|ERJq5h>GZSOEz_sS>lMUVv}=W*6|D%ad< zpPuI@r$!dOkAMGlwaIKF-uYuyV3SfjbB*WvsxIzru&6i+sxo*4RjH%hnX5_xslX!H z_KRwaeJ7h#5w$=Af}Hx23aUG0CEZ^wZJ+yv6+Q?{Xk1l)7FAJKZek!u9-_zc5JTPl zeWrOHsX_-EK^Yjx1|NkoB`mZy_>W|6NQBqH&>ZHerhk9D0Te68<$+|QWI}sLh zN_IE!RK$iJkajB~Vn-DMCqKAVo-BFt47y8h)qCTHN_*(R3*?uGVtzT<-5`ST`^lzB z0POhRXbKONPbL38U_klC{VUWdc5b~m^HR^qfAe`GO$7U=*m@{3K`R-v1VZD)Njosu20PEjXkm17 zP=wXOC2L1Ypk2ijaWHght>A9)19g+}huydlu`mzZRcvH{i(SdcY0G7t<7yxKuX6PeWir+L&pS2#c06;){e8gmpUAc>^rF26Ga+Gg;BkRZK6y4GY_=aivy0x{NgaVFD8oLuV-y0R-_W4r=s)Gnw2QXKmS^Dzl8hdtrN#+Quf6g+tsINjkLZ zjttjewC?K&S1p4CAJgxRJ(YpfD0`&8PhA^xZFn7$pUy-@5Jnm!+HiA57r^I}y;b(W zB=(l4$oL$V_jbiQ*iuFVaZX)>rZKLmo*X5iEY>8JYf$dwv`jb)aX>1R)i*{w_0F@+ zMcud4d!l7<$+x~O%!d---{#?;PSZkoG_H{21{Ej2G6N}a_H9Cau3kq@j{mkW4>+mq zlwd;p2ovYn2pR*SEiM)1fRjivc|H4^#IQ_mn#EXrWPk)Y!>$-rY2uOfrd_? zObmYUFo=%vgh4VY*dy4E*ahh3`2~4Fz!|3@I(LpN*rgqyUQ{@;0LD6@pWf31|FR)> zbk&l_HOmJNs88}fz#Ba6H9I_occ!_(T}ze4CIrzZx$}IvE~0#QE&r+Y-z@Wk=Uw%e zAXAug1l@bQw#PCv|1G@)TK--Hmq}D<;@vH_{8<8jNBGq<#}0w}0jChd({^{xB>(?; zRu%Y!*9k#C0g`(o3hK7c4eYen&?}Oss_^{Fe>-dA%DyS9^}nc|u?Yc(*(D3(4~BpL G^M3(f5t=3d literal 0 HcmV?d00001 diff --git a/docs/evidence/admin-pages-2026-09-22/page-5.png b/docs/evidence/admin-pages-2026-09-22/page-5.png new file mode 100644 index 0000000000000000000000000000000000000000..6137c10292c1433e661c42aa44a1d3fffa42126d GIT binary patch literal 151557 zcmb@tby!qw^e#Mt(hbrLA|2A5(hbtxHFP)9C?F!;UD7Z}BOpi*-Q5f!-Eg+=`@O&O zo&U}s=Yb2jm|?T`dRE-)UiTBNsw{(!LW}|efzah-rPM(n_%09#juZ(F_zgry1TzI0DbVxZkKFc> zMBtquIVo{X?}fuhuT0W@AG)~C6aD2x9+^XGEK1NvY&5JS`k2D}_iu)hEn!=_X$j?4aX zq3geui%bXyHu-NsU!sNZu>ZGg;3C9G2>)ALFC=r((f(WM!Bo)yxjuqYt_NJe;an}t z-s(()859ivw4QTY#B|;@l4kzTwV{tTin;OAZ~_4(->XF%6z`AjyjDNMM|VdC?WDAI zR%R~H!ngWFlAim(23#K28r-N2lToP-NLSk8z(3djy$J^z9XS-?hd(_W#)~pND1s{+ z#agibzZVF+BnY~zQ>+weG4BW7Z^{!s#7(JIzj}xTUh#&^$2w-%{9~HXER>4y0JyN8 zdRdP@PliqxXL}}yBq*Aw9)>V;-`}*#ULl@ymc+H_^>3>?V>n+a(@HMP$a{e`tCm{~@UTTIJ{kjdl z+QaLERCmE93(-sDrL#rRu;R7dPj_zg3>O+banRm7nplA=p8lUO|Ho(ZJ}T$7kb({a z$OEml`JT`8Q#i=f>MSB+_eR&T-dwIKouwoF-wl9}SIY9i*%;&c%%9ZdMM4?QUX0W2 zZV4JCbL{I~;r{xqpK&otY`N&)w^(@I97=Z1$ZPhG4MLglweCM0f@mhKC_d)!&MxYb z9D6q-6xM%CBNN?U=CsLEMkPB*t!4ek<_5KU7NmQ}O|sk#^s_^9iyRV&-#U)g>QeIs z^EZ(E9dR=>!6|5Z{k7aN7UnVkc+QUrXw|EQ6Q$`hG6CldOmCa%rfFS9Xo6&vgm9$t zX!+wCK?z(~JlDY-ualS_c||4F;N`B-)I6aZvDblwtSfS_Lx|oYr~AS~+vRb|zb60daRygP1=`*66Cx6V`%Y1;LwRr@P6Y-f+!3By4eS0)4?_`mtC;GB z`rpGTwq`P{_r>E(rf+O1)UqykrQ})~<#^4jttO?0G)&@#GI8{I{=PZ$|9tcOVR@Tz zCGG2<#UW|f<6H?f(OCk5JKq;sC9R8pnBt}>7I$`vW{lvx@fg>Ve~l8Jl$2yvJ698J z*y0@pwoN%`}0js&m95xe!jjfZ53&XRu&e8B_(h9{SZLZ2mAX(L_`A?@6b{0ua=ZU zMkE=N-$H!+;B@#Lmr%0D*VaYz{t7C=4^ZKrXupAt;9!>ySJE*9R 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 z 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

F-_m>)gO@p~zz(alCahwp&4-)%{v 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

  • gay}F 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 literal 0 HcmV?d00001 diff --git a/docs/evidence/admin-pages-2026-09-22/page-7.png b/docs/evidence/admin-pages-2026-09-22/page-7.png new file mode 100644 index 0000000000000000000000000000000000000000..a71684b0f927354fbef4828d8430a42f4442b0d2 GIT binary patch literal 151875 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�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 WN)V@ZgZ;K3S1y?umgwL8>;C}pKe*@s literal 0 HcmV?d00001 diff --git a/docs/evidence/admin-pages-2026-09-22/repository-checks.txt b/docs/evidence/admin-pages-2026-09-22/repository-checks.txt new file mode 100644 index 0000000..d271799 --- /dev/null +++ b/docs/evidence/admin-pages-2026-09-22/repository-checks.txt @@ -0,0 +1,476 @@ +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 inspection requires dead registered body, server authority, conscious on-foot nonplayer, 3m reach, clear LOS and inventory; only missing issued site IDs reported once +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: original 15-minute launch/loss cadence, active/captured timer disarm, saved delay reset, stop, 300m orbit and close-contact standoff +PASS: actual aircraft-removal notification guards owner/server/active/stop and schedules one full delay without replay extension +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, and terminates without repeated searches +PASS: actual faction resolution reserves explicit roles, samples without replacement, substitutes disabled selections, and rejects duplicate/unknown/missing choices and insufficient pools +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 authored storage anchors, native trace flags, own-hierarchy exclusion, external wall/vehicle obstruction, range, unknown geometry and bounded context refusal +PASS: actual stock capture, unique finite identities, original recipients, HQ reservations, delivered report replay/cooldown and failed-downlink cleanup +PASS: actual original turret identity, native/canonical guards, scoped >=80/>=100 profile, reset, dismount/reboard, requested-skill preservation and restoration +PASS: bounded150s startup followed by exactly one120s memory window; only HQ-memory outer deadline extended +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 single-item transfer, physical ownership/native callback proof, stop quarantine, compatibility and strict original actor/vehicle boundaries +PASS: actual early ammunition policy and status-first shared uplink; complete threshold, phases, cooldown, failures and requested check-ins +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.269s + +OK +PASS: actual radio node rejects current incapacitation, death, ownership and faction changes despite cached inventory; one-second capability refresh remains explicit +PASS: removed guarded vehicle cache and maintenance stock, airfield-only extraction config, and two remaining finite radio-clue sources +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: 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: 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.075s + +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.105s + +OK +PASS: actual convoy motion thresholds, native-only proof boundaries, physical cargo/crew ownership and pre-launch runner restrictions +PASS: actual 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 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 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 and surviving radio sender requirement +PASS: delivered-only status snapshots, two missed check-ins/reply deadline, last reported coordinates, episode/replay guards, confirmed-loss idempotence and 256-record cap +PASS: actual 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 enemy eligibility, scoped native skill floor/reset/restoration, one-roll inventory issuance, completion/failure, timeout quarantine, actor capture and terminal stop; native inventory runtime unproven +PASS: actual equipment coordinator registration dedupe, startup delay, five member scans, finite component retries, unregister/stop terminal behavior and 256-group bound +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 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 7 tests in 0.025s + +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.278s + +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 eleven settings, rejects unsupported keys, gates companions, and matches unique authored widgets +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.276s + +OK +...................... +---------------------------------------------------------------------- +Ran 22 tests in 27.219s + +OK +.................. +---------------------------------------------------------------------- +Ran 18 tests in 3.077s + +OK +......... +---------------------------------------------------------------------- +Ran 9 tests in 2.379s + +OK +............... +---------------------------------------------------------------------- +Ran 15 tests in 1.269s + +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.729s + +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.695s + +OK +...................... +---------------------------------------------------------------------- +Ran 22 tests in 0.195s + +OK +................ +---------------------------------------------------------------------- +Ran 16 tests in 11.109s + +OK +...... +---------------------------------------------------------------------- +Ran 6 tests in 0.021s + +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.440s + +OK +PASS: actual route gain/caps/braking, callback selection, old landing/cancellation control and matching read-only telemetry +.............................. +---------------------------------------------------------------------- +Ran 30 tests in 0.453s + +OK +.............. +---------------------------------------------------------------------- +Ran 14 tests in 0.213s + +OK +......... +---------------------------------------------------------------------- +Ran 9 tests in 0.127s + +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.069s + +OK +....................... +---------------------------------------------------------------------- +Ran 23 tests in 0.042s + +OK +PASS: actual initial WAITING task/guide copy, configured duration, unchanged interruption and rounded progress; native task assertion pending +........ +---------------------------------------------------------------------- +Ran 8 tests in 0.012s + +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.559s + +OK +...... +---------------------------------------------------------------------- +Ran 6 tests in 0.078s + +OK +.............. +---------------------------------------------------------------------- +Ran 14 tests in 0.002s + +OK +........... +---------------------------------------------------------------------- +Ran 11 tests in 0.092s + +OK +......... +---------------------------------------------------------------------- +Ran 9 tests in 0.362s + +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.105s + +OK +............... +---------------------------------------------------------------------- +Ran 15 tests in 0.036s + +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/observer monitors retry native refusal, cache successful delivery, deduplicate and preserve living/preparing/spectator 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.603s + +OK +PASS: actual three-state result wording and UI refresh; stale winner IDs never manufacture escape +........... +---------------------------------------------------------------------- +Ran 11 tests in 0.127s + +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: 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.250s + +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.115s + +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.221s + +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.037s + +OK +........... +---------------------------------------------------------------------- +Ran 11 tests in 0.037s + +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 +................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 11.221s + +OK +....... +---------------------------------------------------------------------- +Ran 7 tests in 0.314s + +OK +.............. +---------------------------------------------------------------------- +Ran 14 tests in 2.085s + +OK +.... +---------------------------------------------------------------------- +Ran 4 tests in 0.426s + +OK +.... +---------------------------------------------------------------------- +Ran 4 tests in 0.082s + +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.557s + +OK +..... +---------------------------------------------------------------------- +Ran 5 tests in 1.430s + +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.016s + +OK +.... +---------------------------------------------------------------------- +Ran 4 tests in 0.233s + +OK +PASS: actual aim renewal requires fresh same-report solve and original-command equivalence; native firing untested +........ +---------------------------------------------------------------------- +Ran 8 tests in 0.014s + +OK +PASS: actual startup/generation/ownership/timeout/callback policies and native-counter wait; integration preserves one-shot allocation and pending-crew cancellation +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 36 tests in 0.020s + +OK +.......... +---------------------------------------------------------------------- +Ran 10 tests in 0.003s + +OK +..... +---------------------------------------------------------------------- +Ran 5 tests in 1.057s + +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: 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 +..... +---------------------------------------------------------------------- +Ran 5 tests in 0.645s + +OK +. +---------------------------------------------------------------------- +Ran 1 test in 0.425s + +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.249s + +OK +.............................................. +---------------------------------------------------------------------- +Ran 46 tests in 0.972s + +OK +PASS: legacy values preserved, unsupported fields reported, invalid data rejected, existing files protected, runtime bounds aligned +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: 32 prefabs have unique saved root entity IDs +PASS: 299 original script entries tracked across 18 unfinished responsibilities +PASS: 1 isolated addons, acyclic dependencies, 51 unique resources, exact vanilla/authorized external references +All repository checks passed. Native compilation and multiplayer tests are separate requirements. diff --git a/docs/evidence/admin-pages-2026-09-22/sources.json b/docs/evidence/admin-pages-2026-09-22/sources.json new file mode 100644 index 0000000..892f673 --- /dev/null +++ b/docs/evidence/admin-pages-2026-09-22/sources.json @@ -0,0 +1,10 @@ +{ + "addons/core/Scripts/Game/ERR/00_Core/ERR_AdminMenu.c": "b9cf9b7e6f3135bff2fe2ad58d90bcb696936e984fb0c285172be627fccfeda5", + "addons/core/Scripts/Game/ERR/00_Core/ERR_ContentMenu.c": "c82b173496e7524b4570b2afc5493cb970252a19aed740a53011988db7700a01", + "addons/core/Scripts/Game/ERR/00_Core/ERR_FactionMenu.c": "b7dd477548322e674d9492fd8d037f787dc880ec7bf0e73dc89a2bf7f93cfdb5", + "addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelEvidence.c": "6bbf8d3b83e2c09fd9a23a9a5e5e11d7c29af2e618116bee613562fc45af2b33", + "addons/core/Scripts/Game/ERR/10_AI/ERR_BodyRecovery.c": "3aa41a8694e6409577fb07ef23a8d71ea104696e9e468a00c19a2a2b7e70172e", + "addons/core/UI/layouts/ERR/AdminMenu.layout": "e43f70720d4a33d37ae7f41c8d59aec753b8bbfb8c491b311850f6f87fff314b", + "addons/core/UI/layouts/ERR/PauseModsButton.layout": "393de5099e8aa5c849b95ed6955c09348f740d318f39f08c46768d1468cd4a0c", + "addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAdminMenuProbe.c": "4bdbaf54a9e325f631eb6f60003b3fceb7b1986148ca51100f5b1f4d765a794b" +} diff --git a/docs/evidence/hq-air-support-2026-09-22/README.md b/docs/evidence/hq-air-support-2026-09-22/README.md new file mode 100644 index 0000000..23f8d9c --- /dev/null +++ b/docs/evidence/hq-air-support-2026-09-22/README.md @@ -0,0 +1,21 @@ +# HQ support native evidence — 22 September 2026 + +These excerpts retain successful gameplay assertions from isolated Workbench runs. +The accompanying hashes identify relevant addon sources at each launch; earlier +runs are not represented as a full acceptance test of later code changes. + +- `airborne-native5`: eight original actors dropped and landed, both original teams + released, same-airframe airport return/service and second eight-person departure. + The fixture supplies a controlled drop order and shortens the post-drop cover wait. +- `recovery-native3`: physical corpse retention, ordinary delivered body sighting, + special recovery team, local inspection, radio report and compromised-site response. +- `cargo-native7`: ordinary low-ammo report and downlinks, physical loading/flight/ + landing, squad approach and three exact native magazine transfers. No body sighting + occurred in this run, so the combined cargo-plus-recovery completion condition was + not reached. The run was stopped after the handover evidence was captured. + +Repository checks and the production policy regressions passed. Native compilation +passed for the final cargo run. Strict runner shutdown can encounter a transient +exiting Wine process with empty argv; prefix idleness was verified separately before +any subsequent source edits. This evidence does not certify dedicated multiplayer, +all factions, packet loss, spent rocket-pod reload or a complete cargo repeat trip. diff --git a/docs/evidence/hq-air-support-2026-09-22/airborne-native5-excerpt.log b/docs/evidence/hq-air-support-2026-09-22/airborne-native5-excerpt.log new file mode 100644 index 0000000..18c6d46 --- /dev/null +++ b/docs/evidence/hq-air-support-2026-09-22/airborne-native5-excerpt.log @@ -0,0 +1,14 @@ +script.log +18:43:07.639 SCRIPT : ERR SMOKE PASS: air assault eight original passengers physically seated before takeoff +18:43:40.032 SCRIPT : ERR SMOKE PASS: air assault controlled order finds real clear landing corridor +18:44:52.363 SCRIPT : ERR SMOKE PASS: air assault same eight actors landed and two original groups released; original aircrew retained +18:44:52.364 SCRIPT : ERR SMOKE PASS: air assault post-drop cover active +18:48:28.438 SCRIPT : ERR SMOKE PASS: air assault same helicopter returned, serviced and departed with another native squad +18:48:28.438 SCRIPT : ERR SMOKE PASS: air assault separate cargo helicopter waiting at airport +18:48:28.438 SCRIPT : ERR SMOKE COMPLETE: native airborne cycle completed + +rereintroduced-hq.log +#260 t=201.2s M0 AIR TEAM LANDED original team searching carried HQ order at <4884.44, 31.8356, 11360.4> [session=1790095280-1] +#262 t=204.2s M0 AIR TEAM LANDED original team searching carried HQ order at <4884.44, 31.8356, 11360.4> [session=1790095280-1] +#263 t=205.2s M136 ORDER QUEUED AIRCRAFT RELOAD from report M0; cover complete; return to airport for another squad and ammunition [session=1790095280-1] +#482 t=418.4s M0 AIRFIELD SERVICE Airport: 1 services; gun rounds=23998 fuel=11354; ammo trips=0; original airframe and crew retained [session=1790095280-1] diff --git a/docs/evidence/hq-air-support-2026-09-22/airborne-native5-source-sha256.json b/docs/evidence/hq-air-support-2026-09-22/airborne-native5-source-sha256.json new file mode 100644 index 0000000..ce1835b --- /dev/null +++ b/docs/evidence/hq-air-support-2026-09-22/airborne-native5-source-sha256.json @@ -0,0 +1,14 @@ +{ + "addons/core/Prefabs/ERR/AssaultParachute.et": "b556997989605e2a05982418b7e9f26d12d427eb3ea6e3bc50e85c67ea7aa4b8", + "addons/core/Prefabs/ERR/AssaultParachute.et.meta": "e9dea2d533ad1ce6ce689e0e2815c97a6382e1b90c35ce1efa88a885527e8e18", + "addons/core/Scripts/Game/ERR/00_Core/ERR_AirfieldPlacement.c": "79d9baf40ed4890e129ec50f6852a6b86e3920390afda51cefe30daa045856a2", + "addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAirfieldMarkersProbe.c": "593e59664dbd7330b52674e5d4cc7b70db588cb75a1259ed808b74602501d541", + "addons/core/Scripts/Game/ERR/10_AI/ERR_AirAssaultLoad.c": "6bc62ac73f4a682b2a3dfe0aee5a5f1f706d28bb1bd7739e601ddd02a9338696", + "addons/core/Scripts/Game/ERR/10_AI/ERR_AirAssaultSystem.c": "b9d62818e3a7ab712fa2327e2f3341c0324d6c1d0703d563c7f58764d5c5f32a", + "addons/core/Scripts/Game/ERR/10_AI/ERR_AirSupportPolicy.c": "ed3e9a362583b092d840770eb8a4d2c68f22d376c21733803324765ae49d8eea", + "addons/core/Scripts/Game/ERR/10_AI/ERR_AirfieldSupport.c": "dbe9cbc9b326a27778841e941b745b7d96a420b47306f95d2aaa8c6f97c4f9dc", + "addons/core/Scripts/Game/ERR/10_AI/ERR_AssaultParachute.c": "a93c996059e7166988e9d1b0b498cbfd36f19a1cf8520cb4e9215a8884752e18", + "addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirAssaultProbe.c": "edf1e1e5393e10b6df40ed13fa2e33ad2a9c3cc77c1fb24852ee10c621fe9a41", + "addons/core/Scripts/Game/ERR/10_AI/ERR_ReconFlightComponent.c": "42cda3ea67f17c29dcd0c10f93475448e66284fb484b5125fb7dff55ef3629ef", + "addons/core/addon.gproj": "adee1fe3689108da7e2c0f4e7288a2f414d74208477ed5f9e4efad1c01030aa5" +} diff --git a/docs/evidence/hq-air-support-2026-09-22/cargo-native7-excerpt.log b/docs/evidence/hq-air-support-2026-09-22/cargo-native7-excerpt.log new file mode 100644 index 0000000..b00fede --- /dev/null +++ b/docs/evidence/hq-air-support-2026-09-22/cargo-native7-excerpt.log @@ -0,0 +1,33 @@ +script.log +19:33:17.224 SCRIPT : ERR SMOKE PASS: air logistics native corpse retention; actual issued document now absent +19:34:21.239 SCRIPT : ERR AIR CARGO ACCESS: enabled=1 contexts=85 +19:34:21.239 SCRIPT : ERR AIR CARGO ACCESS: storage context=door_l01_door rootOwner=1 transformed=1 point=<4787.85,29.8604,11416.8> +19:34:24.279 SCRIPT : ERR SMOKE PASS: air logistics native infantry low-ammunition request setup; waiting for real radio/HQ dispatch +19:38:31.807 SCRIPT : ERR SMOKE PASS: air logistics aircraft transported airport-loaded magazine and native inventory transfer confirmed + +rereintroduced-hq.log +#171 t=109.3s M64 ORDER QUEUED AIR AMMUNITION from report M47; load twelve magazines and fly to reported unit position <4951.63, 29.7016, 11342.8> [session=1790098354-1] +#187 t=124.5s M0 AIR AMMUNITION DEPARTURE native cargo aboard; destination from delivered unit request [session=1790098354-1] +#188 t=125.5s M0 HELICOPTER STATUS TAKEOFF: ammunition helicopter awaiting HQ order; position=<4789.08, 28.2043, 11414.7> [session=1790098354-1] +#189 t=140.7s M0 HELICOPTER STATUS TAKEOFF: ammunition helicopter awaiting HQ order; position=<4789.08, 59.858, 11414.7> [session=1790098354-1] +#190 t=155.8s M0 HELICOPTER STATUS TAKEOFF: ammunition helicopter awaiting HQ order; position=<4789.08, 133.749, 11414.7> [session=1790098354-1] +#196 t=171s M0 HELICOPTER STATUS LANDING: landing at airfield; position=<4808.99, 149.218, 11377.2> [session=1790098354-1] +#197 t=186.1s M0 HELICOPTER STATUS LANDING: landing at airfield; position=<4831.26, 147.225, 11335.3> [session=1790098354-1] +#198 t=201.3s M0 HELICOPTER STATUS LANDING: landing at airfield; position=<4834.18, 129.562, 11329.9> [session=1790098354-1] +#199 t=216.5s M0 HELICOPTER STATUS LANDING: landing at airfield; position=<4834.25, 112.119, 11329.7> [session=1790098354-1] +#272 t=231.7s M0 HELICOPTER STATUS LANDING: landing at airfield; position=<4834.25, 94.6399, 11329.7> [session=1790098354-1] +#291 t=246.9s M0 HELICOPTER STATUS LANDING: landing at airfield; position=<4834.25, 76.326, 11329.7> [session=1790098354-1] +#292 t=262s M0 HELICOPTER STATUS LANDING: landing at airfield; position=<4834.25, 58.6636, 11329.7> [session=1790098354-1] +#293 t=277.1s M0 HELICOPTER STATUS LANDING: landing at airfield; position=<4834.25, 40.9712, 11329.7> [session=1790098354-1] +#299 t=292.2s M0 HELICOPTER STATUS LANDING: landing at airfield; position=<4834.25, 32.9493, 11329.7> [session=1790098354-1] +#305 t=304.3s M0 AIR AMMUNITION RENDEZVOUS nearest original recipient=110.559m; confirmed magazines=0 [session=1790098354-1] +#306 t=319.5s M0 AIR AMMUNITION RENDEZVOUS nearest original recipient=96.7928m; confirmed magazines=0 [session=1790098354-1] +#307 t=334.6s M0 AIR AMMUNITION RENDEZVOUS nearest original recipient=46.0027m; confirmed magazines=0 [session=1790098354-1] +#310 t=349.8s M0 AIR AMMUNITION RENDEZVOUS nearest original recipient=3.20373m; confirmed magazines=0 [session=1790098354-1] +#314 t=364.9s M0 AIR AMMUNITION RENDEZVOUS nearest original recipient=3.20379m; confirmed magazines=3 [session=1790098354-1] +#315 t=380.1s M0 AIR AMMUNITION RENDEZVOUS nearest original recipient=2.45618m; confirmed magazines=3 [session=1790098354-1] +#316 t=395.2s M0 AIR AMMUNITION RENDEZVOUS nearest original recipient=2.4561m; confirmed magazines=3 [session=1790098354-1] +#368 t=410.3s M0 AIR AMMUNITION RENDEZVOUS nearest original recipient=2.45622m; confirmed magazines=3 [session=1790098354-1] +#408 t=425.5s M0 AIR AMMUNITION RENDEZVOUS nearest original recipient=2.45609m; confirmed magazines=3 [session=1790098354-1] +#409 t=440.6s M0 AIR AMMUNITION RENDEZVOUS nearest original recipient=2.4562m; confirmed magazines=3 [session=1790098354-1] +#410 t=455.7s M0 AIR AMMUNITION RENDEZVOUS nearest original recipient=2.45659m; confirmed magazines=3 [session=1790098354-1] diff --git a/docs/evidence/hq-air-support-2026-09-22/cargo-native7-source-sha256.json b/docs/evidence/hq-air-support-2026-09-22/cargo-native7-source-sha256.json new file mode 100644 index 0000000..11a9e5f --- /dev/null +++ b/docs/evidence/hq-air-support-2026-09-22/cargo-native7-source-sha256.json @@ -0,0 +1,13 @@ +{ + "addons/core/Scripts/Game/ERR/00_Core/ERR_AirfieldPlacement.c": "79d9baf40ed4890e129ec50f6852a6b86e3920390afda51cefe30daa045856a2", + "addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAirfieldMarkersProbe.c": "593e59664dbd7330b52674e5d4cc7b70db588cb75a1259ed808b74602501d541", + "addons/core/Scripts/Game/ERR/10_AI/ERR_AirAmmoMission.c": "293a2c9f59e533768a37ef8c3b1609da1800a8bf9b4a8828aa8015bbd6be27a6", + "addons/core/Scripts/Game/ERR/10_AI/ERR_AirfieldSupport.c": "c6d88ede0b1b6bac5a7075b6e2e783ccfa8850210aabd28bfa4bcdb698cc5f87", + "addons/core/Scripts/Game/ERR/10_AI/ERR_BodyRecovery.c": "73b00ff42f188503245d4b67a50d17a028a2071c3cbff5f2b6750441be647797", + "addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoAccess.c": "ab4262f78d54782c5ecbf5fff4ebe3da16d72329658d7e18c0c35387dc8b3c7d", + "addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoTransfer.c": "b398cbf166fe55dd2ff518a1ac028d87dc27edc225e25c1ca3703704a978d994", + "addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirLogisticsProbe.c": "befee1bd4838dd84847d09490c9dd82e2719db5cc0e6dd6aac8d0197b8e766fd", + "addons/core/Scripts/Game/ERR/10_AI/ERR_ReconFlightComponent.c": "d959749235758bb394543aef1c978ec1b3384850884df87e47ae4acc4affa537", + "addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelEvidence.c": "c0a24e36f718b81dc631ee5bee03f3ef710ae6e0fc091bc2ca7ed05d0abbda6e", + "addons/core/addon.gproj": "adee1fe3689108da7e2c0f4e7288a2f414d74208477ed5f9e4efad1c01030aa5" +} diff --git a/docs/evidence/hq-air-support-2026-09-22/recovery-native3-excerpt.log b/docs/evidence/hq-air-support-2026-09-22/recovery-native3-excerpt.log new file mode 100644 index 0000000..968c367 --- /dev/null +++ b/docs/evidence/hq-air-support-2026-09-22/recovery-native3-excerpt.log @@ -0,0 +1,16 @@ +script.log +19:05:15.637 SCRIPT : ERR SMOKE PASS: air logistics native corpse retention; actual issued document now absent +19:06:22.931 SCRIPT : ERR SMOKE PASS: air logistics native infantry low-ammunition request setup; waiting for real radio/HQ dispatch +19:06:31.970 SCRIPT : ERR SMOKE PASS: air logistics special native recovery team searched body and delivered missing-intel report + +rereintroduced-hq.log +#42 t=38.8s M0 BODY RECOVERY REQUEST delivered body sighting; search ordered at reported position <4895.11, 29.0835, 11869.3> [session=1790096676-1] +#49 t=38.8s M0 BODY RECOVERY TEAM special search team departing friendly site; bodies remain retained [session=1790096676-1] +#174 t=73.9s M49 ORDER QUEUED BODY SEARCH from report M0; inspect reported military body <4895.11, 29.0835, 11869.3> [session=1790096676-1] +#177 t=75.9s M0 BODY SEARCH PROGRESS nearest searcher=31.9729m; physical inspection required [session=1790096676-1] +#198 t=102.9s M0 BODY SEARCH COMPLETE local inspection complete; missing document report awaits radio [session=1790096676-1] +#199 t=102.9s M70 SUPPORT REPORT QUEUED searched body; missing documents=1 [session=1790096676-1] +#209 t=107.9s M0 INTEL COMPROMISE missing issued document concerns everon-mortar-1; defensive reinforcement requested [session=1790096676-1] +#217 t=138.1s M0 INTEL COMPROMISE missing issued document concerns everon-mortar-1; defensive reinforcement requested [session=1790096676-1] +#223 t=168.2s M0 INTEL COMPROMISE missing issued document concerns everon-mortar-1; defensive reinforcement requested [session=1790096676-1] +#224 t=198.4s M0 INTEL COMPROMISE missing issued document concerns everon-mortar-1; defensive reinforcement requested [session=1790096676-1] diff --git a/docs/evidence/hq-air-support-2026-09-22/recovery-native3-source-sha256.json b/docs/evidence/hq-air-support-2026-09-22/recovery-native3-source-sha256.json new file mode 100644 index 0000000..166290b --- /dev/null +++ b/docs/evidence/hq-air-support-2026-09-22/recovery-native3-source-sha256.json @@ -0,0 +1,13 @@ +{ + "addons/core/Scripts/Game/ERR/00_Core/ERR_AirfieldPlacement.c": "79d9baf40ed4890e129ec50f6852a6b86e3920390afda51cefe30daa045856a2", + "addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAirfieldMarkersProbe.c": "593e59664dbd7330b52674e5d4cc7b70db588cb75a1259ed808b74602501d541", + "addons/core/Scripts/Game/ERR/10_AI/ERR_AirAmmoMission.c": "4b39eafbea7e53f4105635552c44823b56bae1e8c48c327df0a5995c766f60ef", + "addons/core/Scripts/Game/ERR/10_AI/ERR_AirfieldSupport.c": "347e642638f67fb6547e8e88bb47310663f404121526e69020422036af36c194", + "addons/core/Scripts/Game/ERR/10_AI/ERR_BodyRecovery.c": "b91d767d14627867f1d5e08e3d6cc8e5d53352ca75b56cc242aeefee911a1b4a", + "addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoAccess.c": "917f9df36b93258a30b7af24b0ee52b65c5205405d8056bb721a9868010d64d1", + "addons/core/Scripts/Game/ERR/10_AI/ERR_InfantryAmmoTransfer.c": "b398cbf166fe55dd2ff518a1ac028d87dc27edc225e25c1ca3703704a978d994", + "addons/core/Scripts/Game/ERR/10_AI/ERR_NativeAirLogisticsProbe.c": "72065de413a64b20d23f31b74f2d0cfd467e87ee463310db80c4da02ed0b31df", + "addons/core/Scripts/Game/ERR/10_AI/ERR_ReconFlightComponent.c": "629abd79dec91982741621b24d2bad79d8f950a9a87bbe7a998d4a0451aa2bf1", + "addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelEvidence.c": "dc5d4957d9b3bce9874a7b06073b03548bfd8e59b4ab04313a83aa7789768695", + "addons/core/addon.gproj": "adee1fe3689108da7e2c0f4e7288a2f414d74208477ed5f9e4efad1c01030aa5" +} diff --git a/docs/external-addons.json b/docs/external-addons.json index 8008a33..571afdb 100644 --- a/docs/external-addons.json +++ b/docs/external-addons.json @@ -1,10 +1,11 @@ { "schema_version": 1, - "authorization": "User authorized RHS, WCS and BMP dependencies on2026-09-20; external assets remain in installed addons.", + "authorization": "User authorized RHS, WCS and BMP dependencies on2026-09-20; external assets remain in installed addons. Parachute Framework is required by the requested original paratrooper port and HQ-controlled drops (2026-09-22).", "direct_ai_dependencies": [ "595F2BF2F44836FB", "629B2BA37EFFD577", - "5E524E4FEECCA92B" + "5E524E4FEECCA92B", + "65930CB4CD0237B2" ], "addons": { "595F2BF2F44836FB": { @@ -59,6 +60,14 @@ "629B2BA37EFFD577" ], "project_sha256": "ad44151140adf62e99eaa639984c2b9c400be17481e934186d61c307b5221259" + }, + "65930CB4CD0237B2": { + "title": "Parachute Framework", + "version": "1.2.0", + "dependencies": [ + "58D0FB3206B6F859" + ], + "project_sha256": "183fbb521382a95ad33af9efc547147a80241bd536a29d124c93064b5ae5e8bc" } }, "resources": { @@ -91,6 +100,41 @@ "guid": "8D4BAA235F7EDBEA", "addon": "595F2BF2F44836FB", "verification": "Exact path/type/GUID record in installed owning resourceDatabase.rdb; read-only audit 2026-09-20" + }, + "Configs/Factions/RHS_ION.conf": { + "guid": "CB76A36EACFBDF35", + "addon": "595F2BF2F44836FB", + "verification": "Exact path/type/GUID in installed owning resourceDatabase.rdb; read-only audit 2026-09-21. Faction keys and physical group slots checked in owning PAK." + }, + "Configs/Factions/RHS_RF_MSV.conf": { + "guid": "627A8CDE681D223D", + "addon": "595F2BF2F44836FB", + "verification": "Exact path/type/GUID in installed owning resourceDatabase.rdb; read-only audit 2026-09-21. Faction keys and physical group slots checked in owning PAK." + }, + "Configs/Factions/RHS_US_USMC.conf": { + "guid": "F33C7BF22CBF3A8A", + "addon": "595F2BF2F44836FB", + "verification": "Exact path/type/GUID in installed owning resourceDatabase.rdb; read-only audit 2026-09-21. Faction keys and physical group slots checked in owning PAK." + }, + "Prefabs/Groups/BLUFOR/RHS_USAF/RHS_USAF_USMC_MEF/Group_USAF_USMC_MEF_FireTeam.et": { + "guid": "19843E954790DF28", + "addon": "595F2BF2F44836FB", + "verification": "Exact path/type/GUID in installed owning resourceDatabase.rdb; read-only audit 2026-09-21. Faction keys and physical group slots checked in owning PAK." + }, + "Prefabs/Groups/INDFOR/RHS_ION/RHS_ION_COY/Group_RHS_ION_COY_StaticSecurityTeam.et": { + "guid": "516C8C7400DF2C4D", + "addon": "595F2BF2F44836FB", + "verification": "Exact path/type/GUID in installed owning resourceDatabase.rdb; read-only audit 2026-09-21. Faction keys and physical group slots checked in owning PAK." + }, + "Prefabs/Groups/OPFOR/RHS_AFRF/MSV/Flora/Group_RHS_RF_MSV_Flora_FireGroup.et": { + "guid": "AB905EF799E0A0AE", + "addon": "595F2BF2F44836FB", + "verification": "Exact path/type/GUID in installed owning resourceDatabase.rdb; read-only audit 2026-09-21. Faction keys and physical group slots checked in owning PAK." + }, + "Prefabs/DeployedParachutes/Core/DeployedParachuteMK4.et": { + "guid": "9ADD554959C09197", + "addon": "65930CB4CD0237B2", + "verification": "Exact installed owning resourceDatabase.rdb path/type/GUID and inspected native prefab/scripts, 2026-09-22." } } } diff --git a/docs/generated-sites.md b/docs/generated-sites.md new file mode 100644 index 0000000..ec719ad --- /dev/null +++ b/docs/generated-sites.md @@ -0,0 +1,85 @@ +# Generated starts and radio camps + +Everon now chooses a new prison, radio camp and four mortar sites at preparation time. Other caches, +outposts retain their authored positions. The extraction helicopter uses the validated +Everon airfield pad (4800.953 / 11487.412), with no off-airfield fallback. The server +resolves the prison first, then the radio, before creating any site entities. +Joining clients receive the real replicated locations; intel keeps the same +stable destination IDs. + +Site authors can use `RandomClear 1` on a prison, radio or mortar definition. `Heading` +sets the authored fallback heading; `RootHeight` offsets a composition above its +surveyed ground (the radio/table composition uses 0.8 m). Runtime placement never +rewrites the configuration file. Existing definitions default to authored sites. + +Placement samples the island bounds and rejects water, obstructed footprints, +terrain varying by more than 0.6 m, nearby roads (12 m), and unsafe guard footing. +Prisons avoid physical runway/control-tower anchors by 1,500 m. The radio stays +at least 1 km from the prison and 300 m from other sites. The extraction pickup +must remain inside the prison-relative escape boundary with 100 m clearance. +Sampling yields after an 8 ms work budget, with a 30-second overall deadline and +12,000 candidate limit per site. The budget is checked between native terrain +queries, so a single engine query can exceed it. Authored fallback positions +must pass the same checks; otherwise preparation reports failure instead of +spawning an incomplete camp or waiting forever. + +The existing prison composition, gate, backpack and guards move together. +Player slots and escape-boundary tests use the same rotation. Admission still +waits for physical guards, inventory and the client's nearby replicated scene. +Spawn clearance uses a filled standing-volume trace for scenery and actual +character positions for body spacing, avoiding false overlaps from rotated +entity bounding boxes. Pending reservations remain part of the clearance check. +The radio camp has a radio and table inside a full-size tent, with an antenna +and sandbag cover outside. Its complete guard squad permanently defends a 20 m +area around the radio and cannot be reassigned by virtual HQ. See +[radio camp security](radio-camp-security.md). +It retains the existing contact-extraction-HQ action and defence progression. + +Partial intel displays a question mark at the centre of the containing 500 m +square. Exact identification changes it to a site icon at the real location. +The prison is always hidden. Notifications use the original Intel wording. + +`/esc killais` is an administrator-only debugging command centred on the +administrator's current living prisoner. It applies lethal damage to AI +characters within 1,000 m in three dimensions, including friendly AI and seated +crews. Player-controlled and retained player-roster bodies are excluded, as are +vehicles and structures. Death callbacks run normally; the command does not +refill AI forces or manufacture HQ reports. `/esc help killais` explains it. + +Four mortar sites each have a physical gun, four crew, finite shells and +targeting through the HQ radio-report chain. Sites are at least 1 km apart and +500 m from the prison. See [mortar intel and perimeter guards](mortar-intel-and-prison-map.md). + +## Validation + +`test_generated_sites.py` executes the actual bounded-search scheduler; +`test_debug_ai.py` executes kill eligibility. Existing player-tool, admission, +prison-slot and intel-feedback tests cover the changed boundaries. +`--project core --smoke generated-sites` opts into real randomized placement and +tests admission, hidden/identified markers, authenticated killais (including a +seated AI), and the radio objective. The `opening-tools` and `airfield-markers` outcomes also use the live site +definitions. Other Workbench smoke outcomes explicitly load +`Configs/ERR/Tests/LegacySites.conf` to retain their historical deterministic +fixtures, including the retired western cache and old extraction position. +Ordinary Workbench play and dedicated servers use the live definitions. + +On 2026-09-22, the full `python3 tools/check.py` suite passed. The final native +`generated-sites` fixture passed 39 assertions at a randomized Everon start: +prison at approximately (5100, 9137), heading 89 degrees; radio at (5991, 5659). +It placed twelve physical prisoners inside the rotated prison, verified that +occupied body/wall positions still reject spawning, and checked admission with +stocked backpack, hidden partial-intel markers, exact +discovered coordinates, authenticated AI killing (including a seated passenger), +and the existing radio transmission objective. The runner confirmed unchanged +source inputs and complete process cleanup. Native diagnostics still include +external RHS/WCS localization and stock resource-keyword errors; the fixture had +no script/runtime failure. A captured camp view was inspected for radio/table, +antenna and shelter placement. + +Local scripted fixtures do not establish ordinary input, remote-client +replication, or complete multiplayer acceptance. Dedicated-server validation is +still outstanding; this change has not been published or deployed. + +The western guarded vehicle/cache site has been removed. The medical stash now +provides the second reachable source of radio intel; mortar logistics uses the +existing eastern outpost. See [airfield and map changes](airfield-extraction-and-map-icons.md). diff --git a/docs/hill-scouts.md b/docs/hill-scouts.md new file mode 100644 index 0000000..14a9ee0 --- /dev/null +++ b/docs/hill-scouts.md @@ -0,0 +1,80 @@ +# Hill scouts + +Everon's `ScoutCount 10` creates ten independent, finite observation posts before +player admission. `ScoutCount` is a scenario-definition field (0–32; default zero +for existing authored/test scenarios). It does not depend on convoy settings. + +The server samples island elevation, then surveys random dry standing points on +local crests. Posts must be at least 900 m apart, 600 m from the prison and 150 m +from other mission sites. Minimum elevation is 35 m or 18% of sampled island +maximum, whichever is higher. Eight terrain samples 150 m away must show a mean +drop of at least 6 m, with four at least 5 m lower. At least two of eight physical +350 m sight traces must be clear for 95% of their length. The character faces the +best surveyed view. Survey work is limited to 6 ms per preparation tick, 100,000 +candidates and a 45-second real-time deadline. Unsupported terrain fails with a +specific preparation error instead of silently placing scouts in water/forest +obstructions or admitting fewer than requested. + +Each post contains one native AI soldier, an indefinite defend waypoint with an +8 m radius, binoculars, a scoped sniper rifle, and a custom radio backpack with +real BaseRadioComponent/SCR_RadioComponent manpack capability. The pack uses the +Kolobok model, weighs 10 kg empty, and reserves 6 litres for ammunition. Compatible +full magazines are inserted into this exact pack until native capacity refuses +another. One operation per post can be outstanding. The deadline, callback +success, physical radio, binoculars and sniper rifle are checked before admission. +The tested SVD loadout fits 40 full spare magazines in the pack, in addition to +its native loadout ammunition. No ammunition is periodically granted afterward. + +US and RHS_USAF use the native M21 sniper base; other enemy selections use the +native SVD sharpshooter base. Both the group and character receive the selected +enemy faction. The separate ScoutEast, ScoutWest and ScoutRadioPack prefabs are +intended extension points for additional faction-specific scout equipment. The +radio pack is a field-radio loadout, not a deployable player respawn point. + +Scouts inherit the prison's initial AI freeze. On release they use native +RETURN_FIRE: hold fire while observing, engage when native group perception +considers them threatened, and return to holding fire when that threat ends. +They remain registered HQ observers but permanently reserved against tactical +reassignment, courier/resupply work, and assault/search orders. Generic startup +launcher, optic and radio fitting does not overwrite their specialist equipment. +The finite force ledger records one original soldier per post. Killed scouts are +never replaced; the mission owns and cleans up their groups and waypoints. + +Reporting uses the existing clear-visual-contact capture and physical radio +uplink. Reports include observed coordinates, visible travel mode, weapon +categories (drawn weapons only, within the existing identification limits), and +nearby visible escapist count. Road status comes from the captured coordinate +against actual road width, segments and height, not the target's later position. +A scout retains at most 64 recent identity/observation snapshots. Two credible +same-target/same-source sightings 2–30 seconds apart supply an average horizontal +velocity, km/h speed and compass/azimuth direction. Changed travel modes, +implausible speed and stale/replayed observations cannot produce a motion +estimate. All data is frozen before the existing originating call/transmission +delays; removing the physical radio or losing the carrier interrupts that route. +No target inventories, hidden occupants or live player physics are inspected. + +Validation: `tests/test_scouts.py` executes production terrain/road geometry, +observed-motion estimation and the finite admission state machine, including +pending inventory, timeout, client/stop guards and no replacement/refill after +completion. The full repository suite passed. The production `airfield-markers` +Workbench fixture additionally validates all ten physical bodies, complete +magazine counts and full native capacity, faction identity, manpack capability, +return-fire mode, permanent HQ reservation and inter-post separation. Native +results are recorded below. Dedicated multiplayer observation +and combat acceptance remain separate from these local Workbench checks. + + +The final native run on 22 September 2026 used +`/tmp/erri-scout-final/logs/logs_2026-09-22_17-04-55`. It completed 52 gameplay +assertions and 11 scout-specific checks, with zero script errors. Ten independently +randomized posts had full 40-magazine SVD packs, matching the preceding successful +layout in `/tmp/erri-scout-native3`. The full regression suite completed in +`/tmp/erri-scout-check2.log`; the final movement addition and affected HQ/intel +regressions were checked again afterward. + +The runner's strict result was `cleanup-failed`, with `smoke-completed` recorded +before cleanup: it could not classify an exiting `enfMain` with an empty command +line. A subsequent escalated host-visible `assert_prefix_idle` passed. Existing +vanilla GUI/resource and external RHS/WCS localization errors also remain in the +logs. This is not a clean strict runner result or dedicated multiplayer acceptance. +No server deployment, Workshop publication or Git push was performed. diff --git a/docs/hq-air-support.md b/docs/hq-air-support.md new file mode 100644 index 0000000..166bb33 --- /dev/null +++ b/docs/hq-air-support.md @@ -0,0 +1,93 @@ +# HQ airborne support and recovery + +HQ uses delivered sightings and friendly check-ins to decide on reinforcement. +A drop needs at least two sightings, confidence of 70% or better, uncertainty no +larger than 160 m, and a credible on-foot speed no greater than 6 m/s. Reports +older than 90 seconds are unsuitable. Sufficient nearby or already committed +infantry prevents the drop. An unmet need must persist for 45 seconds, reduced +to 20 seconds after two confirmed local losses. Committed drops have an eight +minute cooldown. Radio delivery and a clear real landing corridor are required; +a missing radio, changed memory, occupied airspace, or unavailable troops cancels +the order. No hidden player position supplies an HQ target. + +Eight physical passengers board the search helicopter at the airport in two +four-person teams. The same actors transfer into Parachute Framework canopies +and become ordinary HQ infantry after landing. Passengers are not recreated at +the destination. A drop pass must have a suitable heading, at least 15 m/s speed +and 90–180 m terrain clearance. Drops are staggered two seconds apart. + +The helicopter covers the order's area for five minutes after finishing its drop +pass, then HQ can radio an order to return. It lands at its original airfield, +services for 60 seconds, rearms mounted magazines and rocket pods, refuels and loads another +squad. The original aircraft and aircrew remain. The round has four attempted +passenger loads, 24,000 service rounds, 512 rocket-loading attempts and 12,000 fuel units; failed spawns and +losses are not refunded. An incomplete passenger drop retains surviving aboard +soldiers. The airport has a tent, supply box and service vehicle. Losing the depot +vehicle prevents subsequent service. + +A separate helicopter waits at the airport for ammunition missions. The depot and +cargo helicopter prepare independently of the search helicopter departure timer. A delivered +low-ammo check-in (at most 30 small-arms rounds per soldier) requests assistance. +HQ reserves the receiving infantry and sends separate physical radio orders to +the crew and recipient. A quiet search task is interrupted only after the replacement +radio order arrives. The aircraft loads up to twelve magazines matching the +unit's native weapons, flies to a clear nearby landing pad, and lands. Native +inventory transfer requires the original recipient to reach the stopped aircraft; +there is no remote ammunition refill. Remaining cargo stays with the original +helicopter. Unresolved native inventory operations block a subsequent trip, and an +already submitted magazine is never submitted again. There are at most twelve +delivery attempts per round. Permanent site +guards are not pulled away for these rendezvous. + +Each mortar fire order requests eight HE shells spread over an 80 m radius +(160 m diameter). Individual shells still require a current valid order, physical +ammunition, a usable crew, a ballistic solution, and clear friendly/settlement +safety checks. Thus eight is the requested salvo, not a promise to keep firing +after the crew dies or a friendly enters the impact area. Pending drops, descending +paratroopers and active helicopter supply landing zones exclude mortar impacts. + +Mission enemy bodies are retained until a search and its radio report complete. +Native cleanup of a parent wreck is also blocked while it contains retained evidence. +A delivered body sighting dispatches a separate recovery group from a friendly +site. Searchers must reach the actual body, stop fighting, spend ten seconds +nearby, and pass a line-of-sight check. They compare the remaining physical +folders against the body's issued-document record. Document contents are assigned +while their owner is alive; pickup uses those same site IDs. Missing documents +make those sites potentially compromised. The resulting radio report can order +available infantry to defend them. This is a defensive hypothesis, not a new +sighting and not authorization for mortar fire. If the team or its radio is lost, +HQ receives no stolen-intel knowledge and the body stays retained. Once HQ receives +the completed search report and records its compromised sites, the corpse is +unblacklisted and scheduled for native cleanup after 300 seconds. A search without +a delivered report cannot release it; repeated delivery cannot reset that timer. +This retention applies to registered mission enemy AI, not player corpses. + +`/esc hq heli show` includes airborne decisions, airport stocks and recovery status. +The combined addon now depends on **Parachute Framework** (`65930CB4CD0237B2`; +installed/tested input version 1.2.0). Framework code and assets remain external. + +Validation, 22 September 2026: + +- `python tools/check.py` passed, as did the updated native-context access regression. +- Native airborne fixture: eight original passengers boarded, deployed their canopies, + landed alive, and formed two original teams. The same helicopter returned, consumed + gun ammunition/fuel stock and departed with another eight passengers. The fixture + supplies a controlled drop order and advances the cover deadline after landing; + actual HQ selection and cover timing/target are tested separately as production policies. +- Native recovery fixture: a real issued document was removed from a real guard's + inventory, the guard died, and native garbage insertion was rejected. A normal + delivered body sighting spawned a separate team; that team reached and inspected + the body, then delivered the missing-document report to HQ. +- Native cargo fixture: real low-ammunition check-in, both HQ downlinks, twelve + airport magazine-loading attempts, takeoff, flight, landing, infantry approach, + and three confirmed exact-item transfers. Native Mi-8 storage access has 85 + contexts and 38 actions at the cargo door; both bounded scans now admit it. + This run did not sight its separate randomly placed forensic body, so combined + fixture completion is not claimed. Recovery is evidenced by the earlier run. + +[Native excerpts and source hashes](evidence/hq-air-support-2026-09-22/) retain the +scope of each run. Dedicated multiplayer, adverse network conditions, all faction +loadouts, spent rocket-pod reload and a complete cargo return/service/second-trip +cycle still need live acceptance. Airport stocks are finite service budgets, not +individual fuel-can/round entities. The current compromised-site response dispatches +infantry defenders; it does not construct new physical roadblocks. diff --git a/docs/migration-provenance.json b/docs/migration-provenance.json index f9acf26..1190d3b 100644 --- a/docs/migration-provenance.json +++ b/docs/migration-provenance.json @@ -123,7 +123,7 @@ "source": "escapists-intel/Scripts/Game/EscapistsIntel/EI_IntelService.c", "sha256": "0009786c543c2758dcd55d3d6936feca5641dd4c4b2ff820564a38815e4cca57", "destination": "addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelDiscoveryFeedback.c", - "changes": "Adapt team discovery notification behavior using successor location events, bounded coalescing and rough-location secrecy." + "changes": "Restore original partial, identified and exhausted-intel wording; adapt site-type nouns and retain successor reliable delivery, bounded coalescing and rough-location secrecy." }, { "source": "escapists-intel/Scripts/Game/EscapistsIntel/EI_IntelLifecycle.c", @@ -154,5 +154,65 @@ "sha256": "9fb9a76ccaaff2a3c85cb6112ef5f6d272b3570bd4216d81c723c0f0c62cef84", "destination": "addons/core/UI/layouts/ERR/AdminMenu.layout", "changes": "Author successor settings/HQ/journal pages with vanilla widget inheritance and new resource identity; use owned menu layout as design reference." + }, + { + "source": "escapists-ai/Scripts/Game/EscapistsAI/EAI_ImprovisedPrisons.c", + "sha256": "e1b7dd3b7b45bc803e61e2031030d873101947def8b6a41fe450555e90d000b9", + "destination": "addons/core/Scripts/Game/ERR/00_Core/ERR_GeneratedSites.c", + "changes": "Adapt owned clear-ground terrain sampling, rotated trace volumes, road/airfield exclusion to asynchronous bounded successor site generation. No original mission dependencies; successor prison and vanilla radio camp." + }, + { + "source": "escapists-ai/Scripts/Game/EscapistsAI/EAI_AirRecon.c", + "sha256": "7e72c9eac0fce21865f09a923cbfd638c25939c8492b3e1e5dfdda1f1394f51e", + "destination": "addons/core/Scripts/Game/ERR/00_Core/ERR_GeneratedSites.c", + "changes": "Use owned physical runway/control-tower prefab classification for prison exclusion; no original reconnaissance service or dependency." + }, + { + "source": "escapists-ai/Scripts/Game/EscapistsAI/EAI_AirRecon.c", + "sha256": "7e72c9eac0fce21865f09a923cbfd638c25939c8492b3e1e5dfdda1f1394f51e", + "destination": "addons/core/Scripts/Game/ERR/10_AI/ERR_ReconAirports.c", + "changes": "Adapt incremental airport clustering, runway classification and clear departure-pad survey into the successor HQ-owned service." + }, + { + "source": "escapists-ai/Scripts/Game/EscapistsAI/EAI_AirRecon.c", + "sha256": "7e72c9eac0fce21865f09a923cbfd638c25939c8492b3e1e5dfdda1f1394f51e", + "destination": "addons/core/Scripts/Game/ERR/10_AI/ERR_AirReconSystem.c", + "changes": "Adapt original initial/loss cadence, one active aircraft and retained wrecks to mission escape phase, settings, ownership and finite force ledger." + }, + { + "source": "escapists-ai/Scripts/Game/EscapistsAI/EAI_AirRecon.c", + "sha256": "7e72c9eac0fce21865f09a923cbfd638c25939c8492b3e1e5dfdda1f1394f51e", + "destination": "addons/core/Scripts/Game/ERR/10_AI/ERR_ReconFlightComponent.c", + "changes": "Adapt airport takeoff, terrain-following, search/orbit, lost-contact search, return and player release; successor native clear perception and physical HQ radio pipeline. Excludes assault/rearm/recovery." + }, + { + "source": "escapists-base/Scripts/Game/Components/Heli/ESCT_HeliBehaviourBaseComponent.c", + "sha256": "d363edafe59162ebbde5d84d17c9786cb60ef83ebc3e5003bfc812ab48dd0812", + "destination": "addons/core/Scripts/Game/ERR/10_AI/ERR_ReconFlightComponent.c", + "changes": "Adapt physics velocity/attitude, engine and crew-seating setup to current native APIs and unique successor resources." + }, + { + "source": "escapists-base/Scripts/Game/AI/Behavior/ESCT_AIVehicleBehavior.c", + "sha256": "32c83fefde82955670f237ed4c83a3606c3af2a97d5c6f882d15bc6477cd8bf9", + "destination": "addons/core/Scripts/Game/ERR/10_AI/ERR_ReconCrewLocks.c", + "changes": "Adapt native get-out behavior suppression to exact original flight crew and active flight phase; release on landing, loss, takeover or mission stop." + }, + { + "source": "escapists-ai/Scripts/Game/EscapistsAI/EAI_AirAssault.c", + "sha256": "a9c0c2bf59fb4f9b351913708cee54a302a9e447d30c2766faa91c7573af1b6d", + "destination": "addons/core/Scripts/Game/ERR/10_AI/ERR_AirAssaultLoad.c", + "changes": "Port original physical boarding, canopy transfer/descent or aircraft weapon service; integrate finite HQ-owned support and selected factions." + }, + { + "source": "escapists-ai/Scripts/Game/EscapistsAI/EAI_AssaultParachute.c", + "sha256": "b2d2be240d184c436a5b2fd1a03d446763a1c27b6b5c825a988b05feaec7a346", + "destination": "addons/core/Scripts/Game/ERR/10_AI/ERR_AssaultParachute.c", + "changes": "Port original physical boarding, canopy transfer/descent or aircraft weapon service; integrate finite HQ-owned support and selected factions." + }, + { + "source": "escapists-ai/Scripts/Game/EscapistsAI/EAI_AircraftAmmo.c", + "sha256": "52bed2b0008762f221bed4f139cfe0a34e69e0ee455ef3dc47276d3dc3373c45", + "destination": "addons/core/Scripts/Game/ERR/10_AI/ERR_AircraftAmmo.c", + "changes": "Port original physical boarding, canopy transfer/descent or aircraft weapon service; integrate finite HQ-owned support and selected factions." } ] diff --git a/docs/mortar-intel-and-prison-map.md b/docs/mortar-intel-and-prison-map.md new file mode 100644 index 0000000..d41dc53 --- /dev/null +++ b/docs/mortar-intel-and-prison-map.md @@ -0,0 +1,68 @@ +# Mortar intel, prison visibility and perimeter guards + +The live Everon configuration contains four mortar sites (`everon-mortar-1` through +`everon-mortar-4`). Each is placed on surveyed clear, dry terrain, at least 1 km +from another mortar and 500 m from the prison. They use the existing physical gun, +four-person crew, finite initial ammunition, HQ targeting and permanent station +assignment. The gun's destruction still releases its surviving crew. + +Each site registers a normal replicated discovery location. Untargeted recovered +intel can select any undiscovered or partly discovered mortar site. A partial +clue displays the native `mark-question` icon at the centre of its 500 m map +square, with an unknown-location label. Identification changes that same marker +to `artilleryFireMission`, moves it to the actual position, and names the site. +The prison never displays a discovery marker, even when its knowledge is complete. + +The 3–5 opening prison guards are placed once, at separate random positions +12–24 m from the prison centre. Placement samples angular sectors with jitter, +checks supported dry terrain and standing clearance, and reserves all positions +before moving any guard. They remain frozen until the gate is unlocked. The +existing physical manpack-radio requirement is unchanged. + +The ammunition courier previously required exactly one battery. It now accepts +multiple batteries and selects a depleted recipient between trips. A pending +report, command or native inventory move retains its original target. The +existing outpost still has one finite reserve of 12 shells, shared by all four +batteries; adding batteries does not duplicate that stock or courier group. + +## Original intel messages + +Wording is taken from the owner's +`escapists-intel/Scripts/Game/EscapistsIntel/EI_IntelService.c`: + +- `New location marked. Type unknown.` +- `Hey! A [type] was identified in the intel!` +- `Every known location has already been identified. This intel doesn't help us.` + +Successor site types supply the appropriate noun, including `mortar site`. +Notifications retain reliable delivery and per-round duplicate protection. +Multiple discoveries in one scan may be combined into a multiline message; +rough clues never disclose the location type. A spent folder cannot give another +clue. Separate untargeted folders can concern separate locations, so two pickups +may produce two question marks rather than one fully identified site. + +## Validation + +The full repository checks passed after the mortar/courier changes. A further +production-method regression covers selection among four batteries, unavailable +recipients and target preservation during pending work. The Workbench run in +`/tmp/erri-mortar-map4/logs/logs_2026-09-22_16-11-24` passed 30 assertions, admitted +the player, checked frozen perimeter guards and their radio, unlocked the prison, +and recovered seven physical folders to identify all four mortar sites. It +completed with confirmed cleanup and unchanged source/dependency inputs. + +That run preceded the final restoration of question marks and original messages; +its additional validation is recorded below. Native reports still include the +existing RHS/WCS localization and stock UI/resource errors. These are local +Workbench tests, not dedicated multiplayer acceptance. No server deployment or +Workshop publication was performed. + +The final question-mark/message run, +`/tmp/erri-mortar-map5/logs/logs_2026-09-22_16-19-19`, completed 35 assertions with +no script errors or VM exceptions. It verified an approximate question marker +before recovering physical folders and checking the four final artillery icons. +The immediate runner cleanup check encountered an exiting process and reported +cleanup failure; a subsequent host-visible `assert_prefix_idle` confirmed the +private prefix idle. Source and external-addon inputs remained unchanged. +Production-method tests also check the original message strings, mixed discovery +batches, reliable-delivery deduplication, and exhausted-intel feedback. diff --git a/docs/mortar-stations.md b/docs/mortar-stations.md new file mode 100644 index 0000000..5ca63d6 --- /dev/null +++ b/docs/mortar-stations.md @@ -0,0 +1,46 @@ +# Permanent mortar crew assignments + +Each of the four mortar sites has a four-person crew assigned to its physical gun until +that gun is destroyed or removed. This is separate from the lifetime of an HQ +fire order: target expiry, cancellation, completed salvos, and ammunition +depletion do not release the station. + +A gunner walks to and boards the original mortar using native AI. While the gun +is intact, native AI dismount behaviors are ineligible for its own crew. The +other crew members hold their positions while retaining aiming, firing, radio, +inventory and damage behavior. If the gunner is lost, a surviving ammunition +bearer can approach and take the empty gunner position. No crew or ammunition is +created to replace losses, and occupied seats are never forcibly cleared. + +Gun destruction releases movement restrictions and the HQ support reservation, +allowing surviving crew to leave and receive ordinary assignments. Mission stop +also cleans up the station controls. Player-controlled characters, unrelated +groups, other mortars and vehicles are unaffected. The depot courier remains a +separate group and can still deliver the existing finite ammunition stock. + +`tests/test_mortar_station.py` covers authority, ownership, player exclusion and +restriction lifetime. `--project core --smoke mortar-station` exercises native +idle boarding, competing dismount/movement orders, and release after damage +destroys the original mortar. Local fixtures do not establish multiplayer +replication or ordinary player-input acceptance. + +On 2026-09-22, the station fixture passed all seven native checks: idle boarding, +refusal of a high-priority dismount, retention after fire-order cancellation, +all three support members resisting movement orders, and actual movement after +gun destruction. The runner retained its launch source snapshot. Its initial +cleanup check raced an exiting process; an independent post-run check then +confirmed that the disposable prefix was idle. + +The existing `mortar-fire` fixture also completed with the station rule enabled: +an actual radio uplink/downlink led to a native projectile, consumed exactly one +of the 27 original shells, and stopped without duplicate firing or replenishment. +Its setup now unlocks the prison before waiting for combat AI. The full repository +check suite and targeted station/activity tests passed. Native resource warnings +from external addons remain; neither fixture is a dedicated-server acceptance +test. + +The firing run passed 51 assertions with no script errors. Its independent +post-cleanup check confirmed both an idle prefix and source hashes unchanged +from launch; the original runner's cleanup-race report is preserved. + +The sites are now discoverable through intel; see [mortar intel and map behavior](mortar-intel-and-prison-map.md). diff --git a/docs/prison-patrol-and-debug-intel.md b/docs/prison-patrol-and-debug-intel.md new file mode 100644 index 0000000..67837a1 --- /dev/null +++ b/docs/prison-patrol-and-debug-intel.md @@ -0,0 +1,45 @@ +# Prison opening and intel debug command + +The prison receives a finite 3–5-person squad drawn from the selected enemy +faction's group profile. Selection happens before the native member spawn request. +An RTO slot is preserved where available, and preparation confirms an actual +large radio in the squad's inventory. For profiles without one, a soldier equips +an AN/PRC-77 (US/USAF) or R-107M; the native loadout operation can replace an +existing backpack. No further radio grants occur after initial preparation. +The opening squad is placed once at separate random clear positions 12–24 m +around the prison, while still frozen. Other sites retain their authored squad sizes. Existing prison AI freeze/release +hooks still apply. + +Administrators can use `/esc cheat intel` from their current living prisoner. +The server checks six separate nearby ground positions, then creates six normal +intel folders. If placement or creation fails, no partial batch is retained. +The command does not insert anything directly into inventory or reveal locations; +picking up a folder invokes the ordinary discovery rules. Seated characters and +positions without enough accessible ground are refused. + +## Verification, 22 September 2026 + +`python tools/check.py` passed after the production changes. The admin command +regression includes authorized dispatch, unauthorized refusal, a placement-failure +reply, and no inventory-grant side effects. + +The `opening-tools` Core Workbench fixture completed with 22 assertions and no +script/runtime failures in: +`/tmp/erri-opening-tools2/logs/logs_2026-09-22_15-15-11`. +It exercises roster sizes 3, 4 and 5; physical squad size; frozen living guards; +a physically equipped manpack; native fallback equipment on a non-RTO; unauthorized +command refusal; six fresh ground folders; actual pickup and normal discovery; +and normal prison unlock. Source was unchanged throughout the run, dependencies +were unchanged, and the runner confirmed cleanup. This is local Workbench +integration, not a dedicated multiplayer test. + +The strict native reporter still returns failure for existing RHS/WCS localization +and world `Parent`/`SlidingTrackMaterial` resource errors. The same errors are in +`/tmp/erri-mortar-station-fire2` from before these changes. They were not suppressed. + +The live RKS #2 startup log for 22 September at 13:00 UTC records its extraction +Mi-8 alive, grounded, stable and fueled around coordinates 7012/7500. The local +fixture also confirms that aircraft is initially usable. Those authored coordinates were off the airfield. The follow-up change moves +the extraction helicopter to a validated airfield pad and rejects obstructed or +off-airfield placement; see [airfield and map changes](airfield-extraction-and-map-icons.md). +The earlier log establishes initial aircraft condition, not the later crash sequence. diff --git a/docs/radio-camp-security.md b/docs/radio-camp-security.md new file mode 100644 index 0000000..8492028 --- /dev/null +++ b/docs/radio-camp-security.md @@ -0,0 +1,40 @@ +# Radio shelter and permanent guards + +Everon's generated radio camp places the radio and its table inside a full-size +vanilla Soviet tent. The tent is offset 1.5 m sideways from the radio/table centre +to leave room around the interior supports. The antenna and sandbags sit outside +the shelter. Placement retains the existing dry, clear terrain survey. + +Every radio definition must request a physical guard squad (`Guarded 1` or an +explicit guard prefab). Scenario preparation already waits for all requested +guards to be present, conscious and in the configured enemy faction. The radio +squad receives an indefinite native Defend waypoint centred on the radio, with a +20 m radius, instead of defending its offset spawn anchor. + +When HQ registers a radio squad, it permanently reserves it for site security. +The existing eligibility gate then rejects investigation, pursuit, reinforcement, +resupply and courier assignments, including orders revalidated at delivery time. +The squad remains registered for physical status and contact reporting. The +mortars' release path cannot release a radio squad, because it requires ownership +of an actual destroyed mortar. Local combat and ordinary casualty behavior remain +native; this does not freeze the defenders after the prison opens or replace +casualties. + +## Verification + +The registration regression executes the actual HQ registration method and checks +that radio squads remain reserved through repeated registration, while ordinary +outposts retain their existing eligibility. The full repository suite passed. +The Workbench fixture additionally checks a physical tent roof over the radio, +standing room within interaction distance and line of sight, the complete living +squad, refusal of courier reservations, preservation against an unrelated mortar +release, and the centred indefinite defend waypoint. + +On 22 September 2026 the native run in +`/tmp/erri-radio-tent3/logs/logs_2026-09-22_16-42-16` completed 46 gameplay +assertions without script errors or VM exceptions. Source and external addon +inputs were unchanged, and process cleanup was confirmed. The fixture also +repeated player admission, prison guards, four-mortar intel recovery and map +presentation checks. Existing vanilla/RHS/WCS resource errors remain in the +strict report; this is local Workbench integration, not dedicated multiplayer +acceptance. No server deployment or Workshop publication was performed. diff --git a/docs/search-helicopter.md b/docs/search-helicopter.md new file mode 100644 index 0000000..e7e3680 --- /dev/null +++ b/docs/search-helicopter.md @@ -0,0 +1,95 @@ +# Search helicopter + +The combined mission now owns an airport reconnaissance service adapted from the +original `EAI_AirRecon` and `ESCT_HeliBehaviourBaseComponent`. It runs on the server +through VirtualHQ's maintenance tick. The original projects are not runtime +dependencies. + +Prison escape starts a 15-minute countdown. A single armed Mi-8 then departs from +a clear pad at a discovered airfield. Losing that aircraft or its usable original +pilot starts a fresh 15-minute replacement delay. Parking or player takeover does +not create a replacement. Wrecks and surviving original crew remain in the world; +there is no cleanup-driven instant replacement. Explicit native aircraft deletion +also starts the loss delay; mission teardown does not restart the service. The round retains at most 64 +attempted aircraft and uses the shared finite force ledger. + +Airfields are discovered incrementally from physical runway/control-tower prefab +clusters, with an optional validated `ERR_ReconAirport` marker. Pads are surveyed +35–220 m from an airfield centre, with a 14 m clear footprint, terrain tolerance, +water exclusion and a 150 m vertical clearance trace. Failed departure placement +gets three attempts 30 seconds apart; batches use the configured delay. + +The aircraft uses the original server physics flight approach: vertical takeoff, +40 m/s cruise, terrain look-ahead and 120 m terrain clearance. Its four native +pilot/gunner seats are populated before departure. The original crew is locked +aboard during flight and reserved against ground HQ reassignment. The engine's +native gunners retain their weapons and combat behavior. The current stock armed +Mi-8 replaces the old custom left-gun mount that is absent from the installed game. +US/RHS_USAF select the US pilot loadout; other enemy choices select the Soviet +loadout. Aircraft, group and crew all receive the selected enemy faction. + +Without a contact, it searches random dry island sectors or delivered HQ sighting +coordinates. Actual native clear visual sightings of players or their occupied +vehicles produce a 300 m shadow orbit, with an additional 180 m horizontal +standoff. Two observation snapshots estimate motion; no live hidden player +positions or velocities drive the search. After losing sight it searches around +the last observation for two minutes, then resumes sector searches. Crew reports +use the normal physical-radio call, transmission and delivery pipeline to HQ. +A missing or incapacitated radio carrier can interrupt that route. + +Low fuel (less than 50 native fuel units) or an administrator return request sends +the same aircraft back to its departure pad. It lands and stops its engines, retaining the surviving crew for airport servicing. +HQ-controlled passenger drops, post-drop cover, reloading and a separate ammunition +helicopter are described in [HQ air support](hq-air-support.md). A player boarding, taking the crew group or +changing the aircraft's faction releases scripted flight control. + +Administrator commands: + +- `/esc hq heli show` — phase, launch delay and pending countdown. +- `/esc hq heli timer set 15` — save the launch/replacement delay in minutes + (1–1440). Resets a pending countdown; an existing aircraft remains active. +- `/esc hq heli return` — return the current searching helicopter to its airfield. + +The persisted key is `heliTimerMinutes`, default 15. Older settings files acquire +that default; the original settings importer preserves the original key. Normal +configuration validation and save-failure handling apply. + +`tests/test_air_recon.py` executes the production launch/loss schedule and flight +geometry. `tools/headless_workbench.py --project core --smoke air-recon` is an +opt-in native fixture: it shortens the test countdown, arranges a runway encounter, +requests return, destroys the first aircraft and transfers its replacement to the +escapists faction. These +fixture actions do not change production timing or give the helicopter artificial +perception. A focused `--recon-takeover-only` variant exercises native faction handover, +control release and explicit native entity deletion without +repeating the full flight. + +The full repository suite passed in `/tmp/erri-recon-check5.log`. The final +removal-notification regression and affected native lifecycle/runner checks passed +afterward. The 22 September native run +`/tmp/erri-recon-native4/logs/logs_2026-09-22_17-39-45` passed actual airfield +launch, conscious original crew, native player detection, shadow orbit, radio +sighting delivery, more than 300 m of flight, same-aircraft landing, no replacement +while parked, destruction-triggered full delay and retained-wreck replacement. +An earlier run flew more than 650 m. Both full-flight runs ended at a failing +fixture boarding call; forced player boarding also failed in `/tmp/erri-recon-takeover1`. The accessible +seat was found and the owner-routed request accepted, but no actual occupancy +followed. Player entry and its control-release branch remain unverified; the +final focused fixture instead tests the separate native faction-handover branch. +These Workbench runs are not dedicated multiplayer acceptance. No Workshop +publication or server deployment is included in this change. + + +The final focused native run was +`/tmp/erri-recon-ownership-final/logs/logs_2026-09-22_17-54-34`. +All 13 recon assertions completed with zero script errors: native original crew, +airfield-only departure (including a refused pad and subsequent retry), actual +faction handover/control release, and explicit entity deletion starting one full +900-second replacement delay. The final addon files were separately compared to +the launch snapshot and matched. + +The strict runner result remains `cleanup-failed`, with `smoke-completed` recorded +before cleanup: an exiting `enfMain` had an empty command line. A subsequent +host-visible `assert_prefix_idle` passed. The preserved runner record has not been +relabeled as a clean strict run. Existing external localization/resource warnings +remain separate from the zero script-error count. diff --git a/docs/supply-convoys.md b/docs/supply-convoys.md new file mode 100644 index 0000000..065758b --- /dev/null +++ b/docs/supply-convoys.md @@ -0,0 +1,43 @@ +# Supply convoys + +The production HQ now uses `ERR_SupplyConvoySystem`, `ERR_SupplyConvoyService` and `ERR_SupplyConvoyTactics`, adapting the owned original `EAI_SupplyConvoys.c` to the combined mod's native AI and force ledger. + +## Configuration + +Esc → Mission settings → HQ → **Convoys next round** accepts **0–20** or **Random** (uniformly 0–20). The original default is **3**. The server resolves and freezes this count when the round is created. `/esc convoys show`, `/esc convoys set 3` and `/esc convoys set random` use the same authenticated command service. `/esc hq convoy count ...` is an alias. Changes do not create or delete an active convoy. + +The existing `automaticConvoyEnabled` switch remains supported. A saved zero continues to disable automatic startup. `/esc hq convoy start` can consume the next unused slot in the current round's configured allowance; it cannot replace a consumed slot. The settings importer preserves the original exact `convoyCount`, including zero, rather than reducing it to one convoy. + +## Vehicles, soldiers and cargo + +Each USSR convoy uses the original order: PKM UAZ, ammunition Ural, troop Ural, PKM UAZ, BMP-1, PKM UAZ. There are **25 original soldiers**: eleven vehicle crew and all fourteen Ural passenger seats, alternating between two independent seven-person infantry teams. Drivers and gunners stay in separate vehicle groups. The groups use the successor's memberless prefab, not the original framework's group-spawn hooks. + +One finite receipt reserves eight groups and 25 bodies before creation. Partial creation consumes that slot and preserves surviving entities. The production budget permits the existing 60-body allowance plus 25 bodies per configured convoy, within the shared 256-formation ledger. Losses never refund convoy slots. This is an admission ceiling, not a performance guarantee for twenty simultaneous convoys. + +The ammo truck receives eight random weapons from the convoy faction's native arsenal and six matching magazines/projectiles per muzzle of each successfully inserted weapon. The batch has a 96-ammunition-request ceiling and is issued once. Storage failures reduce the actual load; there is no refill after looting. Vehicle contents, casualties and surviving soldiers remain physical after controller release. The earlier infantry rendezvous service still uses the first convoy's compatible AK magazine stock; this change does not distribute that separate service across all trucks. + +## Travel and combat + +After prison escape and existing force admission, automatic deployment begins after a 30-second grace period. Every five seconds it tests up to eight road formations, for at most 120 startup passes. It uses friendly military outpost, depot and radio-site road approaches within 500 metres, deduplicated at 300 metres. Starting formations are separated by up to one kilometre and retain all existing road, terrain and obstruction checks. + +The initial road route feeds an ongoing circuit between different friendly bases. Arrival accepts surviving vehicles within 250 metres; a ten-minute travel deadline advances a stuck trip. Convoys pause 45–90 seconds before selecting their next destination. The original carried supplies between bases but did not unload or regenerate them; no artificial unloading is added here. + +Combat starts from fresh identified native group perception within 400 metres of a surviving convoy vehicle or a delivered HQ sighting. Mounted group origins are not used for this distance, because native groups can retain their original spawn position. Infantry dismounts, approaches the left and right flanks, then searches those sectors. Armed escorts provide cover while the ammo truck withdraws; the troop truck waits until the passengers have dismounted. Orders refresh at a bounded thirty-second interval. Still-mounted infantry receives at most six dismount retries, ten seconds apart, to recover from busy doors or a braking truck. Native boarding waypoints require all surviving members and use a 100-metre approach radius; actual compartment membership determines readiness. Crew retention suppresses both group and individual abandonment priorities only for the original mounted vehicle crew and releases on critical damage or drivetrain failure, allowing native emergency abandonment. + +After sixty seconds without a fresh contact, the teams reboard under escort cover. A new contact interrupts boarding. After a 120-second boarding deadline, stranded survivors are released and the remaining vehicles continue. A lost troop truck releases the infantry. Player capture stops convoy control permanently, preserving the actors and loot. + +## Validation + +`tests/test_supply_convoys.py` executes production startup, base selection, arrival, circuit timing, contact freshness and perception boundaries, scoped crew-abandonment priorities, combat quiet time, boarding interruption, timeout and truck-loss policies. The receipt tests cover all eight groups and configured fleets through twenty convoys, including no replacement after losses. Existing dispatch, native seat allocation, cargo, HQ radio and force-ledger regressions remain in the main check suite. + +`tools/headless_workbench.py --project chat --smoke supply-convoys --rounds 1 --timeout 900` exercises production automatic startup and physical AI in an isolated Workbench profile. Its final controlled contact explicitly tests native dismount/reboarding rather than claiming that an injected report proves perception. Remote-client replication and twenty-convoy performance require dedicated-server testing. Earlier one-convoy evidence in `convoy-migration.md` and `convoy-startup.md` remains historical evidence for those earlier sources. + +The legacy `convoy` and `hq-memory` Workbench smoke fixtures explicitly select their previous single-convoy controller under `WORKBENCH` and `errSmoke=1`, preserving those fixtures' existing assertions. Normal play, ordinary Workbench use, and the `supply-convoys` fixture use the full configured fleet. + +### Local native result — 2026-09-21 + +`/tmp/erri-supply-native10/logs/logs_2026-09-21_16-50-45` completed one `supply-convoys` smoke round with 36 common smoke assertions, no script/runtime failures, unchanged launch sources, and confirmed runner cleanup. The supply fixture additionally verified three automatically started convoys (18 vehicles, 75 original soldiers), exact ledger admission, 174 successful cargo insertions matched to physical inventory, all 18 vehicles driving at least 20 metres, both seven-person teams dismounting and reboarding, and the original troop truck driving the next base leg after the normal pause. The contact and expiry of the preceding trip deadline were explicitly injected test inputs; startup, native AI, seating, cargo, the pause and subsequent driving remained production-owned. RHS content was disabled in this isolated fixture, while its installed dependencies remained loaded. + +Launch source fingerprint: `380aec8a078825b165593fc4445b603f80b5d1ec51360c018d34973d65302b62`. Raw logs remain outside the repository. Strict engine qualification still fails on nine pre-existing dependency errors: four RHS/WCS localization GUID errors and five inherited vehicle-catalog keyword errors (`SlidingTrackMaterial`/`Parent`). This is a successful convoy smoke scenario, not a clean-engine or multiplayer qualification. + +`python3 tools/check.py` passed for this production source; the additional bounded-retry regression also passed afterward. Earlier native iterations exposed partial dismounts, premature healthy-crew abandonment and a crowded boarding approach; the final source contains the bounded exit retries, scoped group/individual priority guards and widened native boarding approach validated above. diff --git a/docs/vanilla-resources.json b/docs/vanilla-resources.json index cc162e6..6351e3f 100644 --- a/docs/vanilla-resources.json +++ b/docs/vanilla-resources.json @@ -1,126 +1,149 @@ { - "Prefabs/Structures/Walls/Concrete/ConcreteWall_01/ConcreteWall_01_3m.et": "60E5729BEA18F875", - "Prefabs/Structures/BuildingParts/Doors/Door_Metal_A_RIGHT_EXT_COV_B.et": "67F17696FF278AE0", - "Prefabs/Items/Equipment/Radios/Radio_R107M.et": "54C68E438DD34265", - "Prefabs/MP/Modes/GameMode_Base.et": "0F307326459A1395", - "worlds/Eden/Eden.ent": "853E92315D1D9EFE", - "Prefabs/AI/SCR_AIWorld.et": "E0A05C76552E7F58", - "Prefabs/World/Game/PerceptionManager.et": "028DAEAD63E056BE", - "Prefabs/MP/Managers/Factions/FactionManager_USxUSSR.et": "589540B35EBA8CDC", - "Prefabs/MP/Managers/Loadouts/LoadoutManager_USxUSSR.et": "97EF4C1A41F63DDB", - "Configs/Systems/MissionSystems.conf": "C50579A2EC48E8EF", - "Prefabs/Characters/Factions/BLUFOR/US_Army/Character_US_Unarmed.et": "2F912ED6E399FF47", - "Prefabs/Groups/OPFOR/Group_USSR_RifleSquad.et": "E552DABF3636C2AD", - "Prefabs/Vehicles/Helicopters/Mi8MT/Mi8MT_unarmed_transport.et": "DF5CCB7C0FF049F4", - "Prefabs/AI/Waypoints/AIWaypoint_SearchAndDestroy.et": "B3E7B8DC2BAB8ACC", - "Prefabs/AI/Waypoints/AIWaypoint_Defend.et": "93291E72AC23930F", - "Prefabs/Items/Misc/IntelligenceFolder_E_01/IntelligenceFolder_E_01.et": "6D56FED1E55A8F84", - "Configs/Map/MapPlain.conf": "A786DD4868598F15", - "Prefabs/Items/Core/Item_Base.et": "C95E11C60810F432", + "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/Items/Equipment/Maps/Map_Paper_01/Map_Paper_01_folded.xob": "E443663E5241622A", - "Sounds/Items/_SharedData/PickUp/Items_PickUp_Map.acp": "13F8D0DE67678118", - "Prefabs/Weapons/Handguns/PM/Handgun_PM.et": "C0F7DD85A86B2900", - "Prefabs/Weapons/Magazines/Magazine_9x18_PM_8rnd_Ball.et": "8B853CDD11BA916E", - "Prefabs/Items/Equipment/Maps/Map_Paper_01/PaperMap_01_folded.et": "13772C903CB5E4F7", - "system/textures/defWhite.edds": "A64A8C63E0FBAE87", - "Configs/Navmesh/Navmesh_GM_Eden_Soldier.conf": "8BBC73472092902E", - "Configs/Navmesh/Navmesh_GM_Eden_Vehicle.conf": "0228A79846FD8A97", - "worlds/MP/Navmeshes/LowResEden.nmn": "5E19E60F26327356", - "Assets/Items/Equipment/Radios/Radio_R107M/Radio_R107M_01_item.xob": "77C9FCF3FB1246E9", - "Prefabs/Systems/Radio/RadioManager.et": "B8E09FAB91C4ECCD", - "Prefabs/MP/ScriptedChatEntity.et": "F69BC912AC8236F9", - "Prefabs/Structures/BuildingParts/Doors/Door_MetalGate_01_Short_LEFT_EXT_ST_B.et": "34B08027DBDE322A", - "Prefabs/Props/Furniture/Table_01.et": "53506DCB398C7EBE", - "Assets/Structures/Walls/Concrete/ConcreteWall_01_3m.xob": "0B96D139FEBCA006", - "Configs/GameOverScreen/BaseGameOverScreensConfig.conf": "651583FFFB7FC765", - "UI/layouts/HUD/GameOver/EndScreen/EndScreenContent_NoImage.layout": "C4507D07F3C54831", - "Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_SL.et": "5436629450D8387A", - "Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_RTO.et": "612F43A4D5AE765F", - "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_SR.et": "333DA6244C7DA34C", - "Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_LAT.et": "BF643BE4ADBDFDD3", - "Prefabs/Weapons/Mortars/2B14/Mortar_2B14.et": "D1FFE458E8AC4BDB", - "Prefabs/Weapons/Ammo/Ammo_Shell_82mm_HE_O832DU.et": "98EC9C526AFBA282", - "Prefabs/Characters/Campaign/Final/OPFOR/USSR_Army/Regular/Campaign_USSR_Player_MortarCrew.et": "86E565387A634103", - "Prefabs/Items/Equipment/Radios/Radio_R148.et": "E1A5D4B878AA8980", - "Prefabs/Groups/OPFOR/Group_USSR_Base.et": "8DE0C0830FE0C33D", - "Prefabs/Tasks/BaseTask.et": "1D0F815858EE24AD", - "Prefabs/Props/EmptyStorages/USSR_AmmoBox_empty.et": "EBBC859CCD94D96D", - "Prefabs/Weapons/Rifles/AK74/Rifle_AK74.et": "FA5C25BF66A53DCF", - "Prefabs/Weapons/Magazines/Magazine_545x39_AK_30rnd_Ball.et": "BBB50A815A2F916B", - "Prefabs/Items/Medicine/FieldDressing_01/FieldDressing_USSR_01.et": "C3F1FA1E2EC2B345", - "Assets/Props/Military/AmmoBox/EquipmentBoxWooden_01/EquipmentBoxWooden_Weapon_01.xob": "819ED3266EE5113B", + "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", - "Prefabs/Items/Equipment/Binoculars/Binoculars_B8/Binoculars_B8.et": "243948B23D90BECB", - "Prefabs/Items/Medicine/MorphineInjection_01/MorphineInjection_01.et": "0D9A5DCF89AE7AA9", - "Prefabs/Items/Medicine/SalineBag_01/SalineBag_USSR_01.et": "527D7C5D2E476BDC", - "Prefabs/Vehicles/Wheeled/UAZ469/UAZ469.et": "259EE7B78C51B624", - "UI/layouts/Task/TaskListEntry.layout": "B71975032150BAFB", - "UI/layouts/Task/TaskListEntryDescription.layout": "552EB1921B5C548C", - "Prefabs/Characters/Factions/BLUFOR/US_Army/Character_US_Base.et": "836E7E39AAC5888B", - "Prefabs/Items/Equipment/Watches/Watch_SandY184A.et": "78ED4FEF62BBA728", - "Prefabs/Characters/HeadGear/Hat_Patrol_US_01/Hat_Patrol_US_01.et": "F545C1BE7C99954A", - "Prefabs/Characters/Uniforms/Jacket_US_BDU_rolledup.et": "3CCA7A9BB4FD3197", - "Prefabs/Characters/Uniforms/Pants_US_BDU.et": "604BB72BE8E023C2", - "Prefabs/Characters/Footwear/CombatBoots_US_01.et": "DAAFD15478BDE1C3", - "Prefabs/Items/Medicine/FieldDressing_01/FieldDressing_US_01.et": "A81F501D3EF6F38E", - "Prefabs/Items/Medicine/Tourniquet_01/Tourniquet_US_01.et": "D70216B1B2889129", - "Configs/Factions/BLUFOR.conf": "E7B7EA4823DD81F0", - "UI/Textures/Editor/EditableEntities/Factions/EditableEntity_Faction_USA.edds": "EB7F65DBC9392557", - "Configs/Identities/FactionIdentity_US.conf": "B600946E9ACC17C2", - "UI/Textures/Flags/US-flag-base-3it.edds": "46FB2FB2C2125A3C", - "Assets/Props/Fabric/Flags/Data/Flag_1_2_USA.emat": "610803CC3F3D6649", + "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/WeaponTripod_EntityCatalog_US.conf": "0E4B62F186F97C43", "Configs/EntityCatalog/US/InventoryItems_EntityCatalog_US.conf": "5F7EC52FC40A03E2", "Configs/EntityCatalog/US/SupplyContainerItems_EntityCatalog_US.conf": "0BF36EFF9FFAF92B", - "Configs/Identities/Territories/FactionHomeTerritory_US.conf": "B548A5B264939A98", - "Configs/Factions/OPFOR.conf": "B122E3B10BB3404B", - "UI/Textures/Editor/EditableEntities/Factions/EditableEntity_Faction_USSR.edds": "40B12B0DF911B856", - "Configs/Identities/FactionIdentity_USSR.conf": "FBBCD73926989580", - "UI/Textures/Flags/USSR-flag-base-3it.edds": "50824EB9F2C215AB", - "Assets/Props/Fabric/Flags/Data/Flag_1_2_SovietArmy.emat": "B47B52D9DA68905D", - "Configs/Callsigns/Callsigns_USSR.conf": "958043CE1648EC43", + "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/WeaponTripod_EntityCatalog_USSR.conf": "DDF17C8C140BD1F2", "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", - "Prefabs/MP/Managers/Factions/FactionManager_Base.et": "A242612865F2A48E", - "UI/Textures/DeployMenu/Loadout-BG/Loadout_US_BG.imageset": "F8AC305446D5D480", - "UI/Textures/DeployMenu/Loadout-BG/Loadout_BG_USSR.imageset": "21533F2089005056", - "Prefabs/Items/Medicine/SalineBag_01/SalineBag_US_01.et": "00E36F41CA310E2A", - "Prefabs/Items/Equipment/Radios/Radio_ANPRC77.et": "9B6B61BB3FE3DFB0", - "Prefabs/AI/Waypoints/AIWaypoint_Move.et": "750A8D1695BD6998", + "Configs/Map/MapPlain.conf": "A786DD4868598F15", + "Configs/Navmesh/Navmesh_GM_Eden_Soldier.conf": "8BBC73472092902E", + "Configs/Navmesh/Navmesh_GM_Eden_Vehicle.conf": "0228A79846FD8A97", + "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/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/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/AI/Groups/Group_Base.et": "000CD338713F2B5A", - "Prefabs/Decals/Dirt/Decal_Dirt_Patch_03.et": "4AD6EB80A8B1FA3A", - "UI/layouts/WidgetLibrary/Buttons/WLib_ButtonText.layout": "75C912A1C89BE6C2", - "UI/layouts/WidgetLibrary/EditBox/WLib_EditBox.layout": "0022F0B45ADBC5AC", - "UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt": "3E7733BAC8C831F6", - "Prefabs/Characters/HeadGear/Helmet_PASGT_01/Helmet_PASGT_01_base.et": "8A2B2A544F3ED831", - "Configs/System/chimeraMenus.conf": "C747AFB6B750CE9A", + "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/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/Vehicles/Wheeled/UAZ469/UAZ469_PKM.et": "0B4DEA8078B78A9B", - "Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_Rifleman.et": "DCB41B3746FDD1BE", - "Prefabs/Weapons/Attachments/Optics/Optic_PSO1/Optic_PSO1.et": "C850A33226B8F9C1", - "Prefabs/Weapons/Attachments/Optics/Optic_ARTII/Optic_ARTII.et": "D2018EDB1BBF4C88", + "Prefabs/Weapons/Ammo/Ammo_Shell_82mm_HE_O832DU.et": "98EC9C526AFBA282", "Prefabs/Weapons/Attachments/Optics/Optic_4x20/Optic_4x20.et": "BD496EE1B40DC510", - "Prefabs/Vehicles/Wheeled/UAZ469/VehParts/Seats/UAZ469_seats_rear.et": "780AAF0A51AEE61A", - "Prefabs/Items/Equipment/Kits/RepairKit_01/RepairKit_01_wrench.et": "33B2DFDCD0EBA3DB", - "Prefabs/Items/Fuel/Jerrycan_01/Jerrycan_01_item.et": "12D5AD21E383B768", - "Prefabs/Structures/BuildingParts/Doors/DoorSet_Base.et": "87CADB5ADC989993", - "Assets/Structures/BuildingsParts/Doors/DoorFrame_door_metal_A_RIGHT_EXT_B.xob": "E3BC73BFBC7AA497" + "Prefabs/Weapons/Attachments/Optics/Optic_ARTII/Optic_ARTII.et": "D2018EDB1BBF4C88", + "Prefabs/Weapons/Attachments/Optics/Optic_PSO1/Optic_PSO1.et": "C850A33226B8F9C1", + "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", + "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" } diff --git a/docs/vehicle-maintenance.md b/docs/vehicle-maintenance.md index 4c92e99..afe5ca8 100644 --- a/docs/vehicle-maintenance.md +++ b/docs/vehicle-maintenance.md @@ -1,6 +1,12 @@ -# Finite player vehicle maintenance +# Finite player vehicle maintenance (historical fixture) -The Western supply cache now contains one emergency repair kit and two vanilla fuel cans, alongside the existing finite UAZ. Its discovered map label identifies the maintenance supplies. Take the item into your inventory, equip it, then use the vanilla action at a damaged vehicle part or fuel cap. Park the vehicle before using either action. +The western guarded vehicle/cache site was removed from the live Everon scenario +on 22 September 2026. Its UAZ, repair kit and fuel cans are no longer spawned. +The prefab and historical test fixture remain for regression coverage; the +following stock and native evidence describe that fixture, not current live stock. +See [current airfield and site changes](airfield-extraction-and-map-icons.md). + +The historical Western supply cache contains one emergency repair kit and two vanilla fuel cans, alongside the existing finite UAZ. Its discovered map label identifies the maintenance supplies. Take the item into your inventory, equip it, then use the vanilla action at a damaged vehicle part or fuel cap. Park the vehicle before using either action. The kit includes 20 native supply units and inherits the vanilla wrench's emergency repair ceiling and damage eligibility. It does not fully restore every damaged part, resurrect destroyed vehicles or create replacements. The held wrench uses the normal native resource consumer; eligible nearby finite supplies may also be consumed according to vanilla resource rights. The item has no resource generator or replenishment callback. Each can starts with 5 litres, with a 20-litre capacity; the pair supplies 10 litres initially. The native fuel station transfers fuel out of the held can into an eligible tank and stops when the can is empty or the target is full. Cans may be refilled only through ordinary existing native sources. diff --git a/tests/mortar_salvo_regression.py b/tests/mortar_salvo_regression.py index e2839f0..6ef7378 100644 --- a/tests/mortar_salvo_regression.py +++ b/tests/mortar_salvo_regression.py @@ -1,20 +1,22 @@ from pathlib import Path from policy_harness import body,run ROOT=Path(__file__).resolve().parents[1] +import re +production=(ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSalvo.c').read_text() +constants='\n'.join(re.findall(r'static const (?:int|float) [^;]+;',production)).replace('static const','constexpr') s=body(ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_MortarSalvo.c','static vector Offset(').replace('Math.','Math::') run('''#include #include struct vector { float x,y,z;}; vector Vector(float x,float y,float z){return {x,y,z};} namespace Math {constexpr float DEG2RAD=0.01745329252;float Sqrt(float n){return std::sqrt(n);}float Sin(float n){return std::sin(n);}float Cos(float n){return std::cos(n);}} -constexpr int ROUNDS=8;constexpr float RADIUS_METRES=40; -'''+s+''' -int main(){for(int site=0;site<4;site++)for(int order=0;order<10;order++){ +'''+constants+s+''' +int main(){assert(ROUNDS>=8&&RADIUS_METRES>=80);for(int site=0;site<4;site++)for(int order=0;order<10;order++){ float previous=0; for(int shot=0;shot<8;shot++){ auto a=Offset(site,order,shot),b=Offset(site,order,shot); assert(a.x==b.x&&a.z==b.z&&a.y==0); - float radius=std::hypot(a.x,a.z);assert(radius>previous&&radius<=40.0001);previous=radius; + float radius=std::hypot(a.x,a.z);assert(radius>previous&&radius<=80.0001);previous=radius; } }} ''') diff --git a/tests/test_admin_menu.py b/tests/test_admin_menu.py index 3a637bd..7d82093 100644 --- a/tests/test_admin_menu.py +++ b/tests/test_admin_menu.py @@ -10,7 +10,7 @@ source = ROOT / 'addons/core/Scripts/Game/ERR/00_Core/ERR_AdminMenu.c' layout = ROOT / 'addons/core/UI/layouts/ERR/AdminMenu.layout' keys = re.findall(r'"([A-Za-z]+)"', body(source, 'static array Keys(')) settings = re.findall(r'"([A-Za-z]+)"', body(BASE / 'addons/core/Scripts/Game/ERR/00_Core/ERR_Settings.c', 'static array Keys(')) -assert len(keys) == 10 and set(settings) - set(keys) == {"stingerChanceOneIn", "automaticConvoyEnabled"} +assert len(keys) == 11 and set(settings) - set(keys) == {"stingerChanceOneIn", "automaticConvoyEnabled", "heliTimerMinutes"} assert set(keys) <= set(settings) # New text-command setting does not alter the fixed native menu. # Native layouts place child widget declarations inside an anonymous Children # block. A missing brace can preserve most widget names yet prevent menu load. @@ -44,9 +44,10 @@ except AssertionError: else: raise AssertionError('Malformed child structure must be rejected') names = re.findall(r'\bName "([^"]+)"', layout.read_text()) +assert 'RandomDay_startTimeMinutes' in names assert len(names) == len(set(names)), 'Menu widget names must be unique' for key in keys: - assert all(name in names for name in (key, 'Apply_' + key, 'Saved_' + key)) + assert all(name in names for name in (key, 'Apply_' + key, 'Saved_' + key, 'Random_' + key)) for name in ('Close', 'SettingsPage', 'HQPage', 'JournalPage', 'JournalText', 'JournalContent', 'JournalScroll', 'PauseJournal', 'LatestJournal', 'Status'): assert name in names for name in re.findall(r'"([A-Za-z]+)"', body(source, 'override void OnMenuOpen(').split('foreach')[0]): @@ -90,9 +91,10 @@ int main() { {"intelRevealChancePercent","intel reveal"},{"startTimeMinutes","mission time"}, {"timeMultiplier","mission speed"},{"startDateCode","mission date"}, {"weatherProfile","mission weather"},{"reportIntervalSeconds","hq interval"}, - {"supportSquadLimit","hq squads"},{"responseRadiusMetres","hq radius"}}; + {"supportSquadLimit","hq squads"},{"responseRadiusMetres","hq radius"},{"convoyCount","hq convoy count"}}; for(auto pair:cases){ assert(Fields::Command(pair.first," 42 ")==pair.second+" set 42"); + assert(Fields::Command(pair.first,"Random")==pair.second+" set Random"); assert(Fields::Command(pair.first,"").empty()); assert(Fields::Command(pair.first," \t ").empty()); assert(Fields::Command(pair.first,string(33,'x')).empty()); @@ -101,10 +103,10 @@ int main() { assert(Fields::Command("startTimeMinutes","14:25")=="mission time set 14:25"); assert(Fields::Command("startDateCode","2026-09-19")=="mission date set 2026-09-19"); assert(Fields::Command("weatherProfile","authored")=="mission weather set authored"); - for(string key:{"heliTimer","convoyCount","prisonDistance","stingerChance","mission abandon","","bad"}){ + for(string key:{"heliTimer","prisonDistance","stingerChance","mission abandon","","bad"}){ assert(Fields::Command(key,"1").empty());assert(!Fields::Available(key,true,true)); } - for(string key:{"reportIntervalSeconds","supportSquadLimit","responseRadiusMetres"}){ + for(string key:{"reportIntervalSeconds","supportSquadLimit","responseRadiusMetres","convoyCount"}){ assert(!Fields::Available(key,false,true));assert(Fields::Available(key,true,false)); } assert(!Fields::Available("aiIntelChancePercent",true,false)); @@ -112,4 +114,4 @@ int main() { for(string key:{"intelRevealChancePercent","radioDefenceSeconds","startTimeMinutes","timeMultiplier","startDateCode","weatherProfile"}) assert(Fields::Available(key,false,false)); } ''') -print('PASS: actual menu command routing covers all ten settings, rejects unsupported keys, gates companions, and matches unique authored widgets') +print('PASS: actual menu command routing covers all eleven settings, rejects unsupported keys, gates companions, and matches unique authored widgets') diff --git a/tests/test_admin_player_tools.py b/tests/test_admin_player_tools.py index 39326b2..0b2c194 100644 --- a/tests/test_admin_player_tools.py +++ b/tests/test_admin_player_tools.py @@ -15,7 +15,7 @@ def adapt(s): s=s.replace('FindComponent(DamageManagerComponent)', 'FindDamage()').replace('FindComponent(SCR_InventoryStorageManagerComponent)', 'FindInventory()') s=s.replace('DamageManagerComponent.Cast(', 'Damage::Cast(').replace('SCR_InventoryStorageManagerComponent.Cast(', 'Inventory::Cast(') s=s.replace('purpose: EStoragePurpose.PURPOSE_DEPOSIT, cb: m_Grants->Operation', '1, m_Grants->Operation') - s=s.replace('String item;', 'String item;') + s=s.replace('String item;', 'String item;').replace('string.Format(', 'String::Format(').replace('ERR_DebugAI.', 'DebugAI::').replace('ERR_DebugIntel.', 'DebugIntel::') return s binding=adapt(body(source,'void Bind(')) constructor=adapt(body(source,'void ERR_AdminPlayerTools(')).replace('void ERR_AdminPlayerTools(ERR_AdminGrantState grants = nullptr)', 'Tools(GrantState* grants = nullptr)') @@ -30,6 +30,7 @@ run(r''' #include struct String:std::string { using std::string::string;String()=default;String(const std::string& s):std::string(s){} + static String Format(String text,int n){text.replace(text.find("%1"),2,std::to_string(n));return text;} String Trim(){auto a=find_first_not_of(" \t\n");return a==npos?String():String(substr(a,find_last_not_of(" \t\n")-a+1));} void ToLower(){std::transform(begin(),end(),begin(),[](unsigned char c){return std::tolower(c);});} bool StartsWith(const char* p){return rfind(p,0)==0;}bool IsEmpty(){return empty();} @@ -51,6 +52,8 @@ struct Game{float now=0;Manager manager;Manager* GetPlayerManager(){return &mana namespace Replication{bool server=true;bool IsServer(){return server;}} namespace Global{bool admin=true;bool IsAdmin(int){return admin;}} namespace Actors{bool Alive(Entity* a){return a&&a->alive;}} +namespace DebugAI {int calls=0;int KillNearby(Mode* m,Entity* e){assert(m&&e);calls++;return 3;}} +namespace DebugIntel {int calls=0;bool success=true;bool SpawnSix(Mode* m,Entity* e){assert(m&&e);calls++;return success;}} struct GrantState{IEntity Actor=nullptr;ERR_AdminItemCallback* Operation=nullptr;String Item;float Deadline=0;bool TimedOut=false; '''+binding+r''' }; @@ -65,6 +68,11 @@ struct Fixture{ bool command(String args){replies.clear();return tools.Execute(&mode,&controller,args,replies);}void tick(){replies.clear();tools.Tick(replies);} }; int main(){ + {Fixture f;int before=DebugIntel::calls;f.command("cheat intel");assert(DebugIntel::calls==before+1&&f.replies[0].find("Spawned 6")!=String::npos&&f.actor.inventory.submissions==0);Global::admin=false;f.command("cheat intel");assert(DebugIntel::calls==before+1);} + {Fixture f;DebugIntel::success=false;f.command("cheat intel");assert(f.replies[0].find("Could not place")!=String::npos);DebugIntel::success=true;} + + {Fixture f;int before=DebugAI::calls;f.command("killais");assert(DebugAI::calls==before+1&&f.replies[0].find("Killed 3")!=String::npos);Global::admin=false;f.command("killais");assert(DebugAI::calls==before+1);} + {Fixture f;assert(!f.command("mission time show")&&f.replies.empty());assert(f.command(" GOD SET ON ")&&!f.actor.damage.enabled);assert(f.tools.m_God);f.command("god");assert(f.actor.damage.changes==1);f.command("god show");assert(f.replies[0].find("on")!=String::npos);f.command("ungod");assert(f.actor.damage.enabled&&f.actor.damage.changes==2);f.tools.Stop();assert(f.actor.damage.changes==2);} {Fixture f;f.actor.damage.enabled=false;f.command("god");f.command("god set off");assert(!f.actor.damage.enabled);} {Fixture f;f.command("god");Global::admin=false;f.tick();assert(f.actor.damage.enabled&&f.tools.m_Stopped&&f.replies.empty());Global::admin=true;f.command("god");assert(f.actor.damage.enabled);} diff --git a/tests/test_admin_providers.py b/tests/test_admin_providers.py index 60bef87..5598653 100644 --- a/tests/test_admin_providers.py +++ b/tests/test_admin_providers.py @@ -65,7 +65,7 @@ int main(){ assert(ha.Setting("intel","carrying").empty()&&ha.Setting("hq","stinger")=="stingerChanceOneIn"); assert(ia.Setting("intel","chance")=="aiIntelChancePercent"&&ia.Setting("intel","carrying")=="aiIntelChancePercent"); assert(ia.Setting("hq","chance").empty()&&ia.Setting("intel","spawn").empty()); - HQHelp hh;IntelHelp ih;lines.clear();assert(hh.Help("hq",lines)&&lines.size()<=4);lines.clear();assert(ih.Help("intel",lines)&&lines.size()<=4); + HQHelp hh;IntelHelp ih;lines.clear();assert(hh.Help("hq",lines)&&lines.size()<=5);lines.clear();assert(ih.Help("intel",lines)&&lines.size()<=4); lines.clear();assert(!hh.Help("unknown",lines)&&!ih.Help("unknown",lines)&&lines.empty()); } ''') diff --git a/tests/test_air_logistics_orders.py b/tests/test_air_logistics_orders.py new file mode 100644 index 0000000..e7c5cb9 --- /dev/null +++ b/tests/test_air_logistics_orders.py @@ -0,0 +1,55 @@ +"""Execute production air-resupply reservation and native-operation quarantine rules.""" +from policy_harness import ROOT, body, run + +reserve = body(ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_AirfieldSupport.c', 'bool ReserveAirAmmo(') +reserve = reserve.replace('ERR_HQUnit unit', 'ERR_HQUnit* unit').replace('unit.', 'unit->').replace('Replication.', 'Replication::') +pending = body(ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_AirAmmoMission.c', 'bool PendingNative(') +pending = pending.replace('foreach (', 'for (').replace('ERR_ConvoyCargoCallback loading', 'ERR_ConvoyCargoCallback* loading').replace('ERR_InfantryAmmoTransfer operation', 'ERR_InfantryAmmoTransfer* operation').replace('loading.', 'loading->').replace('operation.', 'operation->') +run(r''' +#include +#include +struct Replication {inline static bool server=true;static bool IsServer(){return server;}}; +struct ERR_HQUnit { + bool eligible=true,HomeGuard=false,Radio=true,PendingOrder=false,Downlink=false,fighting=false; + int LogisticsReservation=0,Assignment=42; + bool Eligible(int){return eligible&&LogisticsReservation==0;} +}; +struct HQ { + int m_Mode=0;bool active=true; + bool MissionActive(){return active;} + bool Fighting(ERR_HQUnit* unit){return unit->fighting;} +'''+reserve+r''' +}; +struct ERR_ConvoyCargoCallback {bool Finished=false;}; +struct ERR_InfantryAmmoTransfer {bool unresolved=false;bool Unresolved(){return unresolved;}}; +struct Mission { + std::vector m_Loads; + std::vector m_Operations; +'''+pending+r''' +}; +int main(){ + HQ hq;ERR_HQUnit unit; + // A quiet unit may be reserved while retaining its existing delivered search. + assert(hq.ReserveAirAmmo(&unit,200001));assert(unit.LogisticsReservation==200001&&unit.Assignment==42); + assert(!hq.ReserveAirAmmo(&unit,200002)); + for(int invalid=0;invalid<9;invalid++){ + unit={};hq.active=true;Replication::server=true; + if(invalid==0)Replication::server=false; + if(invalid==1)hq.active=false; + if(invalid==2)unit.eligible=false; + if(invalid==3)unit.HomeGuard=true; + if(invalid==4)unit.Radio=false; + if(invalid==5)unit.PendingOrder=true; + if(invalid==6)unit.Downlink=true; + if(invalid==7)unit.fighting=true; + int token=invalid==8?0:200001; + assert(!hq.ReserveAirAmmo(&unit,token)&&unit.Assignment==42&&unit.LogisticsReservation==0); + } + assert(!hq.ReserveAirAmmo(nullptr,200001)); + Mission mission;ERR_ConvoyCargoCallback loading;ERR_InfantryAmmoTransfer move; + mission.m_Loads={&loading};mission.m_Operations={&move}; + assert(mission.PendingNative());loading.Finished=true;assert(!mission.PendingNative()); + move.unresolved=true;assert(mission.PendingNative());move.unresolved=false;assert(!mission.PendingNative()); +} +''') +print('PASS: air logistics reservation preserves delivered search until radio handoff, excludes guards/combat/in-flight orders, and quarantines unresolved native loads/moves') diff --git a/tests/test_air_recon.py b/tests/test_air_recon.py new file mode 100644 index 0000000..772e796 --- /dev/null +++ b/tests/test_air_recon.py @@ -0,0 +1,64 @@ +"""Production recon timing, orbit and standoff geometry; no native flight claim.""" +import re +from policy_harness import ROOT,body,run +path=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_AirReconSystem.c' +schedule=path.read_text().split('class ERR_AirReconSystem')[0] +schedule=schedule[schedule.index('class ERR_ReconSchedule'):].replace('class ERR_ReconSchedule','struct ERR_ReconSchedule').replace('\n}\n','\n};\n') +flight=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_ReconFlightComponent.c' +rules=body(flight,'static vector Cruise(')+'\n'+body(flight,'static vector StandOff(') +rules=rules.replace('Math.','Math::').replace('vector.','vector::') +run(r''' +#include +#include +#include +#include +struct Math{static float Min(float a,float b){return std::min(a,b);}static float Max(float a,float b){return std::max(a,b);}static float Clamp(float a,float lo,float hi){return std::clamp(a,lo,hi);}}; +struct vector{float x=0,y=0,z=0;vector()=default;vector(float a,float b,float c):x(a),y(b),z(c){}vector(const char*s){sscanf(s,"%f %f %f",&x,&y,&z);}float&operator[](int i){return i==0?x:i==1?y:z;}vector operator+(vector b)const{return{x+b.x,y+b.y,z+b.z};}vector operator-(vector b)const{return{x-b.x,y-b.y,z-b.z};}vector operator*(float f)const{return{x*f,y*f,z*f};}vector&operator-=(vector b){x-=b.x;y-=b.y;z-=b.z;return*this;}float Length()const{return std::sqrt(x*x+y*y+z*z);}vector Normalized()const{float f=Length();if(f==0)return{};return{x/f,y/f,z/f};}void Normalize(){*this=Normalized();}static float Dot(vector a,vector b){return a.x*b.x+a.y*b.y+a.z*b.z;}}; +vector Vector(float x,float y,float z){return{x,y,z};} +'''+schedule+rules+r''' +int main(){ + ERR_ReconSchedule s{};assert(!s.Due(1000000,false));s.Begin(1000);assert(s.Deadline==901000); + s.Begin(2000);assert(s.Deadline==901000);assert(!s.Due(900999,false));assert(s.Due(901000,false));assert(!s.Due(901000,true)); + s.Launched();assert(s.Deadline<0&&!s.Due(2000000,false));s.Change(2,2000,true);assert(s.Deadline<0&&s.Minutes==2); + s.Lost(3000);assert(s.Deadline==123000&&!s.Due(122999,false));s.Change(15,4000,false);assert(s.Deadline==904000); + s.Stop();s.Begin(100);s.Lost(200);s.Change(1,300,false);assert(s.Deadline<0&&!s.Due(1e8,false)); + vector orbit=Cruise({300,120,0},{0,0,0},false);assert(std::abs(orbit.x)<.001&&std::abs(orbit.z+28)<.001); + vector far=Cruise({1000,120,0},{0,0,0},false);assert(far.x==-40&&far.y==0); + vector near=Cruise({100,120,0},{0,0,0},false);assert(near.x>0); // push back out toward 300m orbit + vector home=Cruise({20,120,0},{0,0,0},true);assert(home.x==-8); // return approaches pad instead of orbiting + vector away=StandOff({100,120,0},{0,0,0},{-40,0,0});assert(away.x>0); + vector clear=StandOff({300,120,0},{0,0,0},{-40,0,0});assert(clear.x==-40); + vector coincident=StandOff({0,120,0},{0,0,0},{0,0,0});assert(std::isfinite(coincident.x)&&coincident.x>0); +} +''') +print('PASS: original 15-minute launch/loss cadence, active/captured timer disarm, saved delay reset, stop, 300m orbit and close-contact standoff') + +# Explicit entity deletion must not leave an inactive launch deadline behind. +removed=body(path,'void Removed(') +for old,new in [('ERR_ReconFlightComponent flight','Flight* flight'),('Replication.','Replication::'),('ERR_HQ.','ERR_HQ::'),('m_Mode.','m_Mode->'),('null','nullptr'),('GetGame().GetWorld().GetWorldTime()','clockNow')]: + removed=removed.replace(old,new) +run(r''' +#include +#include +using string=std::string; +struct Flight{};struct Mode{bool active=true;bool Active(){return active;}}; +struct Replication{inline static bool server=true;static bool IsServer(){return server;}}; +struct ERR_HQ{inline static int events=0;static void Event(string,string){events++;}}; +float clockNow=5000; +'''+schedule+r''' +struct System{ + ERR_ReconSchedule m_Schedule;Flight* m_Current=nullptr;Mode* m_Mode=nullptr;int m_PadAttempts=3;string m_Reason; + string Status(){return m_Reason;} +'''+removed+r''' +}; +int main(){ + Mode mode;Flight owned,other;System s{};s.m_Mode=&mode;s.m_Current=&owned;s.m_Schedule.Begin(0);s.m_Schedule.Launched(); + s.Removed(nullptr);s.Removed(&other);assert(s.m_Current==&owned&&s.m_Schedule.Deadline<0&&ERR_HQ::events==0); + Replication::server=false;s.Removed(&owned);assert(s.m_Current==&owned);Replication::server=true; + mode.active=false;s.Removed(&owned);assert(s.m_Current==&owned);mode.active=true; + s.Removed(&owned);assert(!s.m_Current&&s.m_PadAttempts==0&&s.m_Schedule.Deadline==905000&&ERR_HQ::events==1); + clockNow=9000;s.Removed(&owned);assert(s.m_Schedule.Deadline==905000&&ERR_HQ::events==1); + s.m_Current=&other;s.m_Schedule.Stop();s.Removed(&other);assert(s.m_Current==&other&&s.m_Schedule.Deadline<0); +} +''') +print('PASS: actual aircraft-removal notification guards owner/server/active/stop and schedules one full delay without replay extension') diff --git a/tests/test_air_support_policy.py b/tests/test_air_support_policy.py new file mode 100644 index 0000000..c8acf5d --- /dev/null +++ b/tests/test_air_support_policy.py @@ -0,0 +1,57 @@ +"""Execute production HQ reinforcement policy against confidence and force scenarios.""" +from policy_harness import ROOT, run +import re +source=(ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_AirSupportPolicy.c').read_text().split('// One immutable')[0] +source=source.replace('class ', 'struct ').replace('\n}', '\n};').replace('ERR_AirSupportSituation s','ERR_AirSupportSituation* s').replace('s.', 's->').replace('ERR_HQMemoryRules.','ERR_HQMemoryRules::').replace('Math.','Math::') +source=source.replace('ERR_HQMemoryRules->', 'ERR_HQMemoryRules::') +source=re.sub(r'\b(bool|int|float) (\w+);',r'\1 \2{};',source) +run(r''' +#include +#include +#include +#include +#include +struct string:std::string{using std::string::string;bool IsEmpty(){return empty();}}; +struct Math {static int Clamp(int x,int a,int b){return std::clamp(x,a,b);}static float Max(float a,float b){return std::max(a,b);}}; +struct ERR_HQMemoryRules{static bool Finite(float v){return std::isfinite(v);}}; +'''+source+r''' +int main(){ + ERR_AirSupportSituation s{};s.AircraftReady=true;s.BeliefId=1;s.Samples=3;s.Spotted=3;s.Age=5;s.Confidence=.9;s.Radius=20;s.MotionKnown=true;s.Infantry=true;s.Speed=1; + ERR_AirSupportPolicy p;assert(!p.Consider(&s,0));assert(!p.Consider(&s,44999));assert(p.Consider(&s,45000)); + p.Committed(45000);assert(!p.Consider(&s,50000));assert(!p.Consider(&s,525000));assert(p.Consider(&s,570000)); + s.CommittedFit=6;assert(!p.Consider(&s,600000));s.CommittedFit=0;s.GroundFit=6;assert(!p.Consider(&s,600000)); + s.ConfirmedLosses=2;assert(!p.Consider(&s,600000));assert(p.Consider(&s,620000)); + s.ArtilleryBusy=true;assert(!p.Consider(&s,630000));s.ArtilleryBusy=false;assert(!p.Consider(&s,640000));assert(p.Consider(&s,660000)); + s.BeliefId=2;assert(!p.Consider(&s,670000));assert(!p.Consider(&s,689999));assert(p.Consider(&s,690000)); + auto good=s; + s.Age=91;assert(!p.Consider(&s,700000));s=good;s.Confidence=.69;assert(!p.Consider(&s,700000)); + s=good;s.Radius=161;assert(!p.Consider(&s,700000));s=good;s.Samples=1;assert(!p.Consider(&s,700000)); + s=good;s.Infantry=false;assert(!p.Consider(&s,700000));s=good;s.Speed=7;assert(!p.Consider(&s,700000)); + s=good;s.MotionKnown=false;assert(!p.Consider(&s,700000));s=good;s.AircraftReady=false;assert(!p.Consider(&s,700000)); + s=good;s.Age=std::numeric_limits::quiet_NaN();assert(!p.Consider(&s,700000)); + assert(!p.Consider(nullptr,700000));assert(!p.Consider(&good,std::numeric_limits::infinity())); +} +''') +print('PASS: production airborne memory confidence, persistence, ground coverage, confirmed losses, artillery veto, cooldown and invalid-input rules') + +from policy_harness import body +load=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_AirAssaultLoad.c' +cover=body(load,'bool Cover(').replace('out vector center','int& center').replace('m_Order.Target','m_Order->Target') +service=body(load,'bool NeedsService(') +run(r''' +#include +struct Order {int Target=730;}; +struct Load { + Order* m_Order=nullptr;bool m_Used=false,m_Approaching=false;float m_CoverUntil=300000; +'''+cover+service+r''' +}; +int main(){ + Load load;Order order;int center=-1; + assert(!load.Cover(0,center)&¢er==-1&&!load.NeedsService(0)); + load.m_Order=ℴload.m_Used=true;load.m_Approaching=true; + assert(!load.Cover(1,center)&&!load.NeedsService(300001)); + load.m_Approaching=false;assert(load.Cover(299999,center)&¢er==730&&!load.NeedsService(299999)); + center=-1;assert(!load.Cover(300000,center)&¢er==-1&&load.NeedsService(300000)); +} +''') +print('PASS: production cover retains the carried HQ target until its deadline; airport reload waits until the drop pass and cover have finished') diff --git a/tests/test_content_policy.py b/tests/test_content_policy.py new file mode 100644 index 0000000..0c16ee4 --- /dev/null +++ b/tests/test_content_policy.py @@ -0,0 +1,48 @@ +"""Exercise production content selection bodies with small engine boundary doubles. +Native preference I/O, group membership and UI have separate Workbench probes. +""" +from policy_harness import ROOT, body, run +import re +p=ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_ContentPolicy.c' +def cpp(sig): + s=body(p,sig).replace('ResourceName ', 'string ').replace('Faction faction','Faction* faction') + s=s.replace('ERR_ContentRegistry.Definition().Find(pack)','registry.Find(pack)') + s=s.replace('ERR_ContentRegistry.Definition().Options','registry.Options') + s=s.replace('ERR_ContentOption option', 'Option* option').replace('foreach (','for (') + s=s.replace('array groups', 'Array groups') + s=s.replace('option.', 'option->').replace('faction.', 'faction->') + return s +run(r''' +#include +#include +#include +#include +struct string:std::string {using std::string::string;string(std::string s):std::string(s){} bool IsEmpty(){return empty();}}; +templatestruct Array:std::vector{using std::vector::vector;void Insert(T v){this->push_back(v);}bool IsEmpty(){return this->empty();}int Count(){return this->size();}}; +struct Flags:std::map{using std::map::operator=;bool Contains(string k){return count(k);}bool Get(string k){return (*this)[k];}}; +struct Option{string Id,Parent,NativeFactionKey,GuardGroup;}; +struct Registry{std::vector Options;Option* Find(string id){for(auto*o:Options)if(o->Id==id)return o;return nullptr;}}; +struct Faction{string key;string GetFactionKey(){return key;}}; +struct Policy{int m_GuardOffset=0;Flags m_Active;Registry registry; +'''+'\n'.join(cpp(sig) for sig in ('bool Enabled(', 'ResourceName GuardGroup(', 'bool Enemy('))+r''' +}; +int main(){ + Option pack{"rhs","","",""}, a{"usmc","rhs","RHS_USAF","usmc-group"}, b{"afrf","rhs","RHS_AFRF","afrf-group"}; + Policy p;p.registry.Options={&pack,&a,&b};p.m_Active={{"rhs",true},{"usmc",true},{"afrf",true}}; + Faction usa{"RHS_USAF"},ru{"RHS_AFRF"},other{"US"}; + assert(p.Enabled("")&&!p.Enabled("unknown"));assert(p.Enemy(&usa)&&p.Enemy(&ru)&&!p.Enemy(&other)&&!p.Enemy(nullptr)); + assert(p.GuardGroup(0)=="usmc-group"&&p.GuardGroup(1)=="afrf-group"&&p.GuardGroup(2)=="usmc-group"); + p.m_GuardOffset=1;assert(p.GuardGroup(0)=="afrf-group"&&p.GuardGroup(1)=="usmc-group"); + p.m_Active["rhs"]=false;assert(!p.Enabled("rhs")&&!p.Enabled("usmc")&&!p.Enabled("afrf"));assert(p.GuardGroup(0).empty()&&!p.Enemy(&usa)); + p.m_Active["rhs"]=true;p.m_Active["usmc"]=false;assert(!p.Enabled("usmc")&&p.Enabled("afrf")); + assert(p.GuardGroup(0)=="afrf-group"&&p.GuardGroup(10)=="afrf-group"&&!p.Enemy(&usa)&&p.Enemy(&ru)); + p.m_Active["afrf"]=false;assert(p.GuardGroup(0).empty()); +} +''') +# Config-driven labels, IDs and exact source resources; no fixed RHS row in UI. +registry=(ROOT/'addons/core/Configs/ERR/Content/Registry.conf').read_text() +assert re.findall(r'\bId "([^"]+)"',registry)==['rhs','rhs_usmc','rhs_afrf','rhs_ion'] +assert len(re.findall(r'\bGuardGroup ',registry))==3 +assert 'ERR_ContentRegistry.Ids()' in (ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_ContentMenu.c').read_text() +assert 'PrisonBackpack.et' in (ROOT/'addons/core/Configs/ERR/EveronSites.conf').read_text() +print('PASS: actual content policy gates parent packs, individual factions, faction identity and finite group rotation with vanilla fallback') diff --git a/tests/test_convoy_auto_settings.py b/tests/test_convoy_auto_settings.py index ee38954..86a0b6c 100644 --- a/tests/test_convoy_auto_settings.py +++ b/tests/test_convoy_auto_settings.py @@ -5,7 +5,7 @@ from policy_harness import ROOT,body,run BASE=Path(os.environ.get('ERR_CONVOY_SETTINGS_ROOT',ROOT)) P=BASE/'addons/core/Scripts/Game/ERR/00_Core/ERR_Settings.c' keys=body(P,'static array Keys(').replace('array','std::vector') -valid=body(P,'static bool Valid(') +valid='\n'.join(body(P,sig) for sig in ('static bool Valid(', 'static bool Randomizable(', 'static bool ValidSelection(')) default=body(P,'static int AddedDefault(') read=body(P,'protected bool Read(').replace('protected ','').replace('out map values','Map*& values').replace('new map()','new Map()') read=read.replace('JsonLoadContext json','JsonLoadContext* json').replace('json.','json->').replace('values.','values->').replace('foreach (string key : Keys())','for (string key : Keys())').replace('Math.Round','std::round') @@ -53,5 +53,5 @@ for forbidden in ('StartConvoy','StartScenarioConvoy','Spawn','m_HQ.'): # Do not advertise this command-only setting as an editable field absent from the actual fixed menu. menu=body(ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_AdminMenu.c','static array Keys(') assert 'automaticConvoyEnabled' not in menu -assert body(provider,'override bool Help(').count('replies.Insert(')<=4 +assert body(provider,'override bool Help(').count('replies.Insert(')<=5 print('PASS: actual read migrates old valid settings, preserves explicit disabled state, rejects invalid data; next-round feedback and fixed menu remain honest') diff --git a/tests/test_convoy_budget.py b/tests/test_convoy_budget.py index 01b884f..c84ba31 100644 --- a/tests/test_convoy_budget.py +++ b/tests/test_convoy_budget.py @@ -44,6 +44,20 @@ int main(){ invalid.Strength=1;assert(!limited.BindRecord(reserved,0,&invalid));invalid.Strength=2;invalid.Physical=false;assert(!limited.BindRecord(reserved,0,&invalid));invalid.Physical=true;assert(limited.BindRecord(reserved,0,&invalid)); Replication::server=false;assert(!limited.Reserve("client"));Replication::server=true; ERR_GameMode formations;ERR_GameMode::current=&formations;for(int i=0;i<123;i++){auto* r=new ERR_ForceRecord();r->Strength=0;r->Physical=false;formations.ledger.records.Insert(r);}ERR_ConvoyPool capped(&formations,8);assert(!capped.Reserve("formation-cap")); + // Production configuration reserves every full troop truck: 14 passengers + 11 crew. + for(int target:{0,1,3,20}){ + ERR_GameMode supply;ERR_GameMode::current=&supply;ERR_ForceRecord baseline;baseline.Strength=60;supply.ledger.records.Insert(&baseline);ERR_ConvoyPool full(&supply,target,true); + for(int i=0;iOutstandingBodies==25&&ticket->OutstandingGroups==8&&ticket->Records.Count()==8);assert(full.Consume(ticket)); + for(int group=0;group<8;group++){ + auto r=new ERR_ForceRecord();r->Id=1+supply.ledger.records.Count();r->SourceId=ticket->SourceId+"-vehicle-"+std::to_string(group);r->InitialStrength=full.PlannedCount(group);r->Strength=r->InitialStrength;supply.ledger.records.Insert(r);assert(full.BindRecord(ticket,group,r)); + } + assert(ticket->OutstandingBodies==0&&ticket->OutstandingGroups==0&&full.CommittedBodies()==60+25*(i+1)); + } + assert(!full.Reserve("excess")); + for(auto r:supply.ledger.records)r->Strength=0; + assert(!full.Reserve("replacement")); + } ERR_GameMode finite;ERR_GameMode::current=&finite;ERR_ConvoyPool one(&finite,1);assert(one.Reserve("first"));assert(!one.Reserve("second")); } ''') diff --git a/tests/test_convoy_dispatch.py b/tests/test_convoy_dispatch.py index 0adb009..2cdb9ef 100644 --- a/tests/test_convoy_dispatch.py +++ b/tests/test_convoy_dispatch.py @@ -41,6 +41,7 @@ namespace ERR_ConvoyResources{bool available=true;bool Available(){return availa namespace ERR_HQ{void Event(string,string){}} namespace ERR_Actors{int calls=0,fail=0;IEntity* Spawn(string prefab,vector,vector=vector{}){calls++;if(calls==fail)return nullptr;if(prefab=="group")return new SCR_AIGroup();return new Vehicle();}} struct Service{ERR_GameMode* m_Mode;ERR_ConvoyPool* m_Pool;Arraym_Tasks;bool current=true;int crews=0,failCrew=-1; + ERR_ConvoyTask* NewTask(){return new ERR_ConvoyTask();} ERR_ConvoyVehicle* NewVehicle(){return new ERR_ConvoyVehicle();} bool Current(){return current;}bool FillCrew(ERR_ConvoyVehicle* unit){crews++;return unit->Index!=failCrew;} ''' + code + r''' }; @@ -49,7 +50,7 @@ int main(){ ERR_ConvoyRules::valid=false;assert(!service.Dispatch(&receipt,positions,angles,&route,100));assert(!receipt.used&&ERR_Actors::calls==0);ERR_ConvoyRules::valid=true; ERR_ConvoyRules::clear=false;assert(!service.Dispatch(&receipt,positions,angles,&route,100));assert(!receipt.used&&ERR_Actors::calls==0);ERR_ConvoyRules::clear=true; ERR_ConvoyResources::available=false;assert(!service.Dispatch(&receipt,positions,angles,&route,100));assert(!receipt.used&&ERR_Actors::calls==0);ERR_ConvoyResources::available=true; - enemy.key="US";assert(!service.Dispatch(&receipt,positions,angles,&route,100));assert(!receipt.used&&ERR_Actors::calls==0);enemy.key="USSR"; + enemy.key="US"; // A selected non-USSR enemy uses the same finite dispatch transaction. auto task=service.Dispatch(&receipt,positions,angles,&route,100);assert(task&&task->Vehicles.Count()==6&&!task->stopped&&receipt.used&&pool.consumes==1&&ERR_Actors::calls==12&&mode.owned.Count()==12&&service.crews==6); assert(!service.Dispatch(&receipt,positions,angles,&route,100));assert(ERR_Actors::calls==12); for(int failed=1;failed<=12;failed++){ @@ -103,7 +104,7 @@ int main(){ assert(!service.FillCrew(&unit)&&unit.Members.Count()==4&&mode.owned==4);assert(seats[4].spawns==0); } ''') -print('PASS: actual convoy dispatch validates before receipt consumption, consumes once before native mutation, retains all12 partial-failure paths, refuses implicit faction replacement, and allocates exact19 bodies without capacity shrinking') +print('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') # The resource must suppress authored allocation before native EOnInit, not try # to purge a queued default squad after custom seat occupants have been added. diff --git a/tests/test_convoy_startup.py b/tests/test_convoy_startup.py index 32d8faa..cc2e79c 100644 --- a/tests/test_convoy_startup.py +++ b/tests/test_convoy_startup.py @@ -8,7 +8,7 @@ s=s.replace('bool m_Enabled;', 'bool m_Enabled=false;').replace('bool m_Finished s=s.replace('class ERR_ConvoyStartup', 'struct ERR_ConvoyStartup').rstrip()+';' h=body(ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_HQ.c','protected void AutomaticConvoy(') h=h.replace('protected ','').replace('null','nullptr').replace('Replication.','Replication::').replace('ERR_GameMode.','ERR_GameMode::') -for name in ('m_Mode','m_ConvoyStartup'):h=h.replace(name+'.',name+'->') +for name in ('m_Mode','m_ConvoyStartup','m_SupplyConvoys','m_Convoys'):h=h.replace(name+'.',name+'->') run(r''' #include #include @@ -20,7 +20,8 @@ struct ERR_ForceRules {static bool Finite(float n){return std::isfinite(n);}}; struct Replication {inline static bool server=true;static bool IsServer(){return server;}}; struct ERR_GameMode {inline static ERR_GameMode* current;bool active=true;static ERR_GameMode* Get(){return current;}bool Active(){return active;}}; struct Journal {int count=0;void Write(string,string){count++;}}; -struct HQ {ERR_GameMode* m_Mode;ERR_ConvoyStartup* m_ConvoyStartup;void* m_ConvoyTask=nullptr;string m_ConvoyFailure;Journal m_Journal;bool ready=true,accepted=true;int calls=0;bool ConvoyAdmissionReady(){return ready;}bool StartScenarioConvoy(){calls++;return accepted;} +struct Supply {void Tick(float,bool){}}; struct Service {int Count(){return 0;}void* At(int){return nullptr;}}; +struct HQ {Supply* m_SupplyConvoys=nullptr; Service* m_Convoys=nullptr;ERR_GameMode* m_Mode;ERR_ConvoyStartup* m_ConvoyStartup;void* m_ConvoyTask=nullptr;string m_ConvoyFailure;Journal m_Journal;bool ready=true,accepted=true;int calls=0;bool ConvoyAdmissionReady(){return ready;}bool StartScenarioConvoy(){calls++;return accepted;} '''+h+r''' }; int main(){ @@ -31,7 +32,7 @@ int main(){ ERR_ConvoyStartup manual;manual.Initialize(true);assert(!manual.Decide(0,true,true)&&manual.Finished());assert(!manual.Decide(60000,false,true)); ERR_ConvoyStartup invalid;invalid.Initialize(true);assert(!invalid.Decide(std::numeric_limits::quiet_NaN(),false,true));assert(!invalid.Decide(-1,false,true));invalid.Decide(10000,false,false);assert(!invalid.Decide(0,false,true));assert(invalid.Decide(40000,false,true)); ERR_ConvoyStartup stopped;stopped.Initialize(true);stopped.Decide(0,false,false);stopped.Stop();assert(!stopped.Decide(30000,false,true)); - ERR_GameMode mode;ERR_GameMode::current=&mode;ERR_ConvoyStartup startup;startup.Initialize(true);HQ hq{&mode,&startup}; + ERR_GameMode mode;ERR_GameMode::current=&mode;ERR_ConvoyStartup startup;startup.Initialize(true);HQ hq;hq.m_Mode=&mode;hq.m_ConvoyStartup=&startup; Replication::server=false;hq.AutomaticConvoy(0);assert(hq.calls==0&&hq.m_Journal.count==0);Replication::server=true; ERR_GameMode::current=nullptr;hq.AutomaticConvoy(0);assert(hq.m_Journal.count==0);ERR_GameMode::current=&mode; mode.active=false;hq.AutomaticConvoy(0);assert(hq.m_Journal.count==0);mode.active=true; diff --git a/tests/test_debug_ai.py b/tests/test_debug_ai.py new file mode 100644 index 0000000..818cb90 --- /dev/null +++ b/tests/test_debug_ai.py @@ -0,0 +1,18 @@ +"""Execute production kill eligibility, including players, retained bodies and radius.""" +from policy_harness import ROOT,body,run +s=body(ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_DebugAI.c','static bool Eligible(') +s=s.replace('IEntity target','IEntity* target').replace('IEntity center','IEntity* center').replace('array protectedBodies','Array protectedBodies').replace('target.','target->').replace('center.','center->').replace('ChimeraCharacter.Cast','ChimeraCharacter::Cast').replace('ERR_Actors.','ERR_Actors::').replace('vector.','vector::') +run(r''' +#include +#include +#include +#include +struct vector{float x=0,y=0,z=0;static float Distance(vector a,vector b){return std::sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z));}}; +struct IEntity{vector position;bool alive=true,player=false,character=true;vector GetOrigin(){return position;}}; +struct Array:std::vector{using std::vector::vector;bool Contains(IEntity* p){return std::find(begin(),end(),p)!=end();}}; +namespace ChimeraCharacter{bool Cast(IEntity* e){return e&&e->character;}} +namespace ERR_Actors{bool Alive(IEntity* e){return e->alive;}bool Player(IEntity* e){return e->player;}} +'''+s+r''' +int main(){IEntity center,target;Array empty;target.position.x=1000;assert(Eligible(&target,¢er,empty));target.position.x=1000.1;assert(!Eligible(&target,¢er,empty));target.position={0,1001,0};assert(!Eligible(&target,¢er,empty));target.position={10,0,0};assert(Eligible(&target,¢er,empty));target.player=true;assert(!Eligible(&target,¢er,empty));target.player=false;assert(!Eligible(&target,¢er,Array{&target}));target.character=false;assert(!Eligible(&target,¢er,empty));target.character=true;target.alive=false;assert(!Eligible(&target,¢er,empty));assert(!Eligible(nullptr,¢er,empty));assert(!Eligible(¢er,¢er,empty));} +''') +print('PASS: actual killais eligibility includes the 1000m boundary, excludes players/retained bodies/dead/non-character entities and checks full 3D distance') diff --git a/tests/test_dedicated_native.py b/tests/test_dedicated_native.py index 6ef77e1..7cdfef8 100644 --- a/tests/test_dedicated_native.py +++ b/tests/test_dedicated_native.py @@ -76,7 +76,7 @@ class DedicatedNativeTests(unittest.TestCase): self.assertEqual(args[args.index('-worldSystemsConfig')+1], '{C50579A2EC48E8EF}Configs/Systems/MissionSystems.conf') definition = (root/'addons/core/addon.gproj').read_text() dependencies = set(re.findall(r'"([A-F0-9]{16})"', re.search(r'Dependencies\s*\{([^}]+)', definition)[1])) - self.assertEqual(dependencies, {'58D0FB3206B6F859', '595F2BF2F44836FB', '629B2BA37EFFD577', '5E524E4FEECCA92B'}) + self.assertEqual(dependencies, {'58D0FB3206B6F859', '595F2BF2F44836FB', '629B2BA37EFFD577', '5E524E4FEECCA92B', '65930CB4CD0237B2'}) def test_invalid_project_route_combinations_fail_before_files_or_processes(self): for route, project in [('vanilla-everon', 'chat'), ('unknown', 'core'), ('header', 'unknown')]: diff --git a/tests/test_enemy_awareness.py b/tests/test_enemy_awareness.py new file mode 100644 index 0000000..16081ef --- /dev/null +++ b/tests/test_enemy_awareness.py @@ -0,0 +1,41 @@ +"""Execute production aim/perception overrides with native API doubles.""" +from policy_harness import ROOT, body, run +path=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_EnemySkillAwareness.c' +def native(signature): + s=body(path,signature).replace('override ','').replace('super.', 'Native::').replace('EAISkill.', 'EAISkill::') + s=s.replace('PerceptionComponent perceptionComp','PerceptionComponent* perceptionComp').replace('SCR_AIThreatSystem threatSystem','SCR_AIThreatSystem* threatSystem') + return s.replace('perceptionComp.', 'perceptionComp->').replace('m_CombatComponent.', 'm_CombatComponent->') +run(r''' +#include +enum class EAISkill{REGULAR,CYLON}; +struct SCR_AIThreatSystem{}; +struct PerceptionComponent{float factor=0;void SetPerceptionFactor(float f){factor=f;}}; +struct Native{ + int calls=0;EAISkill sampled=EAISkill::CYLON; + float GetRandomFactor(EAISkill s,float mu){calls++;sampled=s;return mu+1;} + void UpdatePerceptionFactor(PerceptionComponent* p,SCR_AIThreatSystem*){calls++;p->factor=.4f;} +}; +struct Combat:Native{ + bool bound=false;float m_fEquipmentPerceptionFactor=1,m_fPerceptionFactor=1; + static constexpr float PERCEPTION_FACTOR_ALERTED=2.5f; + bool ERR_EnhancedEnemy(){return bound;} +'''+native('override void UpdatePerceptionFactor(')+r''' +}; +struct Aim:Native{ + Combat* m_CombatComponent=nullptr; +'''+native('override float GetRandomFactor(')+r''' +}; +int main(){ + Aim aim;Combat combat;PerceptionComponent perception;SCR_AIThreatSystem threat; + aim.GetRandomFactor(EAISkill::CYLON,0);assert(aim.sampled==EAISkill::CYLON); + aim.m_CombatComponent=&combat;aim.GetRandomFactor(EAISkill::CYLON,0);assert(aim.sampled==EAISkill::CYLON); + combat.bound=true;aim.GetRandomFactor(EAISkill::CYLON,0);assert(aim.sampled==EAISkill::REGULAR); + combat.UpdatePerceptionFactor(&perception,&threat);assert(perception.factor==2.5f&&combat.calls==0); + combat.m_fEquipmentPerceptionFactor=3;combat.m_fPerceptionFactor=.5f; + combat.UpdatePerceptionFactor(&perception,&threat);assert(perception.factor==3.75f); + combat.UpdatePerceptionFactor(nullptr,&threat);assert(combat.calls==0); + combat.bound=false;combat.UpdatePerceptionFactor(&perception,&threat);assert(perception.factor==.4f&&combat.calls==1); + aim.GetRandomFactor(EAISkill::CYLON,0);assert(aim.sampled==EAISkill::CYLON); +} +''') +print('PASS: actual scoped REGULAR aim error and alert perception; preserves equipment multiplier and restores vanilla behavior when unbound') diff --git a/tests/test_enemy_equipment.py b/tests/test_enemy_equipment.py index 8725380..45a3b0a 100644 --- a/tests/test_enemy_equipment.py +++ b/tests/test_enemy_equipment.py @@ -44,7 +44,7 @@ struct SCR_AIGroup { struct Settings {int oneIn=15;int Get(std::string key){assert(key=="stingerChanceOneIn");return oneIn;}}; struct ERR_GameMode { static inline ERR_GameMode* current=nullptr;bool active=true;struct Settings values; - static ERR_GameMode* Get(){return current;}bool Active(){return active;}int EnemyFaction(){return 1;} + static ERR_GameMode* Get(){return current;}bool Active(){return active;}int EnemyFaction(){return 1;}bool IsMissionEnemy(int f){return f==1;} struct Settings* Settings(){return &values;} }; namespace Math {int draw=0,calls=0;int RandomInt(int lo,int hi){assert(lo==0&&hi>0);calls++;return draw;}} @@ -70,7 +70,7 @@ struct NativeCombat { namespace ERR_EnemyGunnerSkill { bool CapturedGroup(ERR_GameMode*,SCR_AIGroup*){return false;} bool OriginalGunner(ERR_GameMode*,SCR_AIGroup*,IEntity*){return false;} - EAISkill Profile(EAISkill requested,bool){return requestedSkillChecks==5); auto incompleteOptics=incomplete.m_Entries[0]->Optics;int checksBeforeStop=incompleteOptics->checks; @@ -199,4 +199,4 @@ int main(){ capturedBody.eligible=true;capture.Tick(9000);assert(capturedOptics->checks==1); } ''') -print('PASS: actual equipment coordinator registration dedupe, startup delay, five member scans, finite component retries, unregister/stop terminal behavior and 128-group bound') +print('PASS: actual equipment coordinator registration dedupe, startup delay, five member scans, finite component retries, unregister/stop terminal behavior and 256-group bound') diff --git a/tests/test_enemy_gunner_skill.py b/tests/test_enemy_gunner_skill.py index 13bdca5..a9436d1 100644 --- a/tests/test_enemy_gunner_skill.py +++ b/tests/test_enemy_gunner_skill.py @@ -9,11 +9,11 @@ def convert(s): s=s.replace('ERR_HQ.Cast(mode.Command())','mode->Command()').replace('TurretCompartmentSlot.Cast(slot)','dynamic_cast(slot)') for cls in ('ERR_GameMode','SCR_AIGroupUtilityComponent','SCR_AIGroup','IEntity','ERR_HQ','ERR_ConvoyTask','ERR_ConvoyVehicle','ERR_ForceRecord','BaseCompartmentSlot'): s=re.sub(r'\b'+cls+r' ([a-zA-Z_]\w*)',cls+r'* \1',s) - for obj in ('mode','group','actor','utility','hq','task','unit','record','slot'): + for obj in ('mode','group','actor','utility','hq','task','unit','vehicle','record','slot'): s=s.replace(obj+'.',obj+'->') for field in ('Receipt','Entity'): s=s.replace(field+'.',field+'->') - s=s.replace('Forces().','Forces()->') + s=s.replace('Forces().','Forces()->').replace('Convoys().','Convoys()->') for cls in ('ERR_EnemyEquipmentRules','ERR_EnemyGunnerSkill','ERR_ConvoyRules','ERR_Actors','Replication','SCR_Global','ERR_GameMode','EAISkill','ERR_ForceKind','ECompartmentType','CompartmentAccessComponent'): s=s.replace(cls+'.',cls+'::') s=s.replace('super.','NativeCombat::').replace('null','nullptr').replace('foreach (','for (') @@ -22,8 +22,8 @@ def convert(s): rules=equipment[equipment.index('class ERR_EnemyEquipmentRules'):equipment.index('class ERR_EnemyEquipmentCallback')] rules=convert(rules.replace('class ERR_EnemyEquipmentRules','struct ERR_EnemyEquipmentRules').replace('modded class SCR_AICombatComponent','struct SCR_AICombatComponent : NativeCombat')).replace('\n}\n','\n};\n') # Declare helper before rules, then define its real method bodies after rules. -helper=helper[helper.index(' static bool CapturedGroup'):helper.rfind('}')] -helper=convert(helper).replace('static bool CapturedGroup','bool ERR_EnemyGunnerSkill::CapturedGroup').replace('static bool OriginalGunner','bool ERR_EnemyGunnerSkill::OriginalGunner').replace('static EAISkill Profile','EAISkill ERR_EnemyGunnerSkill::Profile') +helper=helper[helper.index(' static ERR_ConvoyTask TaskForGroup'):helper.rfind('}')] +helper=convert(helper).replace('static ERR_ConvoyTask* TaskForGroup','ERR_ConvoyTask* ERR_EnemyGunnerSkill::TaskForGroup').replace('static bool CapturedGroup','bool ERR_EnemyGunnerSkill::CapturedGroup').replace('static bool OriginalGunner','bool ERR_EnemyGunnerSkill::OriginalGunner').replace('static EAISkill Profile','EAISkill ERR_EnemyGunnerSkill::Profile') run(r''' #include #include @@ -44,12 +44,12 @@ struct Ledger{ERR_ForceRecord* record=nullptr;auto FindGroup(SCR_AIGroup*){retur struct ERR_ConvoyReceipt{bool Consumed=true;Array Records={8};}; struct ERR_ConvoyVehicle{SCR_AIGroup* Group=nullptr;Vehicle* Entity=nullptr;bool Registered=true,Released=false;int Index=0;Array Members;Array Seats;}; struct ERR_ConvoyTask{bool Ready=true,Stopped=false;ERR_ConvoyReceipt* Receipt=nullptr;Array Vehicles;}; -struct ERR_HQ{ERR_ConvoyTask* task=nullptr;auto ConvoyTask(){return task;}}; -struct ERR_GameMode{static inline ERR_GameMode* current=nullptr;bool active=true;ERR_HQ* hq=nullptr;Ledger* ledger=nullptr;static auto Get(){return current;}bool Active(){return active;}int EnemyFaction(){return 1;}auto Command(){return hq;}auto Forces(){return ledger;}}; +struct ERR_HQ{ERR_ConvoyTask* task=nullptr;ERR_ConvoyTask* extra=nullptr;auto Convoys(){return this;}int Count(){return extra?2:1;}auto At(int index){return index==0?task:extra;}auto ConvoyTask(){return task;}}; +struct ERR_GameMode{static inline ERR_GameMode* current=nullptr;bool active=true;ERR_HQ* hq=nullptr;Ledger* ledger=nullptr;static auto Get(){return current;}bool Active(){return active;}int EnemyFaction(){return 1;}bool IsMissionEnemy(int f){return f==1;}auto Command(){return hq;}auto Forces(){return ledger;}}; namespace ERR_Actors{bool CanFight(IEntity* a){return a->alive;}bool Alive(IEntity* a){return a->alive;}bool Player(IEntity* a){return a->player;}auto Group(IEntity* a){return a->group;}} namespace ERR_ConvoyRules{bool capture=false;bool Captured(Vehicle*,SCR_AIGroup* group){return capture||group->players>0;}bool PartOf(IEntity* a,IEntity* b){return a==b;}} namespace CompartmentAccessComponent{auto GetVehicleIn(IEntity* actor){return actor->vehicle;}} -struct ERR_EnemyGunnerSkill{static bool CapturedGroup(ERR_GameMode*,SCR_AIGroup*);static bool OriginalGunner(ERR_GameMode*,SCR_AIGroup*,IEntity*);static EAISkill Profile(EAISkill,bool);}; +struct ERR_EnemyGunnerSkill{static ERR_ConvoyTask* TaskForGroup(ERR_HQ*,SCR_AIGroup*);static bool CapturedGroup(ERR_GameMode*,SCR_AIGroup*);static bool OriginalGunner(ERR_GameMode*,SCR_AIGroup*,IEntity*);static EAISkill Profile(EAISkill,bool);}; struct NativeCombat{IEntity* owner=nullptr;EAISkill skill=EAISkill::REGULAR;int writes=0;auto GetOwner(){return owner;}auto GetAISkill(){return skill;}virtual void SetAISkill(EAISkill value){writes++;skill=value;}virtual void ResetAISkill(){skill=EAISkill::ROOKIE;}}; ''' + rules + helper + r''' int main(){ @@ -59,6 +59,7 @@ int main(){ ERR_ConvoyReceipt receipt;ERR_ConvoyTask task;task.Receipt=&receipt;task.Vehicles={&unit};ERR_HQ hq;hq.task=&task;mode.hq=&hq; ERR_ForceRecord record;Ledger ledger;ledger.record=&record;mode.ledger=&ledger; assert(ERR_EnemyGunnerSkill::OriginalGunner(&mode,&group,&actor)); + ERR_ConvoyTask empty;hq.task=∅hq.extra=&task;assert(ERR_EnemyGunnerSkill::OriginalGunner(&mode,&group,&actor));hq.task=&task;hq.extra=nullptr; // Every native/canonical ownership fact independently matters. for(int i=0;i<25;i++){ auto savedActor=actor;auto savedVehicle=vehicle;auto savedGroup=group;auto savedUnit=unit;auto savedTask=task;auto savedReceipt=receipt;auto savedRecord=record;auto savedSlot=slot; @@ -96,9 +97,9 @@ int main(){ SCR_AICombatComponent combat;combat.owner=&actor;combat.ERR_BindEnemySkill(&mode,&group);assert(combat.skill==EAISkill::CYLON); combat.ResetAISkill();assert(combat.skill==EAISkill::CYLON); combat.SetAISkill(static_cast(90));assert(combat.skill==EAISkill::CYLON); - actor.vehicle=nullptr;slot.occupant=nullptr;combat.ERR_RefreshEnemySkill();assert(static_cast(combat.skill)==90); + actor.vehicle=nullptr;slot.occupant=nullptr;combat.ERR_RefreshEnemySkill();assert(combat.skill==EAISkill::CYLON); actor.vehicle=&vehicle;slot.occupant=&actor;combat.ERR_RefreshEnemySkill();assert(combat.skill==EAISkill::CYLON); - combat.SetAISkill(EAISkill::ROOKIE);slot.occupant=nullptr;combat.ERR_RefreshEnemySkill();assert(combat.skill==EAISkill::EXPERT); + combat.SetAISkill(EAISkill::ROOKIE);slot.occupant=nullptr;combat.ERR_RefreshEnemySkill();assert(combat.skill==EAISkill::CYLON); slot.occupant=&actor;combat.ERR_RefreshEnemySkill();assert(combat.skill==EAISkill::CYLON); // Captured group refresh cannot mutate any soldier. ERR_ConvoyRules::capture=true;int writes=combat.writes;combat.ERR_RefreshEnemySkill();assert(combat.writes==writes);ERR_ConvoyRules::capture=false; @@ -106,10 +107,10 @@ int main(){ // A legitimately high underlying setting stays high after leaving a gunner seat. combat.SetAISkill(EAISkill::CYLON);combat.ERR_BindEnemySkill(&mode,&group);slot.occupant=nullptr;combat.ERR_RefreshEnemySkill();assert(combat.skill==EAISkill::CYLON); combat.ERR_ReleaseEnemySkill(&mode);assert(combat.skill==EAISkill::CYLON); - // Ordinary original infantry retain the existing floor without convoy identity. - hq.task=nullptr;combat.SetAISkill(EAISkill::REGULAR);combat.ERR_BindEnemySkill(&mode,&group);assert(combat.skill==EAISkill::EXPERT); - combat.SetAISkill(static_cast(90));assert(static_cast(combat.skill)==90); + // Ordinary original infantry also receive maximum skill without convoy identity. + hq.task=nullptr;combat.SetAISkill(EAISkill::REGULAR);combat.ERR_BindEnemySkill(&mode,&group);assert(combat.skill==EAISkill::CYLON); + combat.SetAISkill(static_cast(90));assert(combat.skill==EAISkill::CYLON); combat.ERR_ReleaseEnemySkill(&mode);assert(combat.skill==EAISkill::REGULAR); } ''') -print('PASS: actual original turret identity, native/canonical guards, scoped >=80/>=100 profile, reset, dismount/reboard, requested-skill preservation and restoration') +print('PASS: actual original turret identity, native/canonical guards, scoped maximum-skill profile, reset, dismount/reboard, requested-skill preservation and restoration') diff --git a/tests/test_enemy_optics.py b/tests/test_enemy_optics.py index ed6592c..71c25b7 100644 --- a/tests/test_enemy_optics.py +++ b/tests/test_enemy_optics.py @@ -27,6 +27,7 @@ code=code.replace('EWeaponType type','int type').replace('foreach (','for (').re for name in ('ERR_EnemyEquipmentRules','ERR_HQ','Math','EStoragePurpose','EWeaponType'):code=code.replace(name+'.',name+'::') for name in ('entity','child','weapon','sights','slot','job','manager','inventory','storage','inspection'): code=re.sub(r'\b'+name+r'\.',name+'->',code) +code=code.replace('mode.Content().Allows(prefab)', 'mode->Content()->Allows(prefab)').replace('mode.Content()', 'mode->Content()') code=code.replace('job->Operation.','job->Operation->') code=re.sub(r'\b(bool|int|IEntity|SCR_AIGroup) (\w+);',r'\1 \2{};',code) code=re.sub(r'\b(ERR_EnemyEquipmentCallback\*) (\w+);',r'\1 \2{};',code) @@ -38,7 +39,7 @@ preamble=r''' #include using string=std::string;using ResourceName=std::string; templatestruct Array:std::vector{using std::vector::vector;int Count(){return this->size();}bool IsEmpty(){return this->empty();}void Insert(T t){this->push_back(t);}void Remove(int index){this->erase(this->begin()+index);}bool Contains(T t){return std::find(this->begin(),this->end(),t)!=this->end();}}; -struct Entity;struct Group;struct Weapon;struct Manager;struct Inventory;struct Storage;struct Slot;struct Sights;struct ERR_GameMode{}; +struct Entity;struct Group;struct Weapon;struct Manager;struct Inventory;struct Storage;struct Slot;struct Sights;struct ContentPolicy{bool rhs=true;bool Allows(string p){return rhs||p.find("{C850A33226B8F9C1}")!=string::npos||p.find("{D2018EDB1BBF4C88}")!=string::npos||p.find("{BD496EE1B40DC510}")!=string::npos;}};struct ERR_GameMode{ContentPolicy content;ContentPolicy* Content(){return &content;}}; using IEntity=Entity*;using SCR_AIGroup=Group*;using BaseWeaponComponent=Weapon*;using BaseWeaponManagerComponent=Manager*; using InventoryStorageManagerComponent=Inventory*;using WeaponAttachmentsStorageComponent=Storage*;using InventoryStorageSlot=Slot*;using AttachmentSlotComponent=Slot*;using BaseSightsComponent=Sights*; struct ScriptedInventoryOperationCallback{virtual void OnComplete(){}virtual void OnFailed(){}virtual void OnAllComplete(){}virtual void OnAllFailed(){}virtual ~ScriptedInventoryOperationCallback()=default;}; @@ -68,6 +69,8 @@ struct Fixture{ERR_GameMode mode;Group group,other;Entity actor,rifle;Weapon wea Fixture(){actor.group=&group;actor.manager=&manager;actor.inventory=&inv;manager.weapons={&rifle};rifle.weapon=&weapon;rifle.storage=&storage;weapon.owner=&rifle;storage.slots={&slot};} }; int main(){ + {Fixture f;f.mode.content.rhs=false;f.inv.fit=false;ERR_EnemyOptics s(&f.actor,&f.group);for(int i=0;i<5;i++)s.Check(&f.mode);assert(f.inv.submits==0&&f.inv.checks==12);} + // Existing mounted/nested/sights magnified optics are preserved. Occupied red dots aren't overwritten. for(int style=0;style<3;style++){Fixture f;Entity optic,adapter;Sights sights;Slot attach; optic.scope2D=style==0;optic.scope2DPip=style==1;optic.scopePip=style==2;if(style==0){f.rifle.child=&adapter;adapter.child=&optic;} diff --git a/tests/test_external_addons.py b/tests/test_external_addons.py index cbcd421..a759214 100644 --- a/tests/test_external_addons.py +++ b/tests/test_external_addons.py @@ -38,7 +38,7 @@ class ExternalAddonsTests(unittest.TestCase): 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_six_are_exposed_and_hashed(self): + 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)) diff --git a/tests/test_faction_selection.py b/tests/test_faction_selection.py new file mode 100644 index 0000000..2c86f8d --- /dev/null +++ b/tests/test_faction_selection.py @@ -0,0 +1,50 @@ +"""Execute role resolution: reserve explicit choices, then sample without replacement.""" +import re +from policy_harness import ROOT, body, run +path = ROOT / 'addons/core/Scripts/Game/ERR/00_Core/ERR_FactionSelection.c' +code = '\n'.join(body(path, signature) for signature in ['static bool Resolve(', 'static bool Distinct(']) +code = code.replace('array available', 'Array available').replace('array fixed', 'Array fixed') +code = code.replace('map', 'Map&').replace('foreach (', 'for (').replace('Math.RandomInt', 'RandomInt') +run(r''' +#include +#include +#include +#include +#include +using string=std::string; +template struct Array:std::vector { + using std::vector::vector; + int Count()const{return this->size();} bool IsEmpty(){return this->empty();} + bool Contains(T v){return std::find(this->begin(),this->end(),v)!=this->end();} + void Insert(T v){this->push_back(v);} void Remove(int i){this->erase(this->begin()+i);} + void RemoveItem(T v){auto i=std::find(this->begin(),this->end(),v);if(i!=this->end())this->erase(i);} +}; +struct Map:std::map{bool Contains(string k){return count(k);}string Get(string k){return at(k);}void Set(string k,string v){(*this)[k]=v;}void Clear(){clear();}}; +struct Rules { + static Array Roles(){return {"escapists","enemy","independent"};} + static bool Find(string id){return id=="us"||id=="ussr"||id=="fia"||id=="rhs";} + static int RandomInt(int,int end){static unsigned x=17;x=x*1664525u+1013904223u;return x%end;} +''' + code + r''' +}; +int main(){ + Map saved,resolved; + for(auto role:Rules::Roles())saved.Set(role,"random"); + for(int n=0;n<1000;n++){ + assert(Rules::Resolve({"us","ussr","fia","rhs"},saved,resolved)); + assert(Rules::Distinct(resolved)&&resolved.size()==3); + } + saved.Set("enemy","us");saved.Set("independent","fia"); + for(int n=0;n<100;n++){ + assert(Rules::Resolve({"us","ussr","fia"},saved,resolved)); + assert(resolved.Get("escapists")=="ussr"&&resolved.Get("enemy")=="us"&&resolved.Get("independent")=="fia"); + } + saved.Set("enemy","rhs"); + assert(Rules::Resolve({"us","ussr","fia"},saved,resolved)); + assert(resolved.Get("enemy")!="rhs"&&resolved.Get("independent")=="fia"); + saved.Set("enemy","fia");assert(!Rules::Resolve({"us","ussr","fia"},saved,resolved));assert(resolved.empty()); + saved.Set("enemy","unknown");assert(!Rules::Resolve({"us","ussr","fia"},saved,resolved)); + saved.Set("enemy","us");assert(!Rules::Resolve({"us","fia"},saved,resolved)); + saved.erase("escapists");assert(!Rules::Resolve({"us","ussr","fia"},saved,resolved)); +} +''') +print('PASS: actual faction resolution reserves explicit roles, samples without replacement, substitutes disabled selections, and rejects duplicate/unknown/missing choices and insufficient pools') diff --git a/tests/test_force_ledger.py b/tests/test_force_ledger.py index 4458cab..6ac8ee9 100644 --- a/tests/test_force_ledger.py +++ b/tests/test_force_ledger.py @@ -190,14 +190,14 @@ int main(){ assert(ledger.Unregister(physical->Id)&&!ledger.FindGroup(&group)); assert(!ledger.Register("physical",K::GARRISON,{0,0,0},4)); ledger.Clear();assert(ledger.Count()==0&&ledger.m_Sources.Count()==0&&ledger.m_ById.Count()==0); - // All 128 formations remain bounded through a simulated hour; stagger only affects snapshot age. + // All 256 formations remain bounded through a simulated hour; stagger only affects snapshot age. ERR_ForceLedger hour;ERR_ForceSimulation hourSim(&hour);auto circuit=square(true); - for(int i=0;i<128;i++)assert(hour.Register(std::to_string(i),K::PATROL,{0,10,0},4,circuit)); + for(int i=0;i<256;i++)assert(hour.Register(std::to_string(i),K::PATROL,{0,10,0},4,circuit)); assert(!hour.Register("overflow",K::PATROL,{0,0,0},4)); assert(!hour.Register("overflow2",K::PATROL,{0,0,0},4)&&logs==1); for(int t=1000;t<=3600000;t+=1000)hourSim.Tick(t); - assert(hour.Count()==128&&hour.m_Sources.Count()==128&&hour.m_ById.Count()==128); - for(int i=0;i<128;i++){ + assert(hour.Count()==256&&hour.m_Sources.Count()==256&&hour.m_ById.Count()==256); + for(int i=0;i<256;i++){ auto r=hour.At(i);assert(!r->Eliminated&&r->Strength==4&&r->Casualties==0); assert(3600000-r->LastSimulatedAt<=1000); float distance=std::fmod(1.4*r->LastSimulatedAt/1000,56); @@ -208,7 +208,7 @@ int main(){ else actual=56-r->Position.z; assert(std::min(std::abs(actual-distance),56-std::abs(actual-distance))<.1); } - assert(hour.Status()=="128,0,128,0,512,0"); + assert(hour.Status()=="256,0,256,0,1024,0"); assert(hour.Unregister(hour.At(0)->Id)); assert(!hour.Register("replacement",K::PATROL,{0,0,0},4)); // retired identity consumes finite pool } @@ -221,4 +221,4 @@ for path in (L,S): assert all(len(line)<120 for line in text.splitlines()),path for signature in ('protected void Route(', 'void Tick('): assert 'new ' not in body(S,signature) -print('PASS: actual force ledger, finite casualties/identity/cap, routes/arrival/elevation/overshoot, server and physical guards, staggered 128-record simulated hour without world queries') +print('PASS: actual force ledger, finite casualties/identity/cap, routes/arrival/elevation/overshoot, server and physical guards, staggered 256-record simulated hour without world queries') diff --git a/tests/test_generated_sites.py b/tests/test_generated_sites.py new file mode 100644 index 0000000..a46ded2 --- /dev/null +++ b/tests/test_generated_sites.py @@ -0,0 +1,36 @@ +"""Run the actual bounded placement scheduler with terrain and clock adapters.""" +import re +from policy_harness import ROOT,body,run +p=ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_GeneratedSites.c' +s=body(p,'ERR_PrepareResult Tick(') +s=s.replace('ERR_SiteDefinition site','Site* site').replace('site.','site->').replace('m_Terrain.Site','m_Terrain.SiteAt') +s=s.replace('System.GetTickCount','Clock::Now').replace('Replication.IsServer','Server').replace('Math.RandomFloat','RandomFloat').replace('ERR_PrepareResult.','Result::') +s=s.replace('float floor;','float floor=0;') +run(r''' +#include +#include +#include +using string=std::string; +struct vector{float a[3];float& operator[](int i){return a[i];}};vector Vector(float x,float y,float z){return {{x,y,z}};} +namespace Result{enum Value{FAILED=-1,PENDING,READY};}using ERR_PrepareResult=Result::Value; +namespace Clock {int now=0,step=1;int Now(){int t=now;now+=step;return t;}} +bool Server(){return true;}float RandomFloat(float a,float b){return (a+b)/2;}templatevoid PrintFormat(T...){} +struct Site{vector Position=Vector(10,0,20);float Heading=0;bool PlacementResolved=false;string Id="site";}; +templatestruct Array:std::vector{using std::vector::operator=;int Count(){return this->size();}}; +struct Terrain{bool clear=true;int queries=0;bool SiteAt(Site*,vector,float,float& height){queries++;height=42;return clear;}}; +struct Scheduler{ + bool m_Started=true;ERR_PrepareResult m_Result=Result::PENDING;int m_Index=0,m_Attempts=0,m_Began=0; + vector m_Low=Vector(0,0,0),m_High=Vector(10000,0,10000);Arraym_Pending;Terrain m_Terrain;string m_Error; + bool Separated(Site*,vector,bool){return true;} +'''+s+r''' +}; +int main(){ + {Scheduler s;s.m_Started=false;assert(s.Tick()==Result::FAILED);} + {Scheduler s;assert(s.Tick()==Result::READY);assert(s.m_Terrain.queries==0);} + {Clock::now=0;Scheduler s;Site a,b;s.m_Pending={&a,&b};while(s.Tick()==Result::PENDING){}assert(s.m_Result==Result::READY&&a.PlacementResolved&&b.PlacementResolved);assert(a.Position[1]>42&&a.Position[1]<42.1);int calls=s.m_Terrain.queries;assert(s.Tick()==Result::READY&&s.m_Terrain.queries==calls);} + {Clock::now=0;Scheduler s;Site a;s.m_Pending={&a};s.m_Terrain.clear=false;assert(s.Tick()==Result::PENDING);assert(s.m_Terrain.queries<10&&!a.PlacementResolved);Clock::now=30001;assert(s.Tick()==Result::FAILED&&!s.m_Error.empty()&&!a.PlacementResolved);int calls=s.m_Terrain.queries;assert(s.Tick()==Result::FAILED&&s.m_Terrain.queries==calls);} + {Clock::now=0;Scheduler s;Site a;s.m_Pending={&a};s.m_Attempts=12000;assert(s.Tick()==Result::READY&&a.Position[0]==10&&a.Position[2]==20&&a.PlacementResolved);} + {Clock::now=30001;Scheduler s;Site a;s.m_Pending={&a};assert(s.Tick()==Result::READY&&a.Position[0]==10&&a.Position[2]==20);} +} +''') +print('PASS: actual generation scheduler bounds each tick, enforces deadline/candidate ceiling, validates fallback, commits only accepted positions, and terminates without repeated searches') diff --git a/tests/test_hq_ammo_dispatch.py b/tests/test_hq_ammo_dispatch.py index 446bc0f..53eb1f4 100644 --- a/tests/test_hq_ammo_dispatch.py +++ b/tests/test_hq_ammo_dispatch.py @@ -7,14 +7,14 @@ for method in ('protected void Investigate(', 'protected void Retask(', 'protect # Execute the production delivery admission before unrelated native waypoint creation. s=body(H,'protected void DeliverOrder(') s=s[:s.index(' if (task.Investigation())')]+' admitted++;\n }' -s=s.replace('protected ','').replace('null','nullptr').replace('ERR_HQUnit unit','ERR_HQUnit* unit') +s=s.replace('protected ','').replace('null','nullptr').replace('.IsEmpty()', '.empty()').replace('ERR_HQUnit unit','ERR_HQUnit* unit') s=s.replace('ERR_HQReport order','ERR_HQReport* order').replace('ERR_HQTask task','ERR_HQTask* task') for name in ('unit','task','order'):s=s.replace(name+'.',name+'->') run(r''' #include #include struct ERR_HQReport{}; -struct ERR_HQTask{float ExpiresAt=100000;bool ReleaseOnly=false;ERR_HQTask* ReplacesTask=nullptr;}; +struct ERR_HQTask{std::string SecuritySite;float ExpiresAt=100000;bool ReleaseOnly=false;ERR_HQTask* ReplacesTask=nullptr;}; struct ERR_HQUnit{ERR_HQReport* PendingOrder=nullptr;ERR_HQTask* PendingTask=nullptr;ERR_HQTask* Task=nullptr; std::string ForceSourceId="original-1";bool eligible=true;int cancellations=0; bool Eligible(void*){return eligible;}void CancelPending(){cancellations++;PendingOrder=nullptr;PendingTask=nullptr;}}; diff --git a/tests/test_hq_assignment_lifecycle.py b/tests/test_hq_assignment_lifecycle.py index 5761bd1..9b54477 100644 --- a/tests/test_hq_assignment_lifecycle.py +++ b/tests/test_hq_assignment_lifecycle.py @@ -5,6 +5,7 @@ p=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_HQ.c' unit='\n'.join(body(p,s) for s in ('void CancelPending(', 'ERR_HQTask PlannedTask(', 'void ReleaseAssignment(', 'void Release()')) lost='\n'.join(body(p,s) for s in ('protected void FinishWatch(', 'protected void LostOrder(')).replace('protected ', '') def adapt(code): + code=code.replace('.IsEmpty()', '.empty()') code=code.replace('null','nullptr').replace('Math.','Math::').replace('ERR_GameMode.Get()', 'ERR_GameMode::Get()') code=code.replace('SCR_EntityHelper.DeleteEntityAndChildren', 'SCR_EntityHelper::DeleteEntityAndChildren') code=code.replace('ERR_HQUnit unit', 'ERR_HQUnit* unit') @@ -21,7 +22,7 @@ run(r''' #include #include struct Math {static float Min(float a,float b){return std::min(a,b);}}; -struct ERR_HQTask {bool ReleaseOnly=false;int BeliefId=0;std::string WatchSourceId;int WatchMessageId=0,WatchRequestId=0;bool Investigation(){return !WatchSourceId.empty();}}; +struct ERR_HQTask {bool ReleaseOnly=false;int BeliefId=0;std::string WatchSourceId,SecuritySite;int WatchMessageId=0,WatchRequestId=0;bool Investigation(){return !WatchSourceId.empty();}}; struct ERR_HQReport {}; struct ERR_HQRoute {}; struct AIWaypoint {int deleted=0;}; @@ -98,6 +99,9 @@ int main(){ ERR_HQTask recall;recall.ReleaseOnly=true;u.PendingTask=&recall;u.PendingOrder=&newReport;u.Downlink=&route; hq.LostOrder(&u,5000);assert(!u.PendingTask&&u.Task==&activeWatch&&u.Waypoint==&oldWaypoint&&hq.m_Watch.calls==1); u.Task=nullptr;u.Waypoint=nullptr;u.Assignment=nullptr; + ERR_HQTask security;security.SecuritySite="radio-1";u.PendingTask=&security;u.PendingOrder=&newReport;u.Downlink=&route; + hq.window.NextHunt=300000;hq.LostOrder(&u,5000); + assert(!u.PendingTask&&!u.Downlink&&hq.window.NextHunt==300000&&hq.m_Watch.calls==1); // Unrelated belief cannot suppress bounded retry, and existing sooner retry remains sooner. peer.PendingTask=&oldTask;u.PendingTask=&newTask;hq.window.NextHunt=5000; hq.LostOrder(&u,2000);assert(hq.window.NextHunt==5000); diff --git a/tests/test_hq_body_observer.py b/tests/test_hq_body_observer.py index ec245bc..5e10cde 100644 --- a/tests/test_hq_body_observer.py +++ b/tests/test_hq_body_observer.py @@ -157,11 +157,11 @@ int main(){ assert(!service.Observe(&contenders[1],1000,report)); service.Observe(&contenders[1],6000,report);assert(service.m_Groups[1]->NextScan==21000); // Registry cap is finite, logs once, and deleted identities free future slots. - service.Stop();logs=0;Entity actors[160];Agent agents[160];Group groups[5]; - for(int g=0;g<5;g++){for(int i=0;i<32;i++){int n=g*32+i;agents[n].actor=&actors[n];groups[g].agents.Insert(&agents[n]);}service.RegisterGroup(&groups[g],Roster(&groups[g]));} - assert(service.m_Roster.Count()==128&&logs==1);service.RegisterGroup(&groups[4],Roster(&groups[4]));assert(logs==1); + service.Stop();logs=0;Entity actors[4128];Agent agents[4128];Group groups[129]; + for(int g=0;g<129;g++){for(int i=0;i<32;i++){int n=g*32+i;agents[n].actor=&actors[n];groups[g].agents.Insert(&agents[n]);}service.RegisterGroup(&groups[g],Roster(&groups[g]));} + assert(service.m_Roster.Count()==4096&&logs==1);service.RegisterGroup(&groups[128],Roster(&groups[128]));assert(logs==1); for(int i=0;i<32;i++)service.m_Roster[i]->Corpse=nullptr; - service.RegisterGroup(&groups[4],Roster(&groups[4]));assert(service.m_Roster.Count()==128); + service.RegisterGroup(&groups[128],Roster(&groups[128]));assert(service.m_Roster.Count()==4096); service.Stop();assert(service.m_Roster.IsEmpty()); } ''') diff --git a/tests/test_hq_convoy_combat.py b/tests/test_hq_convoy_combat.py index de79387..5397c43 100644 --- a/tests/test_hq_convoy_combat.py +++ b/tests/test_hq_convoy_combat.py @@ -6,9 +6,9 @@ H = ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_HQ.c' def cpp(s): s=s.replace('protected ', '').replace('null','nullptr').replace('foreach (','for (') for x in ('ERR_HQPursuitRules','vector','string'): s=s.replace(x+'.',x+'::') - for typ in ('ERR_HQUnit','ERR_HQReport','ERR_HQWatchEntry','ERR_HQRoute','ERR_ConvoyCombatOrder','ERR_ConvoyVehicle'): + for typ in ('ERR_HQUnit','ERR_HQReport','ERR_HQWatchEntry','ERR_HQRoute','ERR_ConvoyCombatOrder','ERR_ConvoyVehicle','ERR_ConvoyTask'): s=re.sub(r'\b'+typ+r' (?=\w)',typ+'* ',s) - for x in ('entry','unit','best','report','vehicle','contact','route','order','m_ConvoyTask'): + for x in ('entry','unit','best','report','vehicle','contact','route','order','task','m_ConvoyTask'): s=s.replace(x+'.',x+'->') s=s.replace('->Combat.', '->Combat->').replace('->Receipt.', '->Receipt->') s=s.replace('unit->Downlink.', 'unit->Downlink->') @@ -16,7 +16,7 @@ def cpp(s): s=s.replace('bool accepted;', 'bool accepted = false;') return s methods='\n'.join(cpp(body(H,s)) for s in ('protected bool ConvoyPositionKnown(', - 'protected ERR_HQReport ConvoyContact(', 'protected void PlanConvoy(', 'protected void DeliverConvoyOrder(')) + 'protected ERR_HQReport ConvoyContact(', 'protected void PlanConvoy(', 'protected void PlanConvoyTask(', 'protected void DeliverConvoyOrder(')) downlink=cpp(body(H,'if (unit.Downlink)\n')) cancel=cpp(body(H,'void CancelPending(')) src=H.read_text() @@ -40,20 +40,21 @@ struct Watch {std::map entries;ERR_HQWatchEntry* Find( struct Journal {int seq=100;int Message(){return ++seq;}void Write(string,string,int){}}; struct ERR_HQRoute {int MessageId=0;string Payload;int result=0;int Advance(float,Journal&){return result;}}; struct Network {bool available=true;int calls=0;ERR_HQRoute* Route(void*,bool down){assert(down);calls++;return available?new ERR_HQRoute:nullptr;}}; -struct ERR_ConvoyCombatOrder {int CommandId=0,ReportId=0,VehicleIndex=0;string SourceId;SCR_AIGroup* Group=nullptr;bool Hold=false;float ObservedAt=-1,IssuedAt=0,ExpiresAt=0;}; +struct ERR_ConvoyCombatOrder {int CommandId=0,ReportId=0,VehicleIndex=0;string SourceId;SCR_AIGroup* Group=nullptr;vector Position;bool Hold=false;float ObservedAt=-1,IssuedAt=0,ExpiresAt=0;}; struct CombatState {bool Held=false;int LastCommandId=0,ReportId=0;float ObservedAt=-1;}; struct ERR_ConvoyVehicle {int SupplyToken=0,Index=0;SCR_AIGroup* Group=nullptr;bool Released=false,Arrived=false,Registered=true;CombatState state;CombatState* Combat=&state;}; struct Receipt {string SourceId="convoy-1";}; -struct ConvoyTask {bool Stopped=false,Ready=true;struct Receipt receipt;struct Receipt* Receipt=&receipt;std::vector Vehicles;}; -struct Service {int calls=0;bool valid=true;ERR_ConvoyCombatOrder* last=nullptr; - bool ApplyCombatOrder(ConvoyTask* task,ERR_ConvoyCombatOrder* o,float){calls++;last=o;if(!task||!valid)return false; +struct ERR_ConvoyTask {bool Stopped=false,Ready=true;struct Receipt receipt;struct Receipt* Receipt=&receipt;std::vector Vehicles;}; +struct Service {ERR_ConvoyTask* task=nullptr;int Count(){return task?1:0;}ERR_ConvoyTask* At(int){return task;}ERR_ConvoyTask* Find(string id){return task&&task->Receipt->SourceId==id?task:nullptr;} + int calls=0;bool valid=true;ERR_ConvoyCombatOrder* last=nullptr; + bool ApplyCombatOrder(ERR_ConvoyTask* task,ERR_ConvoyCombatOrder* o,float){calls++;last=o;if(!task||!valid)return false; auto s=task->Vehicles.at(o->VehicleIndex)->Combat;s->Held=o->Hold;s->LastCommandId=o->CommandId;s->ReportId=o->ReportId;s->ObservedAt=o->ObservedAt;return true;}}; struct ERR_HQUnit {SCR_AIGroup* Group=nullptr;bool ReservedForSupport=true;void* Radio=this;string ForceSourceId="vehicle-0"; ERR_HQRoute* Downlink=nullptr;ERR_ConvoyCombatOrder* PendingConvoyOrder=nullptr;void* PendingOrder=nullptr;void* PendingTask=nullptr; bool PendingCheckin=false;float NextStatus=0; '''+cancel+r''' }; -struct HQ {Watch m_Watch;Network m_Network;Journal m_Journal;Service m_Convoys;ConvoyTask* m_ConvoyTask=nullptr; +struct HQ {Watch m_Watch;Network m_Network;Journal m_Journal;Service m_Convoys;ERR_ConvoyTask* m_ConvoyTask=nullptr; std::vector m_Units;std::vector m_Contacts;int ordinary=0,lost=0; void DeliverOrder(ERR_HQUnit*,float){ordinary++;}void LostOrder(ERR_HQUnit* u,float){lost++;u->CancelPending();} '''+methods+r''' @@ -62,7 +63,7 @@ struct HQ {Watch m_Watch;Network m_Network;Journal m_Journal;Service m_Convoys;C } }; int main(){ - HQ h;SCR_AIGroup g;ERR_HQUnit u;u.Group=&g;h.m_Units={&u};ConvoyTask t;h.m_ConvoyTask=&t; + HQ h;SCR_AIGroup g;ERR_HQUnit u;u.Group=&g;h.m_Units={&u};ERR_ConvoyTask t;h.m_ConvoyTask=&t;h.m_Convoys.task=&t; ERR_ConvoyVehicle v;v.Group=&g;t.Vehicles={&v};ERR_HQWatchEntry e;e.ObservedAt=1000;e.Position={0,0}; ERR_HQReport r;r.MessageId=1;r.ObservedAt=2000;r.Position={200,0}; h.PlanConvoy(3000);assert(!u.Downlink); // no delivered own status or target report diff --git a/tests/test_hq_convoy_dispatch.py b/tests/test_hq_convoy_dispatch.py index ec318f0..d03e870 100644 --- a/tests/test_hq_convoy_dispatch.py +++ b/tests/test_hq_convoy_dispatch.py @@ -12,23 +12,24 @@ def cpp(s): ('ERR_Settings.','ERR_Settings::'),('Math.','Math::'),('array','Array&')]:s=s.replace(old,new) for typ in ('ERR_GameMode','ERR_ConvoyReceipt','ERR_ConvoyTask','ERR_SiteRuntime','ERR_HQUnit','ERR_AdminProvider'): s=re.sub(r'\b'+typ+r' (?=\w)',typ+'* ',s) - for var in ('m_ConvoyStartup','m_Mode','m_Convoys','m_ConvoyPool','m_ConvoyTask','m_HQ','site','unit','receipt','mode','provider'): + for var in ('m_SupplyConvoys','m_ConvoyStartup','m_Mode','m_Convoys','m_ConvoyPool','m_ConvoyTask','m_HQ','site','unit','receipt','mode','provider'): s=s.replace(var+'.',var+'->') s=s.replace('site->Definition.', 'site->Definition->') - for name in ('GetGame()','GetWorld()','Forces()','Sites()','Settings()'):s=s.replace(name+'.',name+'->') + for name in ('GetGame()','GetWorld()','Forces()','Sites()','Settings()','Recon()','AirAssault()','Airfield()','Recovery()'):s=s.replace(name+'.',name+'->') s=s.replace('foreach (ERR_HQUnit* unit : m_Units)','for (ERR_HQUnit* unit : m_Units)') s=s.replace('foreach (ERR_AdminProvider* provider : m_Providers)','for (ERR_AdminProvider* provider : m_Providers)') s=s.replace('foreach (string key : ERR_Settings::Keys())','for (string key : ERR_Settings::Keys())') s=s.replace('mode->Settings()->Get(key).ToString()','string(std::to_string(mode->Settings()->Get(key)))') s=s.replace('bool handled;','bool handled=false;') - s=s.replace('Array& parts = {};','Array parts = {};') + s=s.replace('Array& parts = {};','Array parts = {};').replace('Array& countParts = {};','Array countParts = {};').replace('ERR_CommandArguments.Selection','ERR_CommandArguments::Selection') + s=s.replace('Array& timerParts = {};','Array timerParts = {};') s=s.replace('out int ', 'int& ').replace('ERR_CommandArguments.Integer', 'ERR_CommandArguments::Integer') s=s.replace('value.ToString()', 'string(std::to_string(value))') s=s.replace('"0123456789".IndexOf(', 'string("0123456789").IndexOf(') return s hq='\n'.join(cpp(body(H,s)) for s in ('static bool MissionActive(', 'bool PrepareConvoy(', 'bool StartConvoy(', 'bool StartScenarioConvoy(', 'string ConvoyStatus(')) -provider=cpp(body(P,'protected void ConvoyAutoSetting('))+cpp(body(P,'protected void StingerSetting('))+cpp(body(P,'override bool Execute(')) +provider=cpp(body(P,'protected void CountSetting('))+cpp(body(P,'protected void ConvoyAutoSetting('))+cpp(body(P,'protected void StingerSetting('))+cpp(body(P,'override bool Execute(')) integer=cpp(body(A,'static bool Integer(')) validator=cpp(body(BASE/'addons/core/Scripts/Game/ERR/00_Core/ERR_Settings.c','static bool Valid(')) extension=cpp(body(A,'protected bool Extension(')) @@ -65,6 +66,7 @@ void string::Split(const char* separator,Array& parts,bool skipEmpty)con } } struct ERR_CommandArguments{ + static bool Selection(string key,string text,int& value){if(key!="convoyCount")return false;if(text=="random"){value=-1;return true;}return Integer(text,value)&&value>=0&&value<=20;} '''+integer+r''' }; struct vector{float x=0,y=0,z=0;}; @@ -78,10 +80,12 @@ struct ERR_SiteRuntime{struct Definition* Definition=nullptr;}; struct Sites{ERR_SiteRuntime* site=nullptr;int finds=0;string last; ERR_SiteRuntime* Find(string id){finds++;last=id;return site;}}; struct ERR_Settings{ - int automatic=1,stinger=15,writes=0;bool saveFails=false; - static Array Keys(){return {}; }int Get(string key){return key=="stingerChanceOneIn"?stinger:automatic;} + int automatic=1,stinger=15,convoy=3,writes=0;bool saveFails=false; + static Array Keys(){return {}; }int Get(string key){if(key=="convoyCount")return convoy;return key=="stingerChanceOneIn"?stinger:automatic;} '''+validator+r''' - bool Set(string key,int value){writes++;if(saveFails||!Valid(key,value))return false; + static string SelectionText(int value){return value==-1?string("random"):string(std::to_string(value));} + bool Set(string key,int value){writes++;if(saveFails||(!Valid(key,value)&&!(key=="convoyCount"&&value==-1)))return false; + if(key=="convoyCount"){convoy=value;return true;} if(key=="automaticConvoyEnabled"){automatic=value;return true;} assert(key=="stingerChanceOneIn");stinger=value;return true;} }; @@ -118,10 +122,15 @@ struct Service{ if(!preflight)return nullptr; receipt->Consumed=true;task.Stopped=partial;task.retained=partial?3:6;return &task; } + int Count(){return 0;}ERR_ConvoyTask* At(int){return &task;} string Status(){statusCalls++;return task.Stopped?"stopped; retained vehicles=3":"convoy service status";} }; +struct Supply{bool StartOne(){return false;}string Status(){return "supply";}}; struct ERR_ConvoyStartup{string Status(){return "startup snapshot";}}; +struct ReconService{string Status(){return "recon";}void Return(){}bool SetDelay(int n){return n>=1&&n<=1440;}}; struct HQ{ + ReconService recon;ReconService* Recon(){return &recon;}ReconService* AirAssault(){return &recon;}ReconService* Airfield(){return &recon;}ReconService* Recovery(){return &recon;} + Supply* m_SupplyConvoys=nullptr;bool ConvoyAdmissionReady(){return true;} ERR_ConvoyStartup* m_ConvoyStartup=nullptr; ERR_GameMode* m_Mode;Pool* m_ConvoyPool;Service* m_Convoys;ERR_ConvoyTask* m_ConvoyTask=nullptr; Arraym_ConvoyPositions,m_ConvoyAngles;ERR_ForceRoute* m_ConvoyRoute=nullptr;string m_ConvoyFailure; @@ -246,6 +255,14 @@ int main(){ Service consumedService;HQ consumed(&mode,&consumedPool,&consumedService); assert(!consumed.StartScenarioConvoy()&&!consumed.m_ConvoyTask&&consumedService.calls==0); assert(consumed.ConvoyStatus().find("finite convoy allowance")!=string::npos); + for(string command:{"convoys set 0","hq convoy count set 20","convoys set random"}){ + int calls=service.calls;replies.Clear();admin.Execute(&mode,true,command,replies);assert(replies.Count()==1&&replies[0].find("saved for next round")!=std::string::npos&&service.calls==calls); + } + assert(mode.settings.convoy==-1);writes=mode.settings.writes;admin.Execute(&mode,false,"convoys set 5",replies);assert(mode.settings.convoy==-1&&mode.settings.writes==writes); + for(string invalid:{"convoys set 21","convoys set -2","convoys set 1 extra"}){admin.Execute(&mode,true,invalid,replies);assert(mode.settings.convoy==-1);} + mode.settings.saveFails=true;admin.Execute(&mode,true,"convoys set 4",replies);assert(mode.settings.convoy==-1);mode.settings.saveFails=false; + admin.Execute(&mode,true,"convoys show",replies);assert(replies.Count()==1&&replies[0].find("random")!=std::string::npos); + } ''') for sig in ('bool PrepareConvoy(', 'bool StartConvoy(', 'bool StartScenarioConvoy('): diff --git a/tests/test_hq_coverage.py b/tests/test_hq_coverage.py index 4157819..baae0f2 100644 --- a/tests/test_hq_coverage.py +++ b/tests/test_hq_coverage.py @@ -131,14 +131,14 @@ int main(){ assert(!bounded.Recent({250,12,250},2000)&&bounded.Recent(item.Position,2000)); // Replay watermarks do not grow or evict an old source's identity under pressure. Coverage sources; - for(int i=1;i<=128;i++){ + for(int i=1;i<=256;i++){ item=ERR_HQSearchReport{};item.SourceId=i;item.ObservedAt=i; assert(sources.Ingest(&item,1000)); } - item.SourceId=129;item.ObservedAt=129; - assert(!sources.Ingest(&item,1000)&&sources.m_Messages.Count()==128); - item.SourceId=1;item.MessageId=2;item.ObservedAt=130; - assert(sources.Ingest(&item,1000)&&sources.m_Messages.Count()==128); + item.SourceId=257;item.ObservedAt=257; + assert(!sources.Ingest(&item,1000)&&sources.m_Messages.Count()==256); + item.SourceId=1;item.MessageId=2;item.ObservedAt=258; + assert(sources.Ingest(&item,1000)&&sources.m_Messages.Count()==256); // Nearest unswept candidates remain inside uncertainty, including a small circle. Coverage search;vector center{250,12,250},destination; assert(search.Select(center,25,{1000,0,250},1000,destination)); diff --git a/tests/test_hq_delivered_task.py b/tests/test_hq_delivered_task.py index 6788dd8..605f8cf 100644 --- a/tests/test_hq_delivered_task.py +++ b/tests/test_hq_delivered_task.py @@ -13,7 +13,7 @@ def cpp(s): s=re.sub(r'foreach \((ERR_HQUnit\*) (\w+) : ([^)]+)\)',r'for (\1 \2 : \3)',s) for name in ('unit','other','task','planned','order','belief','record','mode','Group','hunt','m_Mode'): s=s.replace(name+'.',name+'->') - s=s.replace('ResourceName ', 'int ') + s=s.replace('ResourceName ', 'int ').replace('.IsEmpty()', '.empty()') s=s.replace('PendingTask.', 'PendingTask->').replace('Task.', 'Task->') s=s.replace('Downlink.', 'Downlink->').replace('Forces().','Forces()->').replace('ERR_ForceRecord* record;','ERR_ForceRecord* record=nullptr;') return s @@ -39,7 +39,7 @@ struct ERR_HQPursuitRules{ '''+rules+r''' }; struct Math{static float Min(float a,float b){return std::min(a,b);}}; -struct ERR_HQTask{bool RoadIntercept=false,ReleaseOnly=false;ERR_HQTask* ReplacesTask=nullptr;string WatchSourceId;int WatchMessageId=0,WatchRequestId=0; +struct ERR_HQTask{string SecuritySite;bool RoadIntercept=false,ReleaseOnly=false;ERR_HQTask* ReplacesTask=nullptr;string WatchSourceId;int WatchMessageId=0,WatchRequestId=0; int BeliefId=1,BeliefRevision=2,Role=0;vector Destination{40,0,50};float QueuedAt=0,ExpiresAt=60000;bool Investigation(){return !WatchSourceId.empty();}string Name(){return "search";}}; struct ERR_HQReport{int MessageId=10;float ObservedAt=0;}; struct ERR_HQRoute{int MessageId=20;}; @@ -116,6 +116,11 @@ int main(){ assert(ERR_Actors::spawns==1&&f.unit.Waypoint&&f.unit.Waypoint->resource==2&&f.unit.Task==&f.next&&f.previous.deletes==1); f.hq.DeliverOrder(&f.unit,45001);assert(ERR_Actors::spawns==1&&f.group.additions==1); f.hq.Cleanup(60000,1,4);assert(!f.unit.Task&&!f.unit.Waypoint&&f.mode.ledger.record.Duty==f.mode.ledger.record.HomeDuty);} + // Security orders carry an inspected-site hypothesis, not a fabricated enemy track. + {Fixture f;f.next.SecuritySite="mortar-1";f.next.BeliefId=999; + f.hq.DeliverOrder(&f.unit,1000);assert(f.unit.Task==&f.next&&f.unit.Waypoint->resource==2); + f.hq.Cleanup(1001,1,4);assert(f.unit.Task==&f.next); + f.hq.Cleanup(60000,1,4);assert(!f.unit.Task&&!f.unit.Waypoint);} // Cancelling a mismatched recall never releases a replacement task which arrived first. {Fixture f;f.next.ReleaseOnly=true;f.next.ReplacesTask=nullptr;f.hq.DeliverOrder(&f.unit,1000);f.Retained();assert(ERR_Actors::spawns==0);} {Fixture f;f.next.ReleaseOnly=true;f.next.ReplacesTask=&f.active;f.hq.DeliverOrder(&f.unit,1000);assert(!f.unit.Task&&!f.unit.Assignment&&!f.unit.Waypoint&&f.previous.deletes==1&&ERR_Actors::spawns==0);} diff --git a/tests/test_hq_local_handoff_intake.py b/tests/test_hq_local_handoff_intake.py index b89e649..fd4eaff 100644 --- a/tests/test_hq_local_handoff_intake.py +++ b/tests/test_hq_local_handoff_intake.py @@ -11,7 +11,7 @@ for name in ('unit','other','route','own','seen','report'): s=s.replace(name+'.',name+'->') for name in ('Uplink','Task'): s=s.replace(name+'.',name+'->') -s=s.replace('Nodes[0].','Nodes[0]->').replace('m_Mode.Settings().Get','m_Mode->Settings()->Get').replace('ERR_HQObservation.','ERR_HQObservation::').replace('null','nullptr') +s=s.replace('Nodes[0].','Nodes[0]->').replace('m_Mode.Settings().Runtime','m_Mode->Settings()->Runtime').replace('ERR_HQObservation.','ERR_HQObservation::').replace('null','nullptr') s=s.replace('ERR_HQRoute* own;','ERR_HQRoute* own=nullptr;').replace('ERR_HQRoute* route;','ERR_HQRoute* route=nullptr;') run(r''' #include @@ -30,7 +30,7 @@ struct ERR_HQObservation{static void Gather(Utility*u,float,Arr&s){return s[0];}void Queued(IEntity){queues++;}}; struct History{IEntity target=nullptr;float time=-1;bool CanQueue(IEntity t,float at,float){return t&&!(t==target&&at<=time);}void Queued(IEntity t,float at,float){target=t;time=at;}}; struct ERR_HQReport{int MessageId=0,Position=0;IEntity Target=nullptr;Group*Source=nullptr;float ObservedAt=0;string Description(float){return "unaltered source sighting";}}; -struct Settings{int Get(string){return 5;}}; +struct Settings{int Runtime(string){return 5;}}; struct Mode{struct Settings values;struct Settings*Settings(){return &values;}}; struct Task{float ArrivedAt=0;}; struct ERR_HQUnit{struct Group*Group=nullptr;struct Utility*Utility=nullptr;IEntity Radio=nullptr;float NextReport=0;ERR_HQRoute*Uplink=nullptr;ERR_HQReport*PendingReport=nullptr;Selector ReportSelection;History SentObservations;int StatusSampler=1;struct Task*Task=nullptr;}; diff --git a/tests/test_hq_uplink_fairness.py b/tests/test_hq_uplink_fairness.py index af4afa3..c27020e 100644 --- a/tests/test_hq_uplink_fairness.py +++ b/tests/test_hq_uplink_fairness.py @@ -19,10 +19,10 @@ def cpp(s): s=s.replace(v+'.',v+'->') for v in ('Utility','ReportSelection','StatusSampler','Group','Task'): s=s.replace('->'+v+'.','->'+v+'->') - s=s.replace('m_Mode.Settings().Get(', 'm_Mode->Settings()->Get(') + s=s.replace('m_Mode.Settings().Runtime(', 'm_Mode->Settings()->Runtime(') s=s.replace('ERR_HQPursuitRules.', 'ERR_HQPursuitRules::') s=s.replace('ERR_HQObservation.','ERR_HQObservation::').replace('vector.DistanceXZ','vector::DistanceXZ').replace('string.Format','Format') - return s.replace('AmmoState.', 'AmmoState->') + return s.replace('AmmoState.', 'AmmoState->').replace('SecuritySite.IsEmpty()', 'SecuritySite.empty()') policy_path=Path(os.environ.get('ERR_AMMO_REPORTING_ROOT', ROOT))/'addons/core/Scripts/Game/ERR/10_AI/ERR_HQAmmoReporting.c' policy=cpp(policy_path.read_text()).replace('class ERR_HQAmmoReporting','struct ERR_HQAmmoReporting').rstrip()+';' methods='\n'.join(cpp(body(P,s)) for s in ('protected void Observe(', 'protected void ObserveBody(', 'protected void StatusReport(', 'protected void Sweep(', 'protected void QueueReports(')) @@ -36,7 +36,7 @@ templatestring Format(T... args){return "diagnostic";} struct vector{float x=0,z=0;static float DistanceXZ(vector a,vector b){return std::hypot(a.x-b.x,a.z-b.z);}}; templatestruct Array:std::vector{bool IsEmpty(){return this->empty();}}; struct Group{vector position;vector GetOrigin(){return position;}}; -struct Settings{int interval=5;int Get(string){return interval;}}; +struct Settings{int interval=5;int Runtime(string){return interval;}}; struct Mode{struct Settings settings;struct Settings* Settings(){return &settings;}}; struct ERR_HQVisualContact{void* Entity=this;vector Position;float ObservedAt=0;}; struct Utility{bool visible=true;}; @@ -55,7 +55,7 @@ struct Sampler{int observations=0,samples=0;bool valid=true;void ObserveDeaths() ERR_HQStatusReport* Sample(float now,int id,void*){samples++;if(!valid)return nullptr;auto r=new ERR_HQStatusReport;r->MessageId=id;r->ObservedAt=now;return r;}}; struct ERR_HQSearchReport{int SourceId=0,MessageId=0,WatchMessageId=0,WatchRequestId=0,BeliefId=0,BeliefRevision=0; string WatchSourceId;vector Position;float ObservedAt=0;bool SweepCompleted=false,ContactFound=false;}; -struct ERR_HQTask{bool RoadIntercept=false,SweepQueued=false;float ArrivedAt=-1;vector Destination; +struct ERR_HQTask{std::string SecuritySite;bool RoadIntercept=false,SweepQueued=false;float ArrivedAt=-1;vector Destination; string WatchSourceId;int WatchMessageId=0,WatchRequestId=0,BeliefId=1,BeliefRevision=2;}; struct ERR_HQRoute{Group* LocalSource=nullptr;int MessageId=0;string Payload;}; struct Network{bool available=true;int routes=0;ERR_HQRoute* Route(void*){routes++;return available?new ERR_HQRoute:nullptr;}}; diff --git a/tests/test_hq_watch.py b/tests/test_hq_watch.py index b29d8fd..954b394 100644 --- a/tests/test_hq_watch.py +++ b/tests/test_hq_watch.py @@ -30,9 +30,9 @@ ammo=ammo.replace('class ','struct ').replace('ERR_HQAmmoSnapshot Snapshot(', 'E ammo=ammo.replace('ERR_HQAmmoSnapshot copy', 'ERR_HQAmmoSnapshot* copy').replace('copy.', 'copy->') ammo=re.sub(r'\b(bool|int) (\w+);',r'\1 \2=0;',ammo).replace('\n}\n','\n};\n') rules='\n'.join(cpp(body(P,s)) for s in ('static bool Valid(', 'static bool RequestDue(', - 'static bool InvestigationDue(', 'static int SquadLimit(')) + 'static bool InvestigationDue(', 'static int SquadLimit(', 'static int Aggression(', 'static int Hunters(')) methods='\n'.join(cpp(body(P,s)) for s in ('int Count()', 'ERR_HQWatchEntry Find(', 'ERR_HQWatchEntry At(', - 'int ConfirmedLosses()', 'int SquadLimit(int baseline)', 'bool ArmedSearchBlocked(', 'protected ERR_HQWatchEntry Create(', + 'int IdentifiedBodies()', 'int Aggression()', 'int HunterTarget()', 'int ConfirmedLosses()', 'int SquadLimit(int baseline)', 'bool ArmedSearchBlocked(', 'protected ERR_HQWatchEntry Create(', 'protected void ApplyLosses(', 'bool Ingest(', 'bool IngestBody(', 'bool RequestDue(string', 'bool MarkRequested(', 'bool InvestigationDue(string', 'bool MarkInvestigating(', 'bool FinishInvestigation(', 'void Clear(')) common='\n'.join(cpp(body(U,s)) for s in ('static bool Finite(', 'static bool PositionValid(')) @@ -72,7 +72,7 @@ struct ERR_HQPursuitRules{ }; '''+helper+ammo+r''' struct ERR_HQReport{ - string TravelMode="body",CasualtySourceId="patrol-1";bool Distress=false;int MessageId=99,CasualtySlot=0,CasualtyStrength=4; + string RoadStatus="road unknown"; string TravelMode="body",CasualtySourceId="patrol-1";bool Distress=false;int MessageId=99,CasualtySlot=0,CasualtyStrength=4; vector Position{900,30,900},Velocity;float ObservedAt=1000,DetailsObservedAt=-1; void* Target=nullptr;void* Source=nullptr;bool HasVelocity=false,Engaged=false; int SeenEscapists=-1;string SeenWeapons="unknown"; @@ -86,7 +86,7 @@ struct ERR_HQStatusReport{ struct ERR_HQWatchEntry{ string SourceId;int MessageId=0,RequestId=0;vector Position; ERR_HQAmmoSnapshot* AmmoState=nullptr; - int Strength=0,Count=-1,Fit=-1,ConfirmedLosses=0; + int Strength=0,Count=-1,Fit=-1,ConfirmedLosses=0;Array IdentifiedSlots; ERR_HQDeliveredCasualties* Casualties=new ERR_HQDeliveredCasualties();float LastBodyDeliveredAt=-1; float ObservedAt=-1,LastDeliveredAt=-1,AskedAt=-1,NextAttempt=0; bool Investigating=false,Closed=false; @@ -96,7 +96,7 @@ struct ERR_HQWatchRules{ }; struct Watch{ Arraym_Entries;Mapm_BySource; - int m_ConfirmedLosses=0;bool m_CapLogged=false; + int m_ConfirmedLosses=0,m_IdentifiedBodies=0;bool m_CapLogged=false; '''+methods+r''' }; struct ERR_MissionRules{static bool ContactFresh(float t,float now){return std::isfinite(t)&&std::isfinite(now)&&t>=0&&now>=t&&now-t<=120000;}}; @@ -106,9 +106,9 @@ struct MemoryAdapter{int attempts=0;bool Ingest(ERR_HQReport* r,float){attempts+ struct BodyAdapter{int confirmations=0;void ConfirmDelivered(void*){confirmations++;}}; struct CoverageAdapter{int forgotten=0;void Forget(vector){forgotten++;}}; struct JournalAdapter{void Write(string,string,int){}}; -string Format(string,int,int){return "delivered";} +template string Format(string,Args...){return "delivered";} struct HQDelivery{ - Watch m_Watch;MemoryAdapter m_Memory;BodyAdapter m_Bodies;CoverageAdapter m_Coverage;JournalAdapter m_Journal; + Watch m_Watch;MemoryAdapter m_Memory;BodyAdapter m_Bodies;struct RecoveryAdapter{int calls=0;void ReportBody(ERR_HQReport*){calls++;}} m_Recovery;CoverageAdapter m_Coverage;JournalAdapter m_Journal; Arraym_Contacts; '''+accept+r''' }; @@ -212,12 +212,12 @@ int main(){ assert(!watch.Ingest(&late,120001)&&watch.Ingest(&late,120000)); assert(!watch.RequestDue("late",nan)); Watch cap;ERR_HQStatusReport item;item.Count=0;item.Fit=0;item.ConfirmedLosses=4;item.DeathSlots={0,1,2,3}; - for(int i=0;i<128;i++){item.SourceId=std::to_string(i);assert(cap.Ingest(&item,1000));} - assert(cap.Count()==128&&cap.ConfirmedLosses()==512); + for(int i=0;i<256;i++){item.SourceId=std::to_string(i);assert(cap.Ingest(&item,1000));} + assert(cap.Count()==256&&cap.ConfirmedLosses()==1024); item.SourceId="overflow";assert(!cap.Ingest(&item,1000)); item.SourceId="overflow2";assert(!cap.Ingest(&item,1000)&&logs==1); item.SourceId="0";item.MessageId=2;item.ObservedAt=2000; - assert(cap.Ingest(&item,2000)&&cap.ConfirmedLosses()==512&&cap.Count()==128); + assert(cap.Ingest(&item,2000)&&cap.ConfirmedLosses()==1024&&cap.Count()==256); cap.Clear();assert(cap.Count()==0&&cap.ConfirmedLosses()==0&&!cap.Find("0")); // Delivered bodies merge exact original roster slots, never aggregate totals or body positions. Watch merged;ERR_HQStatusReport status;status.Count=3;status.Fit=2;status.ConfirmedLosses=1;status.DeathSlots={0}; @@ -234,9 +234,16 @@ int main(){ body.CasualtySlot=3;assert(merged.IngestBody(&body,4001)); assert(known->Closed&&known->Count==0&&known->Fit==0&&merged.ConfirmedLosses()==4); assert(known->MessageId==2&&known->ObservedAt==3000&&known->Position.x==200); - assert(merged.IngestBody(&body,4002)&&merged.ConfirmedLosses()==4); // replay or different observer + assert(!merged.IngestBody(&body,4002)&&merged.ConfirmedLosses()==4); // replay or different observer status.MessageId=3;status.ObservedAt=5000;assert(merged.Ingest(&status,5000)&&known->Closed); assert(!merged.RequestDue("patrol-1",999999)); + assert(merged.IdentifiedBodies()==4&&merged.Aggression()==1&&merged.HunterTarget()==1); + for(int bodies=0;bodies<=300;bodies++){ + assert(ERR_HQWatchRules::Aggression(bodies)==std::min(30,bodies/3)); + assert(ERR_HQWatchRules::Hunters(ERR_HQWatchRules::Aggression(bodies))==std::min(15,(bodies/3+1)/2)); + } + assert(ERR_HQWatchRules::Aggression(-10)==0&&ERR_HQWatchRules::Hunters(-10)==0); + merged.Clear();assert(merged.IdentifiedBodies()==0&&merged.HunterTarget()==0); // Exercise the actual HQ delivered-intake method and actual Report.Snapshot, including corpse deletion. HQDelivery intake;ERR_HQReport local;local.CasualtySourceId="deleted-during-uplink"; local.CasualtyStrength=1;local.CasualtySlot=0;local.Target=&local;local.MessageId=501; @@ -279,4 +286,4 @@ for forbidden in ('IEntity','SCR_AIGroup','GetGame(','GetOrigin(','GetPlayers(', 'GetControlledEntity(','Spawn(','CallLater(','ERR_HQMemory'): assert forbidden not in source,forbidden assert all(len(line)<120 for line in source.splitlines()) -print('PASS: delivered-only status snapshots, two missed check-ins/reply deadline, last reported coordinates, episode/replay guards, confirmed-loss idempotence and 128-record cap') +print('PASS: delivered-only status snapshots, two missed check-ins/reply deadline, last reported coordinates, episode/replay guards, confirmed-loss idempotence and 256-record cap') diff --git a/tests/test_hunter_lifecycle.py b/tests/test_hunter_lifecycle.py new file mode 100644 index 0000000..2f500f0 --- /dev/null +++ b/tests/test_hunter_lifecycle.py @@ -0,0 +1,44 @@ +"""Production hunter release and objective-role policy, without native spawning.""" +from policy_harness import ROOT, body, run +source=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_HunterService.c' +s=body(source,'override void Release(ERR_GameMode mode)') +s=s.replace('override ','').replace('super.','Native::').replace('null','nullptr') +s=s.replace('ERR_GameMode mode','ERR_GameMode* mode').replace('ERR_ForceRecord record','ERR_ForceRecord* record') +s=s.replace('ERR_HQ hq = ERR_HQ.Cast(mode.Command())', 'ERR_HQ* hq = mode->Command()') +s=s.replace('array agents = {};','Array agents;').replace('foreach (AIAgent agent : agents)','for (AIAgent* agent : agents)') +for name in ('mode','record','Group','agent','hq'):s=s.replace(name+'.',name+'->') +s=s.replace('Forces().','Forces()->').replace('ERR_ConvoyRules.','ERR_ConvoyRules::') +objective=body(ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_ObjectiveDefence.c','static bool Objective(').replace('ERR_LocationKind.','ERR_LocationKind::') +run(r''' +#include +#include +templateusing Array=std::vector; +struct AIAgent{int lod=0,writes=0;void SetPermanentLOD(int x){lod=x;writes++;}}; +struct GroupType{int lod=0;AIAgent agent;void SetPermanentLOD(int x){lod=x;}void GetAgents(Array& a){a={&agent};}}; +struct ERR_ForceRecord{bool Pinned=true;}; +struct Ledger{ERR_ForceRecord record;ERR_ForceRecord* FindGroup(GroupType*){return &record;}}; +struct ERR_HQ{int releases=0;void ReleaseRecovery(GroupType*){releases++;}}; +struct ERR_GameMode{bool active=true;Ledger ledger;ERR_HQ hq;bool Active(){return active;}Ledger* Forces(){return &ledger;}ERR_HQ* Command(){return &hq;}}; +namespace ERR_ConvoyRules{bool captured=false;bool Captured(void*,GroupType*){return captured;}} +struct Native{bool Released=false;int delegated=0,clears=0;GroupType* Group=nullptr;void* Entity=nullptr;void* Downlink=nullptr; + void Release(ERR_GameMode*){delegated++;Released=true;}void ClearOrder(){clears++;} +}; +struct Hunter:Native{ +'''+s+r''' +}; +namespace ERR_LocationKind{enum{PRISON,RADIO,EXTRACTION,PATROL,DEPOT,OUTPOST,MORTAR};} +'''+objective+r''' +int main(){ + ERR_GameMode mode;GroupType group;Hunter unit;unit.Group=&group;unit.Entity=&group;unit.Downlink=&mode; + unit.Release(&mode);assert(unit.Released&&!unit.Downlink&&unit.clears==1&&unit.delegated==0); + assert(!mode.ledger.record.Pinned&&mode.hq.releases==1&&group.lod==-1&&group.agent.writes==1); + assert(unit.Entity==&group&&unit.Group==&group); // living and dead actors/vehicle are preserved + unit.Release(&mode);assert(unit.clears==1&&mode.hq.releases==1&&group.agent.writes==1); + Hunter captured;ERR_ConvoyRules::captured=true;captured.Release(&mode);assert(captured.delegated==1&&mode.hq.releases==1); + ERR_ConvoyRules::captured=false;Hunter stopped;mode.active=false;stopped.Release(&mode);assert(stopped.delegated==1); + Hunter missing;missing.Release(nullptr);assert(missing.delegated==1); + assert(Objective(ERR_LocationKind::RADIO)&&Objective(ERR_LocationKind::DEPOT)&&Objective(ERR_LocationKind::OUTPOST)&&Objective(ERR_LocationKind::EXTRACTION)); + assert(!Objective(ERR_LocationKind::PRISON)&&!Objective(ERR_LocationKind::PATROL)&&!Objective(ERR_LocationKind::MORTAR)); +} +''') +print('PASS: actual hunter release preserves survivors/HQ, releases driving ownership once, delegates capture/teardown, and excludes prison/patrol/mortar from generic objective defence') diff --git a/tests/test_infantry_ammo_access.py b/tests/test_infantry_ammo_access.py index de67cd5..4f927a1 100644 --- a/tests/test_infantry_ammo_access.py +++ b/tests/test_infantry_ammo_access.py @@ -56,15 +56,17 @@ int main(){ storage.owner=&otherTruck;assert(!access.Check(&truck,&actor));storage.owner=&truck; BaseUserAction door;door.owner=&truck;context.actions={&door};assert(!access.Check(&truck,&actor));context.actions={&storage}; manager.enabled=false;assert(!access.Check(&truck,&actor));manager.enabled=true; - // Stock Ural defines 36 root contexts and ammo adds one: a valid storage action near the end must remain discoverable. - for(int count:{37,64}){ + // Stock Ural has 37 contexts and Mi-8 has 82: a valid storage action near the end must remain discoverable. + for(int count:{37,64,82,128}){ std::vector stockContexts(count);manager.contexts.clear(); for(auto& authored:stockContexts){authored.actions={&door};manager.contexts.push_back(&authored);} stockContexts.back().actions={&storage}; assert(ERR_InfantryAmmoAccess::Points(&truck,points)&&points.Count()==1&&access.Check(&truck,&actor)); } - manager.contexts.clear();manager.contexts.resize(65,&context);assert(!access.Check(&truck,&actor));manager.contexts={&context}; - context.actions.resize(17,&storage);assert(!access.Check(&truck,&actor));context.actions={&storage}; + manager.contexts.clear();manager.contexts.resize(129,&context);assert(!access.Check(&truck,&actor));manager.contexts={&context}; + // Native helicopter door contexts include 38 actions, most unrelated to storage. + for(int count:{33,38,64}){context.actions.clear();context.actions.resize(count,&door);context.actions.back()=&storage;assert(access.Check(&truck,&actor));} + context.actions.resize(65,&storage);assert(!access.Check(&truck,&actor));context.actions={&storage}; manager.contexts={nullptr};assert(!access.Check(&truck,&actor));manager.contexts={&context}; assert(!access.Check(&truck,&wall));assert(!access.Check(nullptr,&actor)); // A blocked context never skips an intervening external entity; another independently clear authored context may qualify. diff --git a/tests/test_infantry_ammo_transfer.py b/tests/test_infantry_ammo_transfer.py index df10801..b781130 100644 --- a/tests/test_infantry_ammo_transfer.py +++ b/tests/test_infantry_ammo_transfer.py @@ -10,6 +10,7 @@ callback=s[s.index('class ERR_InfantryAmmoCallback'):s.index('// One exact physi 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', 'BaseMagazineComponent.Cast(exactMagazine.FindComponent(BaseMagazineComponent))':'exactMagazine->magazine', 'BaseWeaponManagerComponent.Cast(actor.FindComponent(BaseWeaponManagerComponent))':'actor->weapons', 'BaseWeaponComponent.Cast(rifle.FindComponent(BaseWeaponComponent))':'rifle->weapon', @@ -78,7 +79,7 @@ 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 alive=true,awake=true,player=false,captured=false;int faction=1;Group*group=nullptr;IEntity vehicle=nullptr,parent=nullptr; +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;}; diff --git a/tests/test_intel_body_inspection.py b/tests/test_intel_body_inspection.py new file mode 100644 index 0000000..c5cb83f --- /dev/null +++ b/tests/test_intel_body_inspection.py @@ -0,0 +1,88 @@ +"""Execute the production physical body-inspection gate; engine traces are boundary doubles.""" +from policy_harness import ROOT, body, run +import re +p=ROOT/'addons/core/Scripts/Game/ERR/20_Intel/ERR_IntelEvidence.c' +s='\n'.join(body(p,sig) for sig in ('bool Inspect(', 'bool RetainedWithin(', 'void Delivered(', 'void Release(')) +for old,new in [('out array missing','Array& missing'),('array','Array'),('array','Array'),('foreach (','for ('),('ERR_BodyEvidence record','ERR_BodyEvidence* record'),('ERR_IssuedIntel issued','ERR_IssuedIntel* issued'),('TraceParam trace','TraceParam* trace'),('InventoryStorageManagerComponent inventory','InventoryStorageManagerComponent* inventory'),('SCR_GarbageSystem garbage','SCR_GarbageSystem* garbage'),('null','nullptr')]:s=s.replace(old,new) +s=s.replace('InventoryStorageManagerComponent.Cast(body.FindComponent(InventoryStorageManagerComponent))','body->inventory') +for cls in ('Replication','ERR_GameMode','ERR_Actors','CompartmentAccessComponent','vector','TraceFlags','ERR_DiscoveryService','SCR_GarbageSystem'): + s=s.replace(cls+'.',cls+'::') +s=s.replace('parent.GetParent()', 'parent->GetParent()') +for v in ('body','observer','record','issued','trace','garbage'): + s=s.replace(v+'.',v+'->') +s=s.replace('ERR_GameMode::Get().','ERR_GameMode::Get()->').replace('GetGame().GetWorld().','GetGame()->GetWorld()->') +run(r''' +#include +#include +#include +#include +#include +using string=std::string; +templatestruct Array:std::vector{using std::vector::vector;void Clear(){this->clear();}bool Contains(T t){return std::find(this->begin(),this->end(),t)!=this->end();}void Insert(T t){this->push_back(t);}}; +struct vector {float x=0,y=0,z=0;vector()=default;vector(float a,float b,float c):x(a),y(b),z(c){}vector(const char*){}vector operator+(vector v){return {x+v.x,y+v.y,z+v.z};}static float Distance(vector a,vector b){return std::hypot(std::hypot(a.x-b.x,a.y-b.y),a.z-b.z);}}; +struct Entity;using IEntity=Entity*; +struct InventoryStorageManagerComponent{Array folders;}; +struct Entity{IEntity parent=nullptr;IEntity GetParent(){return parent;}bool alive=true,fit=true,player=false,seated=false;InventoryStorageManagerComponent* inventory=nullptr;vector position;vector GetOrigin(){return position;}}; +struct ERR_Actors{static bool Alive(IEntity e){return e&&e->alive;}static bool CanFight(IEntity e){return e&&e->alive&&e->fit;}static bool Player(IEntity e){return e&&e->player;}}; +struct CompartmentAccessComponent{static bool GetVehicleIn(IEntity e){return e->seated;}}; +struct TraceFlags{enum{ENTS=1,WORLD=2};};struct TraceParam{vector Start,End;IEntity Exclude=nullptr,TraceEnt=nullptr;int Flags=0;}; +struct World{float fraction=1;IEntity hit=nullptr;float TraceMove(TraceParam* t,void*){t->TraceEnt=hit;return fraction;}}; +struct Game{World world;World* GetWorld(){return &world;}} game;Game* GetGame(){return &game;} +struct Replication{inline static bool server=true;static bool IsServer(){return server;}}; +struct ERR_GameMode{bool active=true;static ERR_GameMode* Get(){static ERR_GameMode mode;return &mode;}bool Active(){return active;}}; +struct ERR_DiscoveryService{static void Folders(InventoryStorageManagerComponent* inv,Array& folders){folders=inv->folders;}}; +struct ERR_IssuedIntel{IEntity Folder;string SiteId;}; +struct ERR_BodyEvidence{IEntity Actor;Array Issued;bool Searched=false;bool Reported=false;}; +struct SCR_GarbageSystem { + inline static int releases=0,inserts=0;inline static bool blacklisted=true;inline static float delay=0; + static SCR_GarbageSystem* GetByEntityWorld(IEntity){static SCR_GarbageSystem g;return &g;} + void UpdateBlacklist(IEntity,bool value){blacklisted=value;releases++;} + void Insert(IEntity,float value){assert(!blacklisted);inserts++;delay=value;} +}; +struct Evidence{Array m_Roster;bool m_Stopped=false;ERR_BodyEvidence* record=nullptr;ERR_BodyEvidence* Find(IEntity b){return record&&record->Actor==b?record:nullptr;} +'''+s+r''' +}; +int main(){ + for(int invalid=0;invalid<9;invalid++){ + Entity body,observer,folder;body.alive=false;InventoryStorageManagerComponent inventory;body.inventory=&inventory; + ERR_IssuedIntel issued{&folder,"radio-1"};ERR_BodyEvidence record{&body,{&issued},false};Evidence service;service.record=&record;Array result; + game.world.fraction=1;Replication::server=true;ERR_GameMode::Get()->active=true; + if(invalid==0)Replication::server=false; + if(invalid==1)service.m_Stopped=true; + if(invalid==2)body.alive=true; + if(invalid==3)observer.player=true; + if(invalid==4)observer.fit=false; + if(invalid==5)observer.seated=true; + if(invalid==6)observer.position={3.01f,0,0}; + if(invalid==7)game.world.fraction=.5; + if(invalid==8)body.inventory=nullptr; + assert(!service.Inspect(&body,&observer,result)&&!record.Searched&&result.empty()); + } + Replication::server=true;game.world.fraction=1; + Entity body,observer,present,missing;body.alive=false;InventoryStorageManagerComponent inv;body.inventory=&inv;inv.folders.Insert(&present); + ERR_IssuedIntel a{&present,"radio-1"},b{&missing,"mortar-3"},c{nullptr,"depot-1"};ERR_BodyEvidence record{&body,{&a,&b,&c},false};Evidence service;service.record=&record;Array result; + observer.position={3,0,0};assert(service.Inspect(&body,&observer,result));assert(result.size()==2&&result.Contains("mortar-3")&&result.Contains("depot-1")&&!result.Contains("radio-1")); + assert(!service.Inspect(&body,&observer,result)); + Entity wreck,seat,unrelated;body.parent=&seat;seat.parent=&wreck;service.m_Roster={&record}; + assert(service.RetainedWithin(&body)&&service.RetainedWithin(&seat)&&service.RetainedWithin(&wreck)); + assert(!service.RetainedWithin(&unrelated)&&!service.RetainedWithin(nullptr)); + body.alive=true;assert(!service.RetainedWithin(&wreck));body.alive=false; + record.Reported=true;assert(!service.RetainedWithin(&wreck));record.Reported=false; + service.m_Stopped=true;assert(!service.RetainedWithin(&wreck));service.m_Stopped=false; + // Searching protects the body until HQ receives the report. Premature, + // client-side, stopped and repeated deliveries never release/renew cleanup. + record.Searched=false;service.Delivered(&body);assert(!record.Reported&&SCR_GarbageSystem::inserts==0); + record.Searched=true;Replication::server=false;service.Delivered(&body);assert(!record.Reported); + Replication::server=true;service.m_Stopped=true;service.Delivered(&body);assert(!record.Reported); + service.m_Stopped=false;service.Delivered(&unrelated);assert(!record.Reported); + assert(service.RetainedWithin(&body));service.Delivered(&body); + assert(record.Reported&&!service.RetainedWithin(&body)); + assert(SCR_GarbageSystem::inserts==1&&SCR_GarbageSystem::releases==1&&SCR_GarbageSystem::delay==300); + service.Delivered(&body);assert(SCR_GarbageSystem::inserts==1&&SCR_GarbageSystem::releases==1); + record.Reported=false; + // Corrupt/cyclic parent links cannot cause unbounded cleanup traversal. + seat.parent=&seat;assert(!service.RetainedWithin(&wreck)); + +} +''') +print('PASS: physical inspection and parent-wreck retention; server-only searched/report delivery unlocks native cleanup once with a 300-second delay') diff --git a/tests/test_intel_discovery_feedback.py b/tests/test_intel_discovery_feedback.py index c33469a..935fbbb 100644 --- a/tests/test_intel_discovery_feedback.py +++ b/tests/test_intel_discovery_feedback.py @@ -15,28 +15,28 @@ def cpp(s): s=s.replace('OnTick().Remove(ERR_FlushDiscoveryFeedback);','OnTick().Remove(0);') s=s.replace('string.Format(', 'Format(') return s -methods='\n'.join(cpp(body(P,s)) for s in ('protected void ERR_QueueDiscoveryFeedback(', 'protected void ERR_FlushDiscoveryFeedback(', 'protected void ERR_ReceiveDiscoveryFeedback(', 'protected void ERR_StopDiscoveryFeedback(')) +methods='\n'.join(cpp(body(P,s)) for s in ('protected void ERR_QueueDiscoveryFeedback(', 'protected void ERR_FlushDiscoveryFeedback(', 'protected void ERR_ReceiveDiscoveryFeedback(', 'protected void ERR_StopDiscoveryFeedback(', 'void ERR_IntelExhausted(')) run(r''' #include #include #include #include -struct string:std::string {using std::string::string;using std::string::operator=;string(std::string s):std::string(s){}bool IsEmpty()const{return empty();}}; +struct string:std::string {using std::string::string;using std::string::operator=;string(std::string s):std::string(s){}bool IsEmpty()const{return empty();}bool Contains(const char* text)const{return find(text)!=npos;}}; string Format(string text,int identified,int rough){text.replace(text.find("%1"),2,std::to_string(identified));text.replace(text.find("%2"),2,std::to_string(rough));return text;} struct Replication {static bool server;static bool IsServer(){return server;}};bool Replication::server=true; struct SCR_Global {static bool edit;static bool IsEditMode(){return edit;}};bool SCR_Global::edit=false; struct SCR_ChatComponent {static std::vector messages;static void RadioProtocolMessage(string text){messages.push_back(text);}};std::vector SCR_ChatComponent::messages; struct Math {static float Max(float a,float b){return a>b?a:b;}}; namespace ERR_Phase {enum {PREPARING,PRISON,RADIO_SEARCH,EXTRACTION};} -namespace ERR_LocationKind {enum {PRISON,RADIO,EXTRACTION,OUTPOST,DEPOT};} -struct ERR_LocationComponent {int kind=ERR_LocationKind::OUTPOST,knowledge=1;string label="Hidden outpost";int Kind(){return kind;}int Knowledge(){return knowledge;}string Label(){return label;}}; +namespace ERR_LocationKind {enum {PRISON,RADIO,EXTRACTION,OUTPOST,DEPOT,MORTAR};} +struct ERR_LocationComponent {int kind=ERR_LocationKind::OUTPOST,knowledge=1;string label="Hidden outpost";int Kind(){return kind;}int Knowledge(){return knowledge;}string Label(){return label;}string Id(){return "outpost-id";}}; template struct Map {std::map values;bool Find(K k,V& v){auto i=values.find(k);if(i==values.end())return false;v=i->second;return true;}bool Contains(K k){return values.count(k);}int Count(){return values.size();}bool IsEmpty(){return values.empty();}void Set(K k,V v){values[k]=v;}void Clear(){values.clear();}}; struct World {float time=0;float GetWorldTime(){return time;}} world; struct Game {bool controller=true;bool GetPlayerController(){return controller;}} game; Game* currentGame=&game;Game* GetGame(){return currentGame;} struct Events {int removes=0;void Remove(int){removes++;}}; struct ERR_IntelDiscoveryText {static -'''+cpp(body(P,'static string Message('))+r''' +'''+cpp(body(P,'static string Type('))+'static '+cpp(body(P,'static string Message('))+r''' }; struct ERR_GameMode { static ERR_GameMode* current;static ERR_GameMode* Get(){return current;} @@ -57,14 +57,14 @@ int main(){ m.ERR_QueueDiscoveryFeedback(nullptr,0,1);m.ERR_QueueDiscoveryFeedback(&site,1,1);m.ERR_QueueDiscoveryFeedback(&site,0,2);m.ERR_QueueDiscoveryFeedback(&site,-1,1);assert(m.m_ERRIntelPending.IsEmpty()); // Rough clues do not disclose labels, kinds or coordinates. Listen callbacks dedupe. m.ERR_QueueDiscoveryFeedback(&site,0,1);m.ERR_FlushDiscoveryFeedback(1499);assert(SCR_ChatComponent::messages.empty()); - m.ERR_FlushDiscoveryFeedback(1500);assert(m.rpcCount==1&&SCR_ChatComponent::messages.size()==1);assert(SCR_ChatComponent::messages.back().find("Hidden")==string::npos);assert(SCR_ChatComponent::messages.back().find("500 m")!=string::npos); + m.ERR_FlushDiscoveryFeedback(1500);assert(m.rpcCount==1&&SCR_ChatComponent::messages.size()==1);assert(SCR_ChatComponent::messages.back().find("Hidden")==string::npos);assert(SCR_ChatComponent::messages.back().find("New location marked. Type unknown.")!=string::npos); m.ERR_QueueDiscoveryFeedback(&site,0,1);assert(m.m_ERRIntelPending.IsEmpty()); site.knowledge=2;world.time=2000;m.ERR_QueueDiscoveryFeedback(&site,1,2);m.ERR_FlushDiscoveryFeedback(6499);assert(m.rpcCount==1); - m.ERR_FlushDiscoveryFeedback(6500);assert(m.rpcCount==2&&SCR_ChatComponent::messages.back().find("Hidden outpost")!=string::npos); + m.ERR_FlushDiscoveryFeedback(6500);assert(m.rpcCount==2&&SCR_ChatComponent::messages.back()=="Hey! A outpost was identified in the intel!"); // A same-batch rough→exact update becomes one final identified location. ERR_GameMode batch;ERR_GameMode::current=&batch;ERR_LocationComponent a,b;world.time=0; batch.ERR_QueueDiscoveryFeedback(&a,0,1);a.knowledge=2;batch.ERR_QueueDiscoveryFeedback(&a,1,2);batch.ERR_QueueDiscoveryFeedback(&b,0,1);batch.ERR_FlushDiscoveryFeedback(1500); - assert(SCR_ChatComponent::messages.back().find("1 identified locations and 1 search areas")!=string::npos); + assert(SCR_ChatComponent::messages.back().find("Hey! A outpost was identified in the intel!")!=string::npos && SCR_ChatComponent::messages.back().find("New location marked. Type unknown.")!=string::npos); // End/restart cancels pending output and removes both hooks, new mode is clean. world.time=2000;b.knowledge=2;batch.ERR_QueueDiscoveryFeedback(&b,1,2);batch.ERR_StopDiscoveryFeedback();assert(batch.m_ERRIntelSeen.IsEmpty()&&batch.m_ERRIntelPending.IsEmpty()&&batch.discovered.removes==1&&batch.tick.removes==1); int calls=batch.rpcCount;batch.ERR_FlushDiscoveryFeedback(99999);batch.ERR_QueueDiscoveryFeedback(&b,0,2);assert(batch.rpcCount==calls&&batch.m_ERRIntelPending.IsEmpty()); @@ -76,7 +76,9 @@ int main(){ next.ERR_ReceiveDiscoveryFeedback(2,"new");assert(SCR_ChatComponent::messages.size()==shown+2); // Queue is bounded even for malformed/unusually large authored scenarios. Replication::server=true;ERR_GameMode bounded;ERR_GameMode::current=&bounded;ERR_LocationComponent many[65];for(auto& item:many)bounded.ERR_QueueDiscoveryFeedback(&item,0,1);assert(bounded.m_ERRIntelSeen.Count()==64&&bounded.m_ERRIntelPending.Count()==64); - assert(ERR_IntelDiscoveryText::Message(0,0,"secret").empty());assert(ERR_IntelDiscoveryText::Message(1,0,"")=="A location identified. Check your field map."); + assert(ERR_IntelDiscoveryText::Type(ERR_LocationKind::MORTAR,"any")=="mortar site"); + ERR_GameMode::current=&m;m.ERR_IntelExhausted();assert(SCR_ChatComponent::messages.back()=="Every known location has already been identified. This intel doesn't help us."); + assert(ERR_IntelDiscoveryText::Message(0,0,"secret").empty());assert(ERR_IntelDiscoveryText::Message(1,0,"")=="Hey! A location was identified in the intel!"); } ''') for required in ('OnLocationDiscovered().Insert(ERR_QueueDiscoveryFeedback)', 'OnTick().Insert(ERR_FlushDiscoveryFeedback)', 'OnStop().Insert(ERR_StopDiscoveryFeedback)', '[RplRpc(RplChannel.Reliable, RplRcver.Broadcast)]'): diff --git a/tests/test_intel_registration.py b/tests/test_intel_registration.py index 0e0c73f..41dd1d2 100644 --- a/tests/test_intel_registration.py +++ b/tests/test_intel_registration.py @@ -10,9 +10,9 @@ def adapt(s): s=s.replace('override ', '').replace('protected ', '').replace('null','nullptr') s=re.sub(r'array<([^>]+)> (\w+) = \{\};',r'Array<\1> \2;',s) s=re.sub(r'foreach \((\w+) (\w+) : ([^)]+)\)',r'for (\1 \2 : \3)',s) - for n in ('Replication','ERR_Actors','Math','ERR_Resources','ERR_DiscoveryService','SCR_InventoryStorageManagerComponent','SCR_AIGroupUtilityComponent','ERR_MortarSupplyState'): + for n in ('Replication','ERR_Actors','Math','ERR_Resources','ERR_DiscoveryService','SCR_InventoryStorageManagerComponent','SCR_AIGroupUtilityComponent','ERR_MortarSupplyState','ERR_LocationKind','ERR_ObjectiveDefence'): s=s.replace(n+'.',n+'::') - for n in ('group','member','actor','request','inventory','known','unit','m_Mode','m_Battery','mode','m_Reroll','home','sites','record','m_Mortars'): + for n in ('group','member','actor','request','inventory','known','unit','m_Mode','m_Battery','mode','m_Reroll','home','sites','record','m_Mortars','m_Scouts','m_Recon','m_Airfield'): s=s.replace(n+'.',n+'->') s=s.replace('Actor.FindComponent(', 'Actor->FindComponent(').replace('SCR_InventoryStorageManagerComponent inventory', 'SCR_InventoryStorageManagerComponent* inventory').replace('SCR_AIGroupUtilityComponent utility', 'SCR_AIGroupUtilityComponent* utility') s=s.replace('home->Definition.', 'home->Definition->').replace('Patrol.IsEmpty()', 'Patrol->IsEmpty()').replace('unit->StatusSampler.Bind(', 'unit->StatusSampler.Bind(') @@ -24,7 +24,7 @@ def adapt(s): s=s.replace('ERR_IntelRequest request = new ERR_IntelRequest();','ERR_IntelRequest request = new Request();') s=s.replace('ERR_HQUnit unit = new ERR_HQUnit();','ERR_HQUnit unit = new Unit();') s=re.sub(r'^.*(?:Print|m_Journal.Write)\([^\n]*$', ';',s,flags=re.M) - return s + return s.replace('Evidence().','Evidence()->').replace('Cargo().','Cargo()->') register=adapt(body(intel,'void RegisterGroup('));tick=adapt(body(intel,'void Tick('));hqregister=adapt(body(hq,'override void RegisterGroup('));hqbind=adapt(body(hq,'protected void BindPhysical(')) observation=adapt(body(intel,'bool ERR_ProbeWasRolled(')) poll=body(ready,'ERR_MortarSupplyState Poll(') @@ -37,7 +37,7 @@ assert poll.index('if (m_Ready) return') < poll.index('mode.RegisterGroup(group) for condition in ('if (!operation.Finished)', 'if (!operation.Succeeded)', 'if (population == ERR_MortarSupplyState.FAILED)', 'if (population == ERR_MortarSupplyState.PENDING)'): assert poll.index(condition)& a){a.clear();if(i->folder)a.Insert(nullptr);}} struct Utility{static Utility* Cast(void* p){return static_cast(p);}};using SCR_AIGroupUtilityComponent=Utility; struct Group{Array members;Utility utility;int faction=1;void GetAgents(Array& out){out=members;}void* FindComponent(){return &utility;}int GetFaction(){return faction;}};using SCR_AIGroup=Group*; -struct Settings{int chance=100;int Get(const char*){return chance;}}; -struct Definition{string Id="site-a";Array* Patrol=nullptr;}; +struct Settings{int chance=100;int Runtime(const char*){return chance;}}; +namespace ERR_LocationKind {enum {RADIO=1};} +namespace ERR_ObjectiveDefence {bool Objective(int kind){return kind==1;}} +struct Definition{int Kind=3;string Id="site-a";Array* Patrol=nullptr;}; struct Site{struct Definition data;struct Definition* Definition=&data;};using ERR_SiteRuntime=Site*; struct Sites{Site home;Site* FindGroup(SCR_AIGroup){return &home;}};using ERR_SiteService=Sites*; struct ForceRecord{string SourceId="site-a";int InitialStrength=4;bool Physical=true,Eliminated=false;};using ERR_ForceRecord=ForceRecord*; struct Forces{ForceRecord record;bool available=false;ForceRecord* FindGroup(SCR_AIGroup){return available?&record:nullptr;}}; -struct Mode{struct Sites sites;struct Forces forces;struct Sites* Sites(){return &sites;}struct Forces* Forces(){return &forces;}struct Settings settings;int publications=0;struct Settings* Settings(){return &settings;}int EnemyFaction(){return 1;}void RegisterGroup(SCR_AIGroup);}; +struct EvidenceService{void Capture(IEntity){}void Retire(IEntity){}}; +struct Mode{EvidenceService evidence;EvidenceService* Evidence(){return &evidence;}struct Sites sites;struct Forces forces;struct Sites* Sites(){return &sites;}struct Forces* Forces(){return &forces;}struct Settings settings;int publications=0;struct Settings* Settings(){return &settings;}int EnemyFaction(){return 1;}bool IsMissionEnemy(int f){return f==1;}void RegisterGroup(SCR_AIGroup);}; struct Request{Callback* Operation=nullptr;IEntity Actor=nullptr;int Attempts=0;bool Accepted=false;};using ERR_IntelRequest=Request*; struct Reroll{void Tick(){}}; struct Intel{Mode* m_Mode;Array m_Requests;Set m_Rolled;bool m_Stopped=false;Reroll* m_Reroll=nullptr;void Unsettled(IEntity){} @@ -82,10 +85,13 @@ struct Sampler{bool Bound(){return bindings>0;}int bindings=0,strength=0;SCR_AIG struct GroupService{int registrations=0;Set seen;Array ids;Array fits; void RegisterGroup(SCR_AIGroup g,int radioId=0,bool fitRadios=true){ids.Insert(radioId);fits.Insert(fitRadios);if(!seen.Contains(g)){seen.Insert(g);registrations++;}}}; struct Mortars{SCR_AIGroup owned=nullptr;bool FindGroup(SCR_AIGroup group){return group&&group==owned;}}; +struct Scouts{SCR_AIGroup owned=nullptr;bool Contains(SCR_AIGroup group){return group&&group==owned;}}; +struct CargoFlight{SCR_AIGroup crew=nullptr;SCR_AIGroup Crew(){return crew;}};struct Airfield{CargoFlight* flight=nullptr;CargoFlight* Cargo(){return flight;}}; +struct Recon{SCR_AIGroup owned=nullptr;bool Owns(SCR_AIGroup group){return group&&group==owned;}}; struct BodyService:GroupService{void RegisterGroup(SCR_AIGroup g,Sampler& s){assert(s.Bound()&&s.group==g);GroupService::RegisterGroup(g);}}; struct Reporting{int initializations=0;void Initialize(int id,float now){assert(id>0&&now==10);initializations++;}}; -struct Unit{Reporting AmmoReporting;string HomeId,ForceSourceId;bool HomeGuard=false;float NextStatus=0;Sampler StatusSampler;int Id=0;SCR_AIGroup Group=nullptr;struct Utility* Utility=nullptr;float NextReport=0;};using ERR_HQUnit=Unit*; -struct HQ{Mode* m_Mode;GroupService m_Equipment;BodyService m_Bodies;int m_NextId=0;Array m_Units;Mortars* m_Mortars=nullptr; +struct Unit{Reporting AmmoReporting;string HomeId,ForceSourceId;bool ReservedForSupport=false;bool HomeGuard=false;float NextStatus=0;Sampler StatusSampler;int Id=0;SCR_AIGroup Group=nullptr;struct Utility* Utility=nullptr;float NextReport=0;};using ERR_HQUnit=Unit*; +struct HQ{void BindSpecialSkills(SCR_AIGroup){}void AuditGroup(ERR_HQUnit){}Mode* m_Mode;GroupService m_Equipment;BodyService m_Bodies;int m_NextId=0;Array m_Units;Mortars* m_Mortars=nullptr;Scouts* m_Scouts=nullptr;Recon* m_Recon=nullptr;Airfield* m_Airfield=nullptr; '''+hqbind+hqregister+r''' }; Intel* intel_;HQ* hq_; @@ -107,6 +113,7 @@ int main(){ battery.shells=27;assert(ready.Finish(&mode,&group)==1&&mode.publications==1&&Math::rolls==4&&intel.m_Requests.Count()==4); assert(hq.m_Units.Count()==1&&hq.m_NextId==1); assert(hq.m_Equipment.registrations==1&&hq.m_Bodies.registrations==1); + assert(!hq.m_Units[0]->ReservedForSupport); assert(hq.m_Units[0]->HomeGuard&&hq.m_Units[0]->HomeId=="site-a"&&hq.m_Units[0]->ForceSourceId=="site-a"); assert(hq.m_Units[0]->StatusSampler.bindings==1&&hq.m_Units[0]->StatusSampler.group==&group&&hq.m_Units[0]->StatusSampler.strength==4); for(Actor& a:actors){assert(intel.ERR_ProbeWasRolled(&a));}assert(!intel.ERR_ProbeWasRolled(nullptr));Actor unrelated;assert(!intel.ERR_ProbeWasRolled(&unrelated)); @@ -133,6 +140,9 @@ int main(){ assert(hq.m_Equipment.ids.Count()==3&&hq.m_Equipment.ids[2]==hq.m_Units[2]->Id&&hq.m_Equipment.ids[2]==3&&hq.m_Equipment.fits[2]); // A subsequent missing mortar registry cannot reroll an already bound group's opt-out. hq.RegisterGroup(&group);assert(hq.m_Equipment.ids.Count()==3&&!hq.m_Equipment.fits[0]&&hq.m_NextId==3); + Group radioGuards;mode.sites.home.data.Kind=ERR_LocationKind::RADIO;hq.RegisterGroup(&radioGuards); + assert(hq.m_Units[3]->ReservedForSupport && hq.m_Units[3]->HomeGuard); + hq.RegisterGroup(&radioGuards);assert(hq.m_Units.Count()==4&&hq.m_Units[3]->ReservedForSupport); } ''') print('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') diff --git a/tests/test_intel_reroll.py b/tests/test_intel_reroll.py index be2df44..ea45f9c 100644 --- a/tests/test_intel_reroll.py +++ b/tests/test_intel_reroll.py @@ -23,7 +23,7 @@ def adapt(text,cls): text=re.sub(r'^(\w+) (\w+)\(',lambda m:m[1]+' '+cls+'::'+m[2]+'(',text) # Defaults belong only to declarations in C++. text=text.replace('bool failed = false, bool skipped = false','bool failed, bool skipped') - return text + return text.replace('Evidence().','Evidence()->') service_methods=[('void RegisterGroup(', 'void RegisterGroup(SCR_AIGroup group);'),('void Tick(', 'void Tick(float now);'),('bool BeginReroll(', 'bool BeginReroll();'),('bool HasPendingInsertion(', 'bool HasPendingInsertion(IEntity actor);'),('void Unsettled(', 'void Unsettled(IEntity actor);'),('bool Settled(', 'bool Settled(IEntity actor);'),('void Stop(', 'void Stop();')] batch_methods=[('void Add(', 'void Add(IEntity actor);'),('bool Running(', 'bool Running();'),('void Tick(', 'void Tick();'),('protected void Finish(', 'void Finish(ERR_IntelRerollEntry entry,bool failed=false,bool skipped=false);'),('protected void Fail(', 'void Fail(ERR_IntelRerollEntry entry,string reason);'),('protected void Process(', 'void Process(ERR_IntelRerollEntry entry);'),('void Stop(', 'void Stop();')] code=r''' @@ -48,8 +48,9 @@ struct Group{Array agents;void GetAgents(Array& out){out=agent namespace ERR_Actors{bool Alive(IEntity a){return a&&a->alive;}bool Player(IEntity a){return a&&a->player;}} namespace ERR_Resources{int IntelFolder(){return 1;}} struct Discovery{Set spent;bool capacity=true;static void Folders(Inventory* i,Array& out){out=i->folders;}bool IsSpent(IEntity a){return spent.Contains(a);}bool CanMarkSpent(IEntity a){return capacity;}bool MarkSpent(IEntity a){if(!capacity)return false;spent.Insert(a);return true;}};using ERR_DiscoveryService=Discovery; -struct Settings{int chance=100;int Get(const char*){return chance;}}; -struct Mode{bool active=true;struct Settings settings;struct Discovery discovery;Set owned;bool Active(){return active;}struct Settings* Settings(){return &settings;}struct Discovery* Discovery(){return &discovery;}void Own(IEntity a){owned.Insert(a);}}; +struct Settings{int chance=100;int Runtime(const char*){return chance;}}; +struct EvidenceService{void Capture(IEntity){}void Retire(IEntity){}}; +struct Mode{EvidenceService evidence;EvidenceService* Evidence(){return &evidence;}bool active=true;struct Settings settings;struct Discovery discovery;Set owned;bool Active(){return active;}struct Settings* Settings(){return &settings;}struct Discovery* Discovery(){return &discovery;}void Own(IEntity a){owned.Insert(a);}}; struct Entry{string WaitingFor="inventory";Callback* Operation=nullptr;IEntity Actor=nullptr,Removing=nullptr;int Attempts=0;bool GiveIntel=false,Inserting=false,Accepted=false,Done=false;};using ERR_IntelRerollEntry=Entry*; struct Request{Callback* Operation=nullptr;IEntity Actor=nullptr;int Attempts=0;bool Accepted=false;};using ERR_IntelRequest=Request*; struct Service;struct Batch; diff --git a/tests/test_mortar_activity_completion.py b/tests/test_mortar_activity_completion.py index 764306e..80907b8 100644 --- a/tests/test_mortar_activity_completion.py +++ b/tests/test_mortar_activity_completion.py @@ -10,7 +10,8 @@ def adapt(signature): s=s.replace('SCR_AIActionBase action','Action* action').replace('EAIActionState ', 'State ').replace('EAIActionState.', 'State::') s=s.replace('ERR_MortarSupplyState ', 'Supply ').replace('ERR_MortarSupplyState.', 'Supply::').replace('ERR_MortarSalvo.', 'Salvo::') s=s.replace('string reason', 'std::string reason') - for name in ['Activity','m_ObservedActivity','m_Transfer','m_Readiness']: + s=s.replace('new ERR_MortarStation(this)', 'new Station(this)') + for name in ['Activity','m_ObservedActivity','m_Transfer','m_Readiness','m_Station']: s=s.replace(name+'.',name+'->') for name in ['OnActivityCompleted','OnActivityFailed']: s=s.replace('.Insert('+name+')', '.Insert(this, &Battery::'+name+')').replace('.Remove('+name+')', '.Remove(this, &Battery::'+name+')') @@ -28,6 +29,7 @@ enum class Supply {FAILED=-1,PENDING,READY}; struct Salvo {static constexpr float TIMEOUT_MS=120000;}; struct Text:std::string {using std::string::string;bool IsEmpty(){return empty();}}; struct Action;struct Battery; +struct Station {Station(Battery*){} void Update(float){} void Stop(){}}; struct Invoker {Battery* owner=nullptr;void(Battery::*callback)(Action*)=nullptr;int inserts=0,removes=0,calls=0; void Insert(Battery* b,void(Battery::*f)(Action*)){owner=b;callback=f;inserts++;} void Remove(Battery* b,void(Battery::*f)(Action*)){if(owner==b&&callback==f){owner=nullptr;callback=nullptr;removes++;}} @@ -44,7 +46,7 @@ struct Battery { bool m_Stopped=false,CommandOpen=true,StartupActivated=true,operational=true,RefreshRejected=false,Released=false; Action* Activity=nullptr;Action* m_ObservedActivity=nullptr;int OrderId=1,m_ObservedActivityOrder=0,OrderShots=8,TotalShots=8; State m_ActivityTerminal=State::EVALUATED;float OrderedAt=0,AimedAt=100,AimValidatedAt=100; - Text SpawnFailure;std::string lastCancel;Readiness readiness;Readiness* m_Readiness=&readiness;Transfer transfer;Transfer* m_Transfer=&transfer; + Text SpawnFailure;std::string lastCancel;Readiness readiness;Readiness* m_Readiness=&readiness;Transfer transfer;Transfer* m_Transfer=&transfer;Station* m_Station=nullptr; void* RadioOrder=nullptr;void* PendingRadioReport=nullptr;void* PendingSupplyReport=nullptr;void* Refresh=nullptr;void* Report=this;void* AimSolver=this;void* AimSolution=this; bool Operational(){return operational;}std::string OperationalReason(){return "physical crew unavailable";}void SpawnFailed(const char*){}void UpdateCrewDetail(float){}void FlushTraces(){} '''+methods+cancel+r''' diff --git a/tests/test_mortar_logistics.py b/tests/test_mortar_logistics.py index fc010f2..f4c2e8f 100644 --- a/tests/test_mortar_logistics.py +++ b/tests/test_mortar_logistics.py @@ -128,3 +128,48 @@ int main(){int faction,group,foreign;Usage usage;Actor gun{&faction,&group};gun. } ''') print('PASS: actual native-gun ownership gate rejects player/foreign/replaced/dead occupant, faction change, missing seat and missing registry') + +# Exercise the production between-trip target selector with four batteries. +select = body(p, 'protected void SelectBattery(') +select = select.replace('protected ', '').replace('ERR_MortarLogisticsRules.', 'Rules::').replace('vector.DistanceXZ', 'Distance') +select = select.replace('array batteries = {};', 'Array batteries;').replace('ERR_MortarBattery selected;', 'Battery* selected=nullptr;') +select = select.replace('foreach (ERR_MortarBattery candidate : batteries)', 'for (Battery* candidate : batteries)').replace('float.MAX', '999999') +select = select.replace('m_HQ.Mortars().Batteries(batteries)', 'system.Batteries(batteries)') +for name in ('m_Battery', 'candidate', 'selected', 'm_Cache'): + select = select.replace(name+'.', name+'->') +run(r''' +#include +#include +#include +using std::abs; +struct Battery { bool StartupActivated=true, stopped=false, operational=true; int shells=0, Gun=1, Group=1; float Position=0; + bool Stopped(){return stopped;} bool Operational(){return operational;} int CountShells(){return shells;} }; +template struct Array:std::vector{using std::vector::operator=;void Clear(){this->clear();}}; +struct System {Array all; void Batteries(Array& out){out=all;}}; +struct Cache {float GetOrigin(){return 0;}}; +float Distance(float a,float b){return abs(a-b);} +namespace Rules {bool Need(int n){return n>=0&&n<=6;}} +struct Courier {int m_State=1;bool m_Report=false,m_Move=false,m_Order=false; Battery* m_Battery=nullptr; + int m_OriginalGun=0,m_OriginalBatteryGroup=0;Array m_BatteryMembers;float m_NextReport=99; + Cache cache;Cache* m_Cache=&cache;System system; + bool TargetAvailable(){return m_Battery&&m_Battery->StartupActivated&&!m_Battery->Stopped()&&m_Battery->Operational();} +''' + select + r''' +}; +int main(){ + Battery a,b,c,d;a.Position=200;b.Position=100;c.Position=300;d.Position=400; + Courier s;s.system.all={&a,&b,&c,&d};s.SelectBattery();assert(s.m_Battery==&b); + // Keep an active low-ammo recipient; a new nearer request cannot retarget it. + a.Position=1;s.SelectBattery();assert(s.m_Battery==&b); + // Once replenished, choose another depleted battery and reset only binding. + b.shells=12;s.m_BatteryMembers={9};s.SelectBattery();assert(s.m_Battery==&a&&s.m_BatteryMembers.empty()&&s.m_NextReport==0); + a.operational=false;s.SelectBattery();assert(s.m_Battery==&c); + c.stopped=true;d.StartupActivated=false;s.SelectBattery();assert(s.m_Battery==&c); + d.StartupActivated=true; + for(int gate=0;gate<4;gate++){ + s.m_State=gate==0?3:1;s.m_Report=gate==1;s.m_Move=gate==2;s.m_Order=gate==3; + s.SelectBattery();assert(s.m_Battery==&c); + } + s.m_Order=false;s.SelectBattery();assert(s.m_Battery==&d); +} +''') +print('PASS: four-battery courier selection preserves pending trip/report/transfer identity, skips unavailable crews, and selects the next depleted battery without new stock') diff --git a/tests/test_mortar_station.py b/tests/test_mortar_station.py new file mode 100644 index 0000000..f821f8f --- /dev/null +++ b/tests/test_mortar_station.py @@ -0,0 +1,35 @@ +"""Run actual station scope predicates; native boarding/movement is tested separately.""" +from policy_harness import ROOT, body, run +p=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_MortarStation.c' +s='\n'.join(body(p,name) for name in ('bool Holds(', 'bool HoldsSeat(', 'bool HoldsPosition(')) +s=(s.replace('IEntity actor','IEntity* actor').replace('IEntity vehicle','IEntity* vehicle') + .replace('m_Battery.', 'm_Battery->').replace('Replication.', 'Replication::') + .replace('ERR_HQ.', 'ERR_HQ::').replace('ERR_Actors.', 'ERR_Actors::') + .replace('CompartmentAccessComponent.', 'CompartmentAccessComponent::')) +run(r''' +#include +struct IEntity {bool player=false, fighting=true; int group=1; IEntity* vehicle=nullptr;}; +struct Battery {int Group=1; IEntity* Gun=nullptr;}; +namespace Replication {bool server=true;bool IsServer(){return server;}} +namespace ERR_HQ {bool active=true;bool MissionActive(){return active;}} +namespace ERR_Actors {bool Player(IEntity* a){return a->player;}int Group(IEntity* a){return a->group;}bool CanFight(IEntity* a){return a&&a->fighting;}} +namespace CompartmentAccessComponent {IEntity* GetVehicleIn(IEntity* a){return a->vehicle;}} +struct Station {Battery* m_Battery;IEntity* m_Gunner=nullptr;bool m_Stopped=false,intact=true;bool GunIntact(){return intact;} +''' + s + r''' +}; +int main(){ + IEntity gun,other,actor;Battery b;b.Gun=&gun;Station s{&b};actor.vehicle=&gun; + assert(s.Holds(&actor)&&s.HoldsPosition(&actor)&&s.HoldsSeat(&actor,&gun)); + assert(!s.HoldsSeat(&actor,&other));actor.vehicle=nullptr;assert(!s.HoldsSeat(&actor,&gun)); + s.m_Gunner=&actor;assert(s.Holds(&actor)&&!s.HoldsPosition(&actor)); // gunner may walk to board + s.m_Gunner=nullptr;actor.fighting=false;assert(!s.HoldsPosition(&actor));actor.fighting=true; + actor.player=true;assert(!s.Holds(&actor));actor.player=false; + actor.group=2;assert(!s.Holds(&actor));actor.group=1; + s.intact=false;assert(!s.Holds(&actor)&&!s.HoldsPosition(&actor));s.intact=true; + s.m_Stopped=true;assert(!s.Holds(&actor));s.m_Stopped=false; + Replication::server=false;assert(!s.Holds(&actor));Replication::server=true; + ERR_HQ::active=false;assert(!s.Holds(&actor));ERR_HQ::active=true; + assert(!s.Holds(nullptr)); +} +''') +print('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') diff --git a/tests/test_native_end_lifecycle.py b/tests/test_native_end_lifecycle.py index 658e4ee..bdcbddc 100644 --- a/tests/test_native_end_lifecycle.py +++ b/tests/test_native_end_lifecycle.py @@ -9,7 +9,7 @@ def cpp(s): s=s.replace('GetGame().','GetGame()->').replace('GetCallqueue().','GetCallqueue()->').replace('GetPlayerManager().','GetPlayerManager()->') return s methods='\n'.join(cpp(body(SOURCE, signature)) for signature in ('bool Active(', 'protected override void OnGameModeEnd(', 'protected void StopServices(')) -startGuard=body(SOURCE,'protected void StartScenario(').split('if (!m_Factions',1)[0].replace('protected ','') +startGuard=body(SOURCE,'protected void StartScenario(').split('if (!m_FactionSelection',1)[0].replace('protected ','') run(r'''#include #include #include diff --git a/tests/test_native_package_external.py b/tests/test_native_package_external.py index 5f30099..9d1c87b 100644 --- a/tests/test_native_package_external.py +++ b/tests/test_native_package_external.py @@ -79,7 +79,7 @@ class ExternalPackageTests(unittest.TestCase): records=n.expose_external(project,profile,self.steam,context) expected={'ArmaReforger'}|({'ERRI_'+guid for guid in ext.ALLOWED} if context else set()) self.assertEqual({p.name for p in (profile/'addons').iterdir()},expected) - self.assertEqual(len(records),6 if context else 0) + self.assertEqual(len(records),len(ext.ALLOWED) if context else 0) for link in (profile/'addons').iterdir(): self.assertTrue(link.is_symlink());self.assertNotEqual(link.resolve(),self.source) self.assertNotEqual(link.resolve(),unrelated) @@ -117,7 +117,7 @@ class ExternalPackageTests(unittest.TestCase): def test_native_clean_exit_binds_before_after_external_fingerprints(self): self.prepare();report=self.native_double() self.assertTrue(report['candidate_created']);self.assertTrue(report['external_addons_unchanged_after_run']) - self.assertTrue(report['profile_addons_unchanged']);self.assertEqual(report['external_addon_count'],6) + self.assertTrue(report['profile_addons_unchanged']);self.assertEqual(report['external_addon_count'],len(ext.ALLOWED)) evidence=self.session/'evidence/core' before=json.loads((evidence/'external-addons-before.json').read_text()) after=json.loads((evidence/'external-addons-after.json').read_text()) @@ -164,7 +164,7 @@ class ExternalPackageTests(unittest.TestCase): return base.NativePackageTests.completed_report(True) code,summary,calls=self.run_double(args,result) self.assertEqual(code,0);self.assertEqual([c.args[3] for c in calls],['core']) - self.assertEqual(summary['external_addon_count'],6);self.assertTrue(summary['external_addons_unchanged_after_run']) + self.assertEqual(summary['external_addon_count'],len(ext.ALLOWED));self.assertTrue(summary['external_addons_unchanged_after_run']) self.assertFalse(summary['release_qualified']);self.assertFalse(summary['published']) self.assertTrue((args.session/'external-addons-after.json').is_file()) def test_diagnostic_continuation_stops_on_mid_batch_external_mutation(self): diff --git a/tests/test_packed_external_game.py b/tests/test_packed_external_game.py index 724fb35..5ba3cd7 100644 --- a/tests/test_packed_external_game.py +++ b/tests/test_packed_external_game.py @@ -77,7 +77,7 @@ class ExternalPackedTests(unittest.TestCase): def test_private_copy_exact_six_links_and_schema(self): unrelated=self.source/'protected';unrelated.mkdir();(unrelated/'addon.gproj').write_text('GameProject {GUID "5F16D7E4A1CBE075"}') self.prepare();raw=self.snapshot();value=json.loads(raw) - self.assertEqual(value['schema_version'],4);self.assertEqual(value['kind'],'packed-chat-external-runtime-input');self.assertEqual(len(value['external_addons']),6) + self.assertEqual(value['schema_version'],4);self.assertEqual(value['kind'],'packed-chat-external-runtime-input');self.assertEqual(len(value['external_addons']),len(ext.ALLOWED)) self.assertEqual({p.name for p in (self.profile/'addons').iterdir()},{'ArmaReforger',*('ERRI_'+g for g in ext.ALLOWED)}) self.assertEqual(self.seal(raw)['packed_inputs_unchanged_after_run'],True) self.assertNotEqual((self.candidate/'core/data.pak').stat().st_ino,(self.packed['input']/'core/data.pak').stat().st_ino) @@ -113,7 +113,7 @@ class ExternalPackedTests(unittest.TestCase): self.prepare();raw=self.snapshot();(self.session/v4.MANIFEST).write_bytes(raw+b' ') self.assertFalse(self.seal(raw)['packed_inputs_unchanged_after_run']) def test_valid_full_nine_mount_database_proof(self): - result=self.evidence();self.assertTrue(result['ready'],result);self.assertFalse(result['release_qualified']);self.assertEqual(result['external_addon_count'],6) + result=self.evidence();self.assertTrue(result['ready'],result);self.assertFalse(result['release_qualified']);self.assertEqual(result['external_addon_count'],len(ext.ALLOWED)) def test_runtime_evidence_rejects_redirects_extra_missing_and_loose(self): content=self.content();guid=ext.DIRECT[0];name=self.packed['external_names'][guid];folder=self.profile/'addons'/('ERRI_'+guid) variants=[content.replace(str(folder),'/unreviewed'),content.replace('(pak count: 1) to filesystem under name '+name,'(pak count: 2) to filesystem under name '+name),content+'00 ENGINE : dir: "ignored"\n'+f"00 ENGINE : dir: '{self.source}'\n",content+f"00 ENGINE : FileSystem: Adding relative directory '{folder}/Scripts' to filesystem under name {name}\n",re.sub(r'[^\n]*gproj:[^\n]*'+guid+r'[^\n]*\n','',content),re.sub(r'[^\n]*ResourceDB: loading cache[^\n]*name='+name+r' [^\n]*\n','',content),content.replace('PLATFORM_WINDOWS','PLATFORM_WINDOWS,WORKBENCH')] diff --git a/tests/test_participant_selection.py b/tests/test_participant_selection.py index 1db1543..fe893e4 100644 --- a/tests/test_participant_selection.py +++ b/tests/test_participant_selection.py @@ -42,8 +42,8 @@ namespace CompartmentAccessComponent{IEntity GetVehicleIn(IEntity a){return a?a- struct Roster{std::map lives;ERR_PlayerLife Get(int id){auto p=lives.find(id);return p==lives.end()?nullptr:p->second;} '''+roster+r''' }; -struct ERR_GameMode{static ERR_GameMode* current;Roster* roster;int phase=2,faction=1;bool active=true;static ERR_GameMode* Get(){return current;}bool Active(){return active;}int Phase(){return phase;}int PlayerFaction(){return faction;}int PrisonPosition(){return 0;}Roster* Players(){return roster;}};ERR_GameMode* ERR_GameMode::current=nullptr; -struct Placement{int nearCalls=0,prisonCalls=0;IEntity last=nullptr;bool clear=true;bool Near(IEntity a,int,vector& p){nearCalls++;last=a;p=a->origin;return clear;}bool Prison(int,int,vector& p){prisonCalls++;p=0;return true;}}; +struct ERR_GameMode{static ERR_GameMode* current;Roster* roster;int phase=2,faction=1;bool active=true;static ERR_GameMode* Get(){return current;}bool Active(){return active;}int Phase(){return phase;}int PlayerFaction(){return faction;}int PrisonPosition(){return 0;}float PrisonHeading(){return 90;}Roster* Players(){return roster;}};ERR_GameMode* ERR_GameMode::current=nullptr; +struct Placement{int nearCalls=0,prisonCalls=0;IEntity last=nullptr;bool clear=true;bool Near(IEntity a,int,vector& p){nearCalls++;last=a;p=a->origin;return clear;}bool Prison(int,int,vector& p,float heading){assert(heading==90);prisonCalls++;p=0;return true;}}; struct Spawn{Placement m_Placement;int m_AuthorizedPositions=0; '''+spawn+r''' }; diff --git a/tests/test_prison_ai.py b/tests/test_prison_ai.py index b591305..2270014 100644 --- a/tests/test_prison_ai.py +++ b/tests/test_prison_ai.py @@ -26,7 +26,7 @@ namespace ERR_Actors {bool Player(Actor* a){return a&&a->player;}bool CanFight(A namespace SCR_FactionManager {int SGetFaction(Actor* a){return a->faction;}} struct Hook {std::set callbacks;int inserted=0;void Insert(std::string c){callbacks.insert(c);inserted++;}void Remove(std::string c){callbacks.erase(c);}}; struct ERR_GameMode {static ERR_GameMode* current;int phase=0,enemy=2;Hook phases,stops; - static ERR_GameMode* Get(){return current;}int Phase(){return phase;}int EnemyFaction(){return enemy;} + static ERR_GameMode* Get(){return current;}int Phase(){return phase;}int EnemyFaction(){return enemy;}bool IsMissionEnemy(int f){return enemy&&f>=enemy;} Hook* OnPhaseChanged(){return &phases;}Hook* OnStop(){return &stops;}}; ERR_GameMode* ERR_GameMode::current=nullptr; struct Agent {ERR_GameMode* m_ERRPrisonMode=nullptr;Actor* actor=nullptr;bool pending=false,active=true;int starts=0; diff --git a/tests/test_prison_placement_policy.py b/tests/test_prison_placement_policy.py index 6983ac2..205ea88 100644 --- a/tests/test_prison_placement_policy.py +++ b/tests/test_prison_placement_policy.py @@ -4,7 +4,7 @@ This verifies bounded search order/termination, not terrain or body clearance. from policy_harness import ROOT,body,run source=ROOT/'addons/core/Scripts/Game/ERR/00_Core/ERR_SpawnPlacement.c' search=(body(source,'bool Prison(').replace('map reservations','map* reservations') - .replace('out vector position','vector& position').replace('ERR_Actors.', 'ERR_Actors::').replace('Math.', 'Math::')) + .replace('out vector position','vector& position').replace('ERR_Actors.', 'ERR_Actors::').replace('Math.', 'Math::').replace('ERR_CampTerrain.', 'ERR_CampTerrain::')) run('''#include #include #include @@ -16,6 +16,7 @@ vector Vector(float x,float y,float z){return {x,y,z};} template struct map {}; namespace ERR_Actors {vector Ground(vector value){return value;}} namespace Math {int AbsInt(int value){return std::abs(value);}} +namespace ERR_CampTerrain {vector Rotate(vector v,float a){float r=a*3.14159265359f/180;return {v.x*std::cos(r)+v.z*std::sin(r),v.y,-v.x*std::sin(r)+v.z*std::cos(r)};}} struct Search { std::vector visited; int accept=-1; @@ -23,6 +24,7 @@ struct Search { ''' + search + ''' }; int main(){ + Search rotated;rotated.accept=0;vector turned;assert(rotated.Prison(Vector(0,0,0),nullptr,turned,90));assert(std::abs(turned.x+1.5)<.001&&std::abs(turned.z-1.5)<.001); const vector center={6090,100,7160}; vector result={-1,-1,-1}; Search blocked; @@ -57,3 +59,37 @@ int main(){ } ''') print('PASS: prison search packs 16 unique 3m-spaced inside-wall centers, prioritizes inner/edge positions and never bypasses clearance') + +occupancy = (body(source, 'protected bool Occupied(').replace('protected ', '') + .replace('IEntity entity', 'IEntity* entity').replace('entity.', 'entity->') + .replace('ChimeraCharacter.Cast', 'ChimeraCharacter::Cast') + .replace('vector.', 'vector::').replace('Math.', 'Math::')) +run(r''' +#include +#include +#include +struct vector { + float x=0,y=0,z=0; + float operator[](int i) const {return i==0?x:(i==1?y:z);} + static float DistanceXZ(vector a,vector b){return std::hypot(a.x-b.x,a.z-b.z);} +}; +struct IEntity {vector position;bool character=true;vector GetOrigin(){return position;}}; +namespace ChimeraCharacter {bool Cast(IEntity* e){return e&&e->character;}} +namespace Math {float AbsFloat(float f){return std::abs(f);}} +struct Placement { + IEntity* m_Exclude=nullptr; vector m_Candidate; bool m_Blocked=false; +''' + occupancy + r''' +}; +int main(){ + IEntity body; + for(float distance : {0.f,1.199f,1.2f,2.12f,3.f}) { + Placement p;body.position={distance,0,0}; + assert(p.Occupied(&body)==(distance>=1.2f)); + } + Placement vertical;body.position={0,2,0};assert(vertical.Occupied(&body)); + Placement excluded;excluded.m_Exclude=&body;body.position={0,0,0};assert(excluded.Occupied(&body)); + Placement scenery;body.character=false;assert(scenery.Occupied(&body)); // geometry uses the separate native trace + assert(scenery.Occupied(nullptr)); +} +''') +print('PASS: physical body occupancy rejects overlap, permits diagonal neighboring slots, and excludes own body and unrelated broad-phase bounds') diff --git a/tests/test_random_settings.py b/tests/test_random_settings.py new file mode 100644 index 0000000..802e9eb --- /dev/null +++ b/tests/test_random_settings.py @@ -0,0 +1,47 @@ +"""Exercise concrete bounds, saved modes, calendar mapping and daylight edges.""" +from datetime import date, timedelta +from policy_harness import ROOT, body, run +core = ROOT/'addons/core/Scripts/Game/ERR/00_Core' +rules = '\n'.join(body(core/file, sig) for file, sig in ( + ('ERR_Settings.c', 'static bool Valid('), + ('ERR_Settings.c', 'static bool Randomizable('), + ('ERR_Settings.c', 'static bool ValidSelection('), + ('ERR_Settings.c', 'static bool RandomBounds('), + ('ERR_EnvironmentService.c', 'static int DateFromOrdinal('), + ('ERR_TimeService.c', 'static bool DaylightBounds('), +)) +rules = rules.replace('string ', 'std::string ').replace('out int ', 'int& ').replace('Math.Floor', 'std::floor').replace('Math.Ceil', 'std::ceil') +calendar = [] +for year in (1900, 1989, 2000, 2024, 2050): + first = date(year, 1, 1) + days = (date(year+1,1,1)-first).days + for ordinal in range(days): + day = first+timedelta(days=ordinal) + code = (year-1900)*10000+day.month*100+day.day + calendar.append(f'assert(DateFromOrdinal({year},{ordinal})=={code});') + calendar.append(f'assert(DateFromOrdinal({year},{days})==-1);') +run('#include \n#include \n#include \n' + rules + r""" +int main() { + int lo=-1,hi=-1; + for (std::string key:{"reportIntervalSeconds","supportSquadLimit","responseRadiusMetres","aiIntelChancePercent","intelRevealChancePercent","radioDefenceSeconds","startTimeMinutes","timeMultiplier","startDateCode","weatherProfile","convoyCount","heliTimerMinutes"}) { + assert(ValidSelection(key,-1)); assert(!Valid(key,-1)); + assert(ValidSelection(key,-2)==(key=="startTimeMinutes")); assert(!ValidSelection(key,-3)); + if(key=="startDateCode")continue; + assert(RandomBounds(key,lo,hi)); + assert(lo<=hi); + for(int value=lo;value<=hi;value++) assert(Valid(key,value)); + } + for(std::string key:{"unknown","","stingerChanceOneIn","automaticConvoyEnabled"}) assert(!ValidSelection(key,-1)); + assert(RandomBounds("convoyCount",lo,hi)&&lo==0&&hi==20); + assert(RandomBounds("weatherProfile",lo,hi)&&lo==1&&hi==3); + assert(RandomBounds("startTimeMinutes",lo,hi)&&lo==0&&hi==1439); + assert(DaylightBounds(6.0,18.0,lo,hi)&&lo==361&&hi==1080); + assert(DaylightBounds(6.125,18.125,lo,hi)&&lo==368&&hi==1088); + for(int minute=lo;minute6.125&&minute/60.0<18.125); + assert(!DaylightBounds(18,6,lo,hi)); assert(!DaylightBounds(12,12,lo,hi)); + assert(!DaylightBounds(-1,18,lo,hi));assert(!DaylightBounds(6,25,lo,hi)); + assert(!DaylightBounds(6.0,6.001,lo,hi)); + assert(DaylightBounds(0,24,lo,hi)&&lo==1&&hi==1440); + assert(DateFromOrdinal(1899,0)==-1&&DateFromOrdinal(2051,0)==-1&&DateFromOrdinal(2000,-1)==-1); +""" + ''.join(calendar) + '}') +print('PASS: random mode restrictions, full numeric ranges, independent calendar dates and strict daylight boundaries') diff --git a/tests/test_rough_intel_feedback.py b/tests/test_rough_intel_feedback.py index 4f2e294..5a3c5b1 100644 --- a/tests/test_rough_intel_feedback.py +++ b/tests/test_rough_intel_feedback.py @@ -46,8 +46,8 @@ int main(){ assert(has(unknown,"Choose either marked supply cache")&&!has(unknown,"Intel recovered")); radio.knowledge=1; string rough=Actual::PhaseDescription(&mode,true); - assert(rough!=unknown&&has(rough,"Intel recovered")&&has(rough,"500 m search square")); - assert(has(rough,"carried field map")&&has(rough,"different intelligence folder")); + assert(rough!=unknown&&has(rough,"Intel recovered")&&has(rough,"question mark")); + assert(!has(rough,"search square")&&has(rough,"different intelligence folder")); assert(has(rough,"already recovered cannot provide another clue")); assert(Actual::PhaseDescription(&mode,false)==rough); // Same task and guide copy. for(int i=0;i<10;i++) assert(Actual::PhaseDescription(&mode,true)==rough); diff --git a/tests/test_scouts.py b/tests/test_scouts.py new file mode 100644 index 0000000..5703087 --- /dev/null +++ b/tests/test_scouts.py @@ -0,0 +1,79 @@ +"""Execute production hill/road geometry and finite admission state machine.""" +import re +from policy_harness import ROOT, body, run +p=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_ScoutSystem.c' +hill=body(p,'static bool Hill(') +road=body(p,'static bool OnSegment(') +prepare=body(p,'ERR_PrepareResult Prepare(') +for name in ('Math','vector','ERR_PrepareResult','Replication'): + hill=hill.replace(name+'.',name+'::');road=road.replace(name+'.',name+'::');prepare=prepare.replace(name+'.',name+'::') +prepare=prepare.replace('ERR_ScenarioDefinition definition','ERR_ScenarioDefinition* definition').replace('foreach (ERR_ScoutPost post : m_Posts)','for (ERR_ScoutPost* post : m_Posts)').replace('post.','post->').replace('bool pending;','bool pending=false;').replace('GetGame().GetWorld().','clock.').replace('GetGame().GetWorldEntity().','world.').replace('System.GetTickCount()','0') +motion=body(p,'static void Estimate(').replace('ERR_HQReport report','ERR_HQReport* report').replace('ERR_HQReport previous','ERR_HQReport* previous') +for name in ('report','previous'): motion=motion.replace(name+'.',name+'->') +for name in ('vector','ERR_HQMemoryRules'): motion=motion.replace(name+'.',name+'::') +memory=ROOT/'addons/core/Scripts/Game/ERR/10_AI/ERR_HQMemory.c' +credible=body(memory,'static float SpeedLimit(')+'\n'+body(memory,'static bool MotionCredible(') +credible=credible.replace('string ', 'std::string ') +run(r''' +#include +#include +#include +#include +#include +struct Math{static float Max(float a,float b){return std::max(a,b);}static float Clamp(float n,float a,float b){return std::clamp(n,a,b);}static float AbsFloat(float n){return std::abs(n);}}; +struct vector{float v[3]={};vector()=default;vector(float x,float y,float z):v{x,y,z}{}float&operator[](int i){return v[i];}float operator[](int i)const{return v[i];}vector operator-(vector b)const{return{v[0]-b[0],v[1]-b[1],v[2]-b[2]};}vector operator/(float f)const{return{v[0]/f,v[1]/f,v[2]/f};}static const vector Zero;static float Dot(vector a,vector b){return a[0]*b[0]+a[1]*b[1]+a[2]*b[2];}static vector Lerp(vector a,vector b,float f){return{a[0]+(b[0]-a[0])*f,a[1]+(b[1]-a[1])*f,a[2]+(b[2]-a[2])*f};}static float DistanceXZ(vector a,vector b){return std::hypot(a[0]-b[0],a[2]-b[2]);}}; +const vector vector::Zero{}; +'''+hill+'\n'+road+r''' +struct ERR_HQReport{void* Target=nullptr;void* Source=nullptr;bool Distress=false,HasVelocity=false;vector Position,Velocity;float ObservedAt=0;std::string TravelMode="on foot";}; +struct ERR_HQMemoryRules{static bool Finite(float n){return std::isfinite(n);} +'''+credible+r'''}; +'''+motion+r''' +enum class ERR_PrepareResult{PENDING,READY,FAILED}; +struct Replication{static bool server;static bool IsServer(){return server;}};bool Replication::server=true; +struct ERR_ScenarioDefinition{};struct ERR_ScoutPost{bool Ready=false,Group=false;}; +struct Clock{float now=0;float GetWorldTime(){return now;}}; +struct World{void GetWorldBounds(vector&,vector&) {}}; +struct Population{ + bool m_Stopped=false,m_Ready=false,m_Begun=false,m_Surveyed=false;ERR_ScenarioDefinition*m_Definition=nullptr;int m_Started=0,spawns=0,stocks=0,surveys=0;float m_Deadline=10;vector m_Low,m_High;Clock clock;World world; + std::vectorm_Posts; + ERR_PrepareResult survey=ERR_PrepareResult::READY,stock=ERR_PrepareResult::READY; + ERR_PrepareResult Survey(){surveys++;m_Surveyed=survey==ERR_PrepareResult::READY;return survey;} + ERR_PrepareResult Fail(const char*){m_Stopped=true;return ERR_PrepareResult::FAILED;} + bool Spawn(ERR_ScoutPost*p){spawns++;p->Group=true;return true;} + ERR_PrepareResult Stock(ERR_ScoutPost*p){stocks++;p->Ready=stock==ERR_PrepareResult::READY;return stock;} +'''+prepare+r''' +}; +int main(){ + assert(Hill(90,200,6,4));assert(!Hill(34,100,30,8));assert(!Hill(35,200,30,8));assert(!Hill(100,200,5.9,8));assert(!Hill(100,200,30,3)); + vector a{0,10,0},b{100,20,0}; + assert(OnSegment({50,15,2},a,b,4));assert(!OnSegment({50,15,2.01},a,b,4)); + assert(!OnSegment({50,25,0},a,b,4)); // aircraft/overpass != ground road + assert(!OnSegment({105,20,0},a,b,4)); // no infinite extension past end + assert(!OnSegment({50,15,0},a,a,4));assert(!OnSegment({50,15,0},a,b,0)); + // A bend is tested as its real segments, not a diagonal shortcut. + assert(!OnSegment({50,10,50},{0,10,0},{100,10,0},4));assert(!OnSegment({50,10,50},{100,10,0},{100,10,100},4)); + ERR_HQReport previous,current;previous.Target=&previous;current.Target=&previous;previous.Source=¤t;current.Source=¤t; + previous.ObservedAt=1000;previous.Position={0,0,0};current.ObservedAt=11000;current.Position={20,5,30}; + Estimate(¤t,&previous);assert(current.HasVelocity&¤t.Velocity[0]==2&¤t.Velocity[1]==0&¤t.Velocity[2]==3); + current.Target=¤t;Estimate(¤t,&previous);assert(!current.HasVelocity);current.Target=&previous; + current.Source=nullptr;Estimate(¤t,&previous);assert(!current.HasVelocity);current.Source=¤t; + current.ObservedAt=1000;Estimate(¤t,&previous);assert(!current.HasVelocity); + current.ObservedAt=33000;Estimate(¤t,&previous);assert(!current.HasVelocity); + current.ObservedAt=11000;current.Position={500,0,0};Estimate(¤t,&previous);assert(!current.HasVelocity); + current.TravelMode="in vehicle";Estimate(¤t,&previous);assert(!current.HasVelocity); + previous.TravelMode="in vehicle";Estimate(¤t,&previous);assert(current.HasVelocity&¤t.Velocity[0]==50); + previous.Distress=true;Estimate(¤t,&previous);assert(!current.HasVelocity); + ERR_ScenarioDefinition def;Population pop;ERR_ScoutPost first,second;pop.m_Posts={&first,&second}; + pop.survey=ERR_PrepareResult::PENDING;assert(pop.Prepare(&def)==ERR_PrepareResult::PENDING&&pop.spawns==0); + pop.survey=ERR_PrepareResult::READY;assert(pop.Prepare(&def)==ERR_PrepareResult::PENDING&&pop.spawns==1); + pop.stock=ERR_PrepareResult::PENDING;assert(pop.Prepare(&def)==ERR_PrepareResult::PENDING&&pop.spawns==2); + assert(pop.Prepare(&def)==ERR_PrepareResult::PENDING&&pop.spawns==2); + pop.stock=ERR_PrepareResult::READY;assert(pop.Prepare(&def)==ERR_PrepareResult::READY); + int stocks=pop.stocks;first.Group=false;first.Ready=false; + assert(pop.Prepare(&def)==ERR_PrepareResult::READY&&pop.spawns==2&&pop.stocks==stocks); // dead original never replaced/refilled + Population timeout;timeout.m_Begun=true;timeout.m_Surveyed=true;timeout.clock.now=11;assert(timeout.Prepare(&def)==ERR_PrepareResult::FAILED&&timeout.spawns==0); + Population stopped;stopped.m_Stopped=true;assert(stopped.Prepare(&def)==ERR_PrepareResult::FAILED&&stopped.surveys==0); + Replication::server=false;Population client;assert(client.Prepare(&def)==ERR_PrepareResult::FAILED&&client.surveys==0); +} +''') +print('PASS: hill prominence/elevation, actual road edges/heights/bends and server-only finite scout admission, pending stock, timeout and no replacements/refills') diff --git a/tests/test_settings_migration.py b/tests/test_settings_migration.py index dff8f34..7279e55 100644 --- a/tests/test_settings_migration.py +++ b/tests/test_settings_migration.py @@ -5,12 +5,12 @@ from policy_harness import ROOT,body,run spec=importlib.util.spec_from_file_location('import_settings',BASE/'tools/import_settings.py') m=importlib.util.module_from_spec(spec);spec.loader.exec_module(m) result,deferred=m.merge({'configVersion':1,'reportIntervalSeconds':20.0,'supportSquadLimit':2,'responseRadiusMetres':1500,'convoyCount':3},{'aiIntelChancePercent':0,'intelRevealChancePercent':100}) -assert result==dict(reportIntervalSeconds=20,supportSquadLimit=2,responseRadiusMetres=1500,aiIntelChancePercent=0,intelRevealChancePercent=100,radioDefenceSeconds=180,startTimeMinutes=840,timeMultiplier=1,startDateCode=0,weatherProfile=0,stingerChanceOneIn=15,automaticConvoyEnabled=1) -assert deferred==['ai:convoyCount=3 mapped to automaticConvoyEnabled=1; successor capped at one initial convoy'] +assert result==dict(reportIntervalSeconds=20,supportSquadLimit=2,responseRadiusMetres=1500,aiIntelChancePercent=0,intelRevealChancePercent=100,radioDefenceSeconds=180,startTimeMinutes=840,timeMultiplier=1,startDateCode=0,weatherProfile=0,stingerChanceOneIn=15,automaticConvoyEnabled=1,convoyCount=3,heliTimerMinutes=15) +assert deferred==[] for count in (0,1,3,20): values,notes=m.merge(ai={'convoyCount':count}) assert values['automaticConvoyEnabled']==int(count>0) - assert bool(notes)==(count>1) + assert values['convoyCount']==count and not notes for invalid in (-1,21,True,False,None,'1',1.5,float('nan'),float('inf')): try:m.merge(ai={'convoyCount':invalid}) except ValueError:pass @@ -38,7 +38,7 @@ with tempfile.TemporaryDirectory() as tmp: legacy=Path(tmp)/'legacy-ai.json';legacy.write_text('{"convoyCount":3}');original=legacy.read_bytes() preview=subprocess.run([sys.executable,str(BASE/'tools/import_settings.py'),'--ai',str(legacy)],capture_output=True,text=True,check=True) assert json.loads(preview.stdout)['automaticConvoyEnabled']==1 - assert 'successor capped at one initial convoy' in preview.stderr and legacy.read_bytes()==original + assert json.loads(preview.stdout)['convoyCount']==3 and not preview.stderr and legacy.read_bytes()==original # Test the actual runtime validator against the migration schema at each boundary. validator=body(BASE/'addons/core/Scripts/Game/ERR/00_Core/ERR_Settings.c','static bool Valid(').replace('string key','std::string key') diff --git a/tests/test_site_discovery_policy.py b/tests/test_site_discovery_policy.py index 206a9e8..5c44a7d 100644 --- a/tests/test_site_discovery_policy.py +++ b/tests/test_site_discovery_policy.py @@ -6,7 +6,7 @@ methods = '\n'.join(body(source, sig) for sig in ( 'static float RadioRadiusLimit(', 'static bool ValidRadius(', 'static bool InRange(' )).replace('ERR_LocationKind.', 'ERR_LocationKind::') run('''#include -enum class ERR_LocationKind { PRISON, RADIO, EXTRACTION, OUTPOST, DEPOT }; +enum class ERR_LocationKind { PRISON, RADIO, EXTRACTION, OUTPOST, DEPOT, MORTAR }; ''' + methods.replace('int kind,', 'ERR_LocationKind kind,') + ''' int main() { using K=ERR_LocationKind; @@ -14,6 +14,7 @@ int main() { assert(!ValidRadius(K::RADIO,8.01f) && !ValidRadius(K::RADIO,-1)); assert(ValidRadius(K::DEPOT,60) && ValidRadius(K::OUTPOST,60)); assert(!ValidRadius(K::DEPOT,60.01f)); + assert(ValidRadius(K::MORTAR,35) && !ValidRadius(K::MORTAR,61)); assert(ValidRadius(K::PRISON,0) && ValidRadius(K::EXTRACTION,0)); assert(!ValidRadius(K::PRISON,1) && !ValidRadius(K::EXTRACTION,1)); assert(!ValidRadius(static_cast(42),0)); diff --git a/tests/test_supply_convoys.py b/tests/test_supply_convoys.py new file mode 100644 index 0000000..ee884ad --- /dev/null +++ b/tests/test_supply_convoys.py @@ -0,0 +1,251 @@ +"""Execute production supply-circuit and combat timing policies with native boundaries doubled.""" +from policy_harness import ROOT, body, run +import re +D=ROOT/'addons/core/Scripts/Game/ERR/10_AI' + +def cpp(s): + s=re.sub(r'//[^\n]*','',s).replace('protected ','').replace('override ','').replace('foreach (','for (').replace('null','nullptr') + s=s.replace('m_Task.', 'm_Task->').replace('m_Mode.', 'm_Mode->').replace('m_Service.', 'm_Service->') + for typ in ('ERR_SupplyConvoyTask','ERR_ConvoyVehicle','ERR_SupplyTeam','ERR_ForceRoute','IEntity'): + s=re.sub(r'\b'+typ+r' (?=\w)',typ+'* ',s) + for obj in ('task','vehicle','departure','team','lost','boarding','stranded','leg','infantryTeam','member','delayed'): + s=s.replace(obj+'.',obj+'->') + for cls in ('Math','ERR_SupplyConvoyRules','ERR_HQ','ERR_ForceRules','ERR_Actors','vector','string'): + s=s.replace(cls+'.',cls+'::') + s=s.replace('bool surviving, pending;','bool surviving=false, pending=false;') + s=s.replace('float nearest = 400; bool found;', 'float nearest = 400; bool found=false;') + s=s.replace('m_Support[released].', 'm_Support[released]->').replace('Vehicles[released].', 'Vehicles[released]->').replace('infantryTeam->Group.', 'infantryTeam->Group->') + s=s.replace('->Receipt.', '->Receipt->').replace('Vehicles[2].', 'Vehicles[2]->') + s=s.replace('.Entity.', '.Entity->').replace('->Entity.', '->Entity->') + return s +common=r''' +#include +#include +#include +#include +#include +struct string:std::string{using std::string::string;string(std::string s):std::string(s){}templatestatic string Format(T...){return "event";}}; +struct vector{float x=0;static float Distance(vector a,vector b){return std::abs(a.x-b.x);}static float DistanceXZ(vector a,vector b){return Distance(a,b);}}; +templatestruct Array:std::vector{using std::vector::vector;int Count(){return this->size();}}; +namespace Math{int RandomInt(int low,int){return low;}float RandomFloat(float low,float){return low;}} +namespace ERR_HQ{void Event(string,string){}} +namespace ERR_ForceRules{bool Finite(float v){return std::isfinite(v);}bool FiniteVector(vector v){return Finite(v.x);}} +''' +next_base=cpp(body(D/'ERR_SupplyConvoySystem.c','static int NextBase(')) +run(common+'struct ERR_SupplyConvoyRules{'+next_base+r'''}; +struct Entity{vector position;vector GetOrigin(){return position;}}; +struct ERR_ForceRoute{Array points;void Add(vector p){points.push_back(p);}void Seal(){}}; +struct Receipt{string SourceId="test";}; +struct ERR_ConvoyVehicle{bool Released=false,Arrived=false;int cleared=0,RouteIndex=3;struct Entity entity;struct Entity* Entity=&entity; + void ClearOrder(){cleared++;}void Tick(void*,ERR_ForceRoute*,float){}}; +struct ERR_SupplyConvoyTask{Array Vehicles;float TravelDeadline=1000,Departure=0;bool Waiting=false,stopped=false;int LastBase=-1,Legs=0; + Array Bases={{0},{1000},{2000}};ERR_ForceRoute* Route=nullptr;struct Receipt receipt;struct Receipt* Receipt=&receipt; + void Stop(void*,string){stopped=true;}}; +struct Service{void* m_Mode=nullptr; +'''+cpp(body(D/'ERR_SupplyConvoyService.c','protected void Circuit('))+r'''}; +int main(){ + for(int last=0;last<5;last++)for(int roll=0;roll<4;roll++){int next=ERR_SupplyConvoyRules::NextBase(5,last,roll);assert(next>=0&&next<5&&next!=last);} + assert(ERR_SupplyConvoyRules::NextBase(1,0,0)==-1);assert(ERR_SupplyConvoyRules::NextBase(3,3,0)==-1); + Service s;ERR_SupplyConvoyTask t;ERR_ConvoyVehicle a,b;t.Vehicles={&a,&b}; + s.Circuit(&t,999);assert(!t.Waiting&&!a.Arrived);s.Circuit(&t,1000);assert(a.Arrived&&b.Arrived&&t.Waiting&&t.Departure==46000); + s.Circuit(&t,45999);assert(t.Legs==0);s.Circuit(&t,46000);assert(t.Legs==1&&!t.Waiting&&!a.Arrived&&!b.Arrived&&t.LastBase==0&&t.TravelDeadline==646000); + a.entity.position={250};b.entity.position={251};s.Circuit(&t,47000);assert(a.Arrived&&!b.Arrived&&!t.Waiting); + b.entity.position={249};s.Circuit(&t,48000);assert(t.Waiting);s.Circuit(&t,93000);assert(t.LastBase==1&&t.Legs==2); + a.Released=true;b.Released=true;s.Circuit(&t,94000);assert(t.stopped); // no replacements +} +''') +run(common+r''' +struct Group{int GetFaction(){return 1;}};struct IEntity{};struct Mode{int EnemyFaction(){return 1;}}; +namespace ERR_Actors{bool Alive(IEntity*){return true;}struct Group* Group(IEntity*){return nullptr;}} +struct ERR_ConvoyVehicle{bool Released=false;void* Group=nullptr;void* Entity=nullptr;}; +struct ERR_SupplyTeam{bool Released=false,aboard=true,living=true;struct Group nativeGroup;struct Group* Group=&nativeGroup;Array Members;int orders=0;void Clear(){} + bool Aboard(void*,bool required){return aboard==required;}bool Living(){return living;}void Release(void*){Released=true;}void Add(int){orders++;}}; +struct Receipt{string SourceId="test";}; +struct ERR_SupplyConvoyTask{Array Vehicles;Array Teams;struct Receipt receipt;struct Receipt* Receipt=&receipt;}; +struct Tactics{ERR_SupplyConvoyTask* m_Task;Mode mode;Mode* m_Mode=&mode;Arraym_Support;bool m_Stopped=false,m_TruckWithdrawn=false,seeing=false,truck=true; + int m_State=0,starts=0,reorders=0,withdraws=0,finishes=0,m_DismountAttempts=0,flanks=0;float m_NextDismount=0;void Flank(int,bool){flanks++;}float m_LastContact=-1,m_NextOrders=0,m_BoardDeadline=0;vector m_Contact; + bool Observe(void*,vector& p,float&){p={100};return seeing;}void Start(vector p,float){m_Contact=p;m_State=1;m_TruckWithdrawn=false;starts++;} + void Orders(bool,float){reorders++;}bool InfantryAboard(bool required){for(auto t:m_Task->Teams)if(!t->Released&&!t->Aboard(nullptr,required))return false;return true;} + void Support(int i,bool hold){if(i==2&&!hold)withdraws++;}bool Usable(int){return truck;}void Clear(){}int Board(void*,bool){return 1;} + void Finish(float){m_State=0;finishes++;} +'''+cpp(body(D/'ERR_SupplyConvoyTactics.c','void Report('))+cpp(body(D/'ERR_SupplyConvoyTactics.c','bool Tick('))+r'''}; +int main(){ + ERR_SupplyConvoyTask task;ERR_ConvoyVehicle driver;task.Vehicles={&driver,&driver,&driver};ERR_SupplyTeam left,right;task.Teams={&left,&right};Tactics t{&task}; + t.Report({100},std::numeric_limits::quiet_NaN(),0);assert(t.starts==0); + t.Report({100},-1,0);t.Report({100},10,0);t.Report({100},0,60001);assert(t.starts==0); + t.Report({100},1000,1000);assert(t.starts==1&&t.m_State==1);t.Report({0},999,1001);assert(t.m_LastContact==1000); + assert(t.Tick(60999)&&t.m_State==1&&t.withdraws==0);left.aboard=right.aboard=false; + assert(t.Tick(61000)&&t.m_State==2&&t.withdraws==1&&left.orders==1&&right.orders==1&&t.m_BoardDeadline==181000); + assert(t.Tick(180999));left.aboard=true;assert(!t.Tick(181000)&&t.finishes==1&&!left.Released&&right.Released); + right.Released=false;t.Report({100},200000,200000);t.Tick(260000);assert(t.m_State==2); + t.seeing=true;t.Tick(260001);assert(t.m_State==1&&t.starts==3); // fresh contact interrupts reboarding + t.seeing=false;t.truck=false;t.Tick(320001);assert(t.m_State==0&&left.Released&&right.Released); // truck lost: release surviving infantry + t.m_Stopped=true;t.Report({100},400000,400000);assert(t.starts==3&&!t.Tick(400000)); + left.Released=right.Released=false;left.aboard=right.aboard=true;Tactics retry{&task};retry.Report({100},0,0); + for(int i=1;i<=9;i++){retry.Report({100},10000*i,10000*i);retry.Tick(10000*i);} + assert(retry.m_DismountAttempts==6&&retry.flanks==12); // six attempts per still-mounted team, no infinite retry + +} +''') +startup=cpp(body(D/'ERR_SupplyConvoySystem.c','void Tick(')) +run(common+r''' +struct Service{int count=0;int Count(){return count;}}; +struct Startup{Service* m_Service;bool m_Stopped=false,m_Automatic=true,create=false;int m_Target=3,m_Attempts=0,calls=0; + float m_Began=-1,m_Next=0;string m_Reason; + bool StartOne(){calls++;if(create)m_Service->count++;return create;} +'''+startup+r'''}; +int main(){ + Service service;Startup s{&service};s.Tick(1000,true);s.Tick(30999,true);assert(!s.calls);s.Tick(31000,false);assert(!s.calls);s.Tick(36000,true);assert(s.calls==1); + s.create=true;s.Tick(41000,true);s.Tick(46000,true);s.Tick(51000,true);assert(service.count==3&&s.calls==4);s.Tick(56000,true);assert(s.calls==4); + Service noRoad;Startup fail{&noRoad};fail.Tick(0,true);for(int i=0;i<200;i++)fail.Tick(30000+5000*i,true);assert(fail.calls==120&&fail.m_Attempts==120); + Startup off{&noRoad};off.m_Target=0;off.Tick(0,true);off.Tick(30000,true);assert(!off.calls); + off.m_Target=3;off.m_Automatic=false;off.Tick(90000,true);assert(!off.calls); +} +''') +retain=body(D/'ERR_SupplyConvoyTactics.c','static bool Retain(') +retain=retain.replace('IEntity actor','IEntity* actor').replace('IEntity vehicle','IEntity* vehicle') +retain=retain.replace('SCR_VehicleDamageManagerComponent damage = SCR_VehicleDamageManagerComponent.Cast(vehicle.FindComponent(SCR_VehicleDamageManagerComponent));','SCR_VehicleDamageManagerComponent* damage = vehicle->damage;') +for name in ('ERR_Actors','CompartmentAccessComponent','EDamageState'):retain=retain.replace(name+'.',name+'::') +retain=retain.replace('damage.', 'damage->') +run(r""" +#include +#include +enum class EDamageState{UNDAMAGED,DAMAGED,DESTROYED}; +struct SCR_VehicleDamageManagerComponent{float health=1;bool engine=true,gear=true;EDamageState state=EDamageState::UNDAMAGED;float GetHealthScaled(){return health;}bool GetEngineFunctional(){return engine;}bool GetGearboxFunctional(){return gear;}EDamageState GetState(){return state;}}; +struct IEntity{bool player=false,fit=true;IEntity* vehicle=nullptr;SCR_VehicleDamageManagerComponent* damage=nullptr;}; +namespace ERR_Actors{bool Player(IEntity* a){return a->player;}bool CanFight(IEntity* a){return a->fit;}} +namespace CompartmentAccessComponent{IEntity* GetVehicleIn(IEntity* a){return a->vehicle;}} +struct Map:std::map{bool Contains(IEntity* a){return count(a);}IEntity* Get(IEntity* a){return at(a);}}s_Crews; +"""+retain+r""" +int main(){ + IEntity driver,truck,other;SCR_VehicleDamageManagerComponent health;truck.damage=&health;driver.vehicle=&truck; + assert(!Retain(&driver,&truck));s_Crews[&driver]=&truck;assert(Retain(&driver,&truck));assert(!Retain(&driver,&other)); + driver.player=true;assert(!Retain(&driver,&truck));driver.player=false;driver.fit=false;assert(!Retain(&driver,&truck));driver.fit=true; + health.state=EDamageState::DAMAGED;health.health=.9;assert(Retain(&driver,&truck));health.health=.25;assert(!Retain(&driver,&truck));health.health=1; + health.engine=false;assert(!Retain(&driver,&truck));health.engine=true;health.gear=false;assert(!Retain(&driver,&truck));health.gear=true; + health.state=EDamageState::DESTROYED;assert(!Retain(&driver,&truck));health.state=EDamageState::UNDAMAGED;driver.vehicle=nullptr;assert(!Retain(&driver,&truck)); +} +""") +boarding=body(D/'ERR_SupplyConvoyTactics.c','static AIWaypoint Board(') +boarding=boarding.replace('AIWaypoint Board','AIWaypoint* Board').replace('Vehicle truck','Vehicle* truck').replace('truck.', 'truck->').replace('waypoint.', 'waypoint->').replace('specific.', 'specific->').replace('null','nullptr') +boarding=boarding.replace('SCR_BoardingWaypoint waypoint','SCR_BoardingWaypoint* waypoint').replace('SCR_BoardingEntityWaypoint specific','SCR_BoardingEntityWaypoint* specific') +boarding=boarding.replace('SCR_BoardingWaypoint.Cast(', 'dynamic_cast(').replace('SCR_BoardingEntityWaypoint.Cast(', 'dynamic_cast(').replace('ERR_Actors.Spawn','ERR_Actors::Spawn').replace('EAIWaypointCompletionType.All','EAIWaypointCompletionType::All') +run(r""" +#include +#include +using ResourceName=std::string; +enum class EAIWaypointCompletionType{Leader,All}; +struct Vehicle{int GetOrigin(){return 7;}}; +struct AIWaypoint{virtual ~AIWaypoint(){}int radius=9;EAIWaypointCompletionType completion=EAIWaypointCompletionType::Leader;void SetCompletionRadius(int n){radius=n;}void SetCompletionType(EAIWaypointCompletionType type){completion=type;}}; +struct SCR_BoardingWaypoint:AIWaypoint{bool driver=true,gunner=true,cargo=false;void SetAllowance(bool d,bool g,bool c){driver=d;gunner=g;cargo=c;}}; +struct SCR_BoardingEntityWaypoint:SCR_BoardingWaypoint{Vehicle* vehicle=nullptr;void SetEntity(Vehicle* v){vehicle=v;}}; +namespace ERR_Actors{bool fail=false;AIWaypoint* Spawn(ResourceName resource,int){if(fail)return nullptr;if(resource.find("GetIn.et")!=std::string::npos)return new SCR_BoardingEntityWaypoint();return new SCR_BoardingWaypoint();}} +"""+boarding+r""" +int main(){ + Vehicle truck;assert(!Board(nullptr,false)); + auto out=dynamic_cast(Board(&truck,false));assert(out&&out->completion==EAIWaypointCompletionType::All&&out->radius==100&&!out->driver&&!out->gunner&&out->cargo); + auto in=dynamic_cast(Board(&truck,true));assert(in&&in->radius==100&&in->completion==EAIWaypointCompletionType::All&&in->vehicle==&truck&&!in->driver&&!in->gunner&&in->cargo); + delete out;delete in;ERR_Actors::fail=true;assert(!Board(&truck,true)); +} +""") +delivery=body(D/'ERR_SupplyConvoyService.c','override bool ApplyCombatOrder(') +delivery=delivery.replace('override ','').replace('ERR_SupplyConvoyTask.Cast(task)','dynamic_cast(task)') +for typ in ('ERR_ConvoyTask','ERR_SupplyConvoyTask','ERR_ConvoyCombatOrder'):delivery=re.sub(r'\b'+typ+r' (?=\w)',typ+'* ',delivery) +for name in ('supply','order'):delivery=delivery.replace(name+'.',name+'->') +delivery=delivery.replace('Tactics.','Tactics->').replace('super.ApplyCombatOrder','Base::ApplyCombatOrder') +run(r""" +#include +struct ERR_ConvoyTask{virtual ~ERR_ConvoyTask(){}}; +struct ERR_ConvoyCombatOrder{bool Hold=true;int Position=3;float ObservedAt=100;}; +struct Tactics{int state=0,reports=0;int State(){return state;}void Report(int,float,float){reports++;}}; +struct ERR_SupplyConvoyTask:ERR_ConvoyTask{struct Tactics tactics;struct Tactics* Tactics=&tactics;}; +struct Base{bool accept=true;int applied=0;bool ApplyCombatOrder(ERR_ConvoyTask*,ERR_ConvoyCombatOrder*,float){applied++;return accept;}}; +struct Service:Base{ +"""+delivery+r""" +}; +int main(){ + Service service;ERR_SupplyConvoyTask task;ERR_ConvoyCombatOrder order; + for(int state=0;state<3;state++){task.tactics.state=state;assert(service.ApplyCombatOrder(&task,&order,100));} + assert(task.tactics.reports==3);order.Hold=false;assert(!service.ApplyCombatOrder(&task,&order,100));assert(service.applied==3); + task.tactics.state=0;assert(service.ApplyCombatOrder(&task,&order,100));assert(task.tactics.reports==3); + service.accept=false;order.Hold=true;assert(!service.ApplyCombatOrder(&task,&order,100)&&task.tactics.reports==3); + assert(!service.ApplyCombatOrder(nullptr,&order,100));assert(!service.ApplyCombatOrder(&task,nullptr,100)); +} +""") +print('PASS: actual supply route cycling/arrival/stops, finite startup bounds, contact freshness, dismount hold, quiet interval, interrupted boarding, timeout and lost-truck release') + +# Mounted groups retain their native spawn origin; sighting distance must follow vehicles. +distance=cpp(body(D/'ERR_SupplyConvoyTactics.c','protected float DistanceToConvoy(')).replace('Math.Min','Math::Min') +observe=cpp(body(D/'ERR_SupplyConvoyTactics.c','protected bool Observe(')) +for typ in ('SCR_AIGroup','SCR_AIGroupPerception','PerceptionManager','SCR_AITargetInfo'): + observe=re.sub(r'\b'+typ+r' (?=\w)',typ+'* ',observe) +for obj in ('group','perception','manager','target'):observe=observe.replace(obj+'.',obj+'->') +observe=observe.replace('out vector position','vector& position').replace('inout float nearest','float& nearest').replace('bool found;','bool found=false;') +observe=observe.replace('GetGroupUtilityComponent().','GetGroupUtilityComponent()->').replace('GetFaction().','GetFaction()->').replace('GetGame().','GetGame()->').replace('EAITargetInfoCategory.','EAITargetInfoCategory::') +run(common+r""" +namespace Math{float Min(float a,float b){return a Vehicles;}; +struct Faction{bool hostile=true;bool IsFactionEnemy(Faction* other){return other->hostile;}}; +enum class EAITargetInfoCategory{IDENTIFIED,SUSPECTED}; +struct SCR_AITargetInfo{void* m_Entity=this;Faction* m_Faction=nullptr;float m_fTimestamp=10;EAITargetInfoCategory m_eCategory=EAITargetInfoCategory::IDENTIFIED;vector m_vWorldPos={5100};}; +struct SCR_AIGroupPerception{Array m_aTargets;}; +struct Utility{SCR_AIGroupPerception* m_Perception=nullptr;bool allowed=true;bool IsPositionAllowed(vector){return allowed;}}; +struct SCR_AIGroup{Faction faction;Utility utility;Utility* GetGroupUtilityComponent(){return &utility;}Faction* GetFaction(){return &faction;}vector GetOrigin(){return {0};}}; +struct PerceptionManager{float now=10;float GetTime(){return now;}}; +struct Game{PerceptionManager manager;PerceptionManager* GetPerceptionManager(){return &manager;}}game; +Game* GetGame(){return &game;} +struct Observer{ERR_SupplyConvoyTask* m_Task; +"""+distance+observe+r""" +}; +int main(){ + Entity car{{5000}},lost{{0}};ERR_ConvoyVehicle live{false,&car},released{true,&lost};ERR_SupplyConvoyTask task{{&live,&released}};Observer observer{&task}; + Faction enemy;SCR_AITargetInfo target;target.m_Faction=&enemy;SCR_AIGroupPerception perception{{&target}};SCR_AIGroup group;group.utility.m_Perception=&perception; + vector position;float nearest=400;assert(observer.Observe(&group,position,nearest)&&position.x==5100&&nearest==100); + target.m_vWorldPos={100};nearest=400;assert(!observer.Observe(&group,position,nearest)); // stale group/spawn origin is irrelevant + target.m_vWorldPos={5401};assert(!observer.Observe(&group,position,nearest));target.m_vWorldPos={5100}; + target.m_eCategory=EAITargetInfoCategory::SUSPECTED;assert(!observer.Observe(&group,position,nearest));target.m_eCategory=EAITargetInfoCategory::IDENTIFIED; + target.m_fTimestamp=4;assert(!observer.Observe(&group,position,nearest));target.m_fTimestamp=11;assert(!observer.Observe(&group,position,nearest));target.m_fTimestamp=5; + assert(observer.Observe(&group,position,nearest));nearest=400;enemy.hostile=false;assert(!observer.Observe(&group,position,nearest));enemy.hostile=true; + group.utility.allowed=false;assert(!observer.Observe(&group,position,nearest));group.utility.allowed=true; + live.Released=true;assert(!observer.Observe(&group,position,nearest));assert(!observer.Observe(nullptr,position,nearest)); +} +""") +retain_group=body(D/'ERR_SupplyConvoyTactics.c','static bool RetainGroup(') +retain_group=retain_group.replace('SCR_AIGroup group','SCR_AIGroup* group').replace('IEntity vehicle','IEntity* vehicle').replace('IEntity leader','IEntity* leader').replace('group.','group->').replace('CompartmentAccessComponent.','CompartmentAccessComponent::') +source=(D/'ERR_SupplyConvoyTactics.c').read_text() +overrides=[] +for cls in ('SCR_AIGetOutVehicle','SCR_AIGetOutActivity'): + section=source[source.index('modded class '+cls):];section=section[:section.index('\nclass ') if '\nclass ' in section else len(section)] + for method in ('CustomEvaluate','EvaluatePriorityLevel'): + # Each method's exact production body, selecting only this class's first occurrence. + a=section.index('override float '+method+'(');b=section.index('\n }',a)+3 + method_source=section[a:b].replace('override ','').replace('m_Utility.','m_Utility->').replace('ERR_ConvoyMountedCrew.','ERR_ConvoyMountedCrew::').replace('super.','Base::') + overrides.append(method_source) +run(r""" +#include +struct IEntity{bool held=false;IEntity* vehicle=nullptr;}; +struct SCR_AIGroup{int players=0;IEntity* leader=nullptr;int GetPlayerCount(bool){return players;}IEntity* GetLeaderEntity(){return leader;}}; +namespace CompartmentAccessComponent{IEntity* GetVehicleIn(IEntity* actor){return actor->vehicle;}} +struct ERR_ConvoyMountedCrew{static bool Retain(IEntity* actor,IEntity* vehicle){return actor&&actor->held&&vehicle&&actor->vehicle==vehicle;} +"""+retain_group+r""" +}; +struct Utility{IEntity* m_OwnerEntity;SCR_AIGroup* m_Owner;}; +struct Base{float CustomEvaluate(){return 1162;}float EvaluatePriorityLevel(){return 1000;}}; +struct Individual:Base{Utility* m_Utility=nullptr;struct{IEntity* m_Value=nullptr;}m_Vehicle; +"""+''.join(overrides[:2])+r""" +}; +struct Activity:Base{Utility* m_Utility=nullptr;struct{IEntity* m_Value=nullptr;}m_Vehicle; +"""+''.join(overrides[2:])+r""" +}; +int main(){ + IEntity truck,driver{true,&truck};SCR_AIGroup group{0,&driver};Utility utility{&driver,&group};Individual individual;Activity activity; + individual.m_Utility=&utility;individual.m_Vehicle.m_Value=&truck;activity.m_Utility=&utility;activity.m_Vehicle.m_Value=&truck; + assert(individual.CustomEvaluate()==0&&individual.EvaluatePriorityLevel()==0);assert(activity.CustomEvaluate()==0&&activity.EvaluatePriorityLevel()==0); + assert(ERR_ConvoyMountedCrew::RetainGroup(&group,nullptr));group.players=1;assert(activity.CustomEvaluate()==1162&&activity.EvaluatePriorityLevel()==1000);group.players=0; + driver.held=false;assert(individual.CustomEvaluate()==1162&&individual.EvaluatePriorityLevel()==1000);assert(activity.CustomEvaluate()==1162&&activity.EvaluatePriorityLevel()==1000); + group.leader=nullptr;assert(!ERR_ConvoyMountedCrew::RetainGroup(&group,&truck));assert(!ERR_ConvoyMountedCrew::RetainGroup(nullptr,&truck)); +} +""") +print('PASS: moving-convoy perception boundaries and scoped individual/group abandonment priorities') diff --git a/tests/test_vehicle_maintenance_stock.py b/tests/test_vehicle_maintenance_stock.py index 9b189ef..ad92f76 100644 --- a/tests/test_vehicle_maintenance_stock.py +++ b/tests/test_vehicle_maintenance_stock.py @@ -21,7 +21,7 @@ for name,site in sites.items(): stock[name].append((ref[1],ref[2],count,item)) assert sum(item[2] for items in stock.values() for item in items)<=256 # Both established routes to radio intel and the prison field map remain usable. -for name in ('everon-supply-1','everon-supply-2'): +for name in ('everon-supply-1','everon-medical-1'): assert 'RevealOnEscape 1' in sites[name] clues=[i for i in stock[name] if i[1]=='Prefabs/ERR/ObjectiveDocument.et'] assert sum(i[2] for i in clues)>=2 and all('TargetId "everon-radio-1"' in i[3] for i in clues) @@ -29,8 +29,11 @@ assert any(i[1].endswith('PaperMap_01_folded.et') for i in stock['everon-prison- kitpath='Prefabs/ERR/Items/EmergencyRepairKit.et' canpath='Prefabs/Items/Fuel/Jerrycan_01/Jerrycan_01_item.et' maintenance=[(name,i) for name,items in stock.items() for i in items if i[1] in (kitpath,canpath)] -assert len(maintenance)==2 and all(name=='everon-supply-2' for name,_ in maintenance) -assert {i[1]:i[2] for _,i in maintenance}=={kitpath:1,canpath:2} +assert 'everon-supply-2' not in sites +assert not maintenance +assert all('Transport ERR_SiteTransport' not in site for site in sites.values()) +assert 'RequireAirfield 1' in sites['everon-extraction-1'] +assert 'Position 4800.953 0 11487.412' in sites['everon-extraction-1'] # Own container must be finite and must not turn off native resource eligibility. kit=(R/'addons/core'/kitpath).read_text() assert kit.startswith('GenericEntity : "{33B2DFDCD0EBA3DB}Prefabs/Items/Equipment/Kits/RepairKit_01/RepairKit_01_wrench.et"') @@ -38,10 +41,10 @@ assert kit.count('SCR_ResourceContainer ')==1 and 'm_fResourceValueCurrent 20' i for forbidden in ('m_aGenerators','m_aDisabledResourceTypes','m_eFactionUsageCheck','m_fMaxHealScaled','SCR_RepairSupportStationComponent','SCR_ResourceConsumer '): assert forbidden not in kit,forbidden meta=(R/'addons/core'/Path(kitpath+'.meta')).read_text();guid=re.search(r'Name "\{([A-F0-9]{16})\}',meta)[1] -assert [i[0] for _,i in maintenance if i[1]==kitpath]==[guid] +assert guid=='C09C7C97EFA34909' vanilla=json.loads((R/'docs/vanilla-resources.json').read_text()) assert vanilla[canpath]=='12D5AD21E383B768' assert vanilla['Prefabs/Items/Equipment/Kits/RepairKit_01/RepairKit_01_wrench.et']=='33B2DFDCD0EBA3DB' evidence=json.loads((R/'docs/vehicle-maintenance-source-evidence.json').read_text()) assert evidence['finite_initial_stock']['litres_per_can']==5 and evidence['native_validation']=='pending' -print('PASS: finite maintenance stock/resource identity, bounded scenario stock and preserved two-cache clue redundancy; native interaction not claimed') +print('PASS: removed guarded vehicle cache and maintenance stock, airfield-only extraction config, and two remaining finite radio-clue sources') diff --git a/tools/check.py b/tools/check.py index 2699f49..1ec543a 100644 --- a/tools/check.py +++ b/tools/check.py @@ -72,7 +72,7 @@ def check(): assert set(mapped)==set(inventory['script_paths']), 'Original inventory has untracked or unknown entries' print(f'PASS: {len(mapped)} original script entries tracked across {len(feature_ids)} unfinished responsibilities') print(f'PASS: {len(ids)} isolated addons, acyclic dependencies, {len(resources)} unique resources, exact vanilla/authorized external references') - for name in ['test_hq_road_intercept.py', 'test_hq_delivered_task.py', 'test_hq_local_handoff.py', 'test_hq_local_handoff_intake.py', 'test_native_local_handoff_probe.py', 'test_infantry_resupply_waypoints.py', 'test_infantry_placement_settle.py', 'test_native_infantry_fixture_lifecycle.py', 'test_infantry_ammo_access.py', 'test_infantry_resupply_planning.py', 'test_enemy_gunner_skill.py', 'test_native_memory_deadlines.py', 'test_convoy_auto_settings.py', 'test_convoy_startup.py', 'test_failure_result_refresh.py', 'test_infantry_resupply_coordinator.py', 'test_infantry_ammo_transfer.py', 'test_hq_ammo_reporting.py', 'test_enemy_radio.py', 'test_native_maintenance_stock.py', 'test_packed_external_game.py', 'test_hq_radio_node.py', 'test_vehicle_maintenance_stock.py', 'test_vehicle_entry_diagnostics.py', 'test_vehicle_security_native_probe.py', 'test_vehicle_security.py', 'test_native_convoy_cover_probe.py', 'test_enemy_optics.py', 'test_convoy_combat.py', 'test_ai_stinger_admin.py', 'test_hq_ammo_dispatch.py', 'test_hq_convoy_combat.py', 'test_hq_ammo_sampler.py', 'test_native_hq_body_probe.py', 'test_hq_delivered_casualties.py', 'test_external_profile_review.py', 'test_hq_uplink_fairness.py', 'test_actor_group.py', 'test_native_package_external.py', 'test_native_convoy_probe.py', 'test_convoy_placement.py', 'test_convoy_road_plan.py', 'test_hq_convoy_dispatch.py', 'test_convoy_admission.py', 'test_convoy_dispatch.py', 'test_convoy_lifecycle.py', 'test_convoy_budget.py', 'test_hq_body_observer.py', 'test_hq_status_sampler.py', 'test_hq_watch.py', 'test_hq_assignment_lifecycle.py', 'test_force_ledger.py', 'test_enemy_equipment.py', 'test_hq_doctrine.py', 'test_hq_coverage.py', 'test_hq_pursuit.py', 'test_hq_memory.py', 'test_external_addons.py', 'test_admin_tick_delivery.py', 'test_project_schema.py', 'test_admin_session.py', 'test_admin_providers.py', 'test_admin_menu.py', 'test_admin_player_tools.py', 'test_intel_admin.py', 'test_intel_reroll.py', 'test_intel_discovery_feedback.py', 'test_hq_report_selection.py', 'test_casualty_feedback.py', 'test_initial_admission_exhaustion.py', 'test_prison_held_action_proof.py', 'test_prison_held_action_evidence.py', 'test_prison_held_input_adapter.py', 'test_prison_held_runner.py', 'test_prison_coarse_facing.py', 'test_aircraft_field_probe.py', 'test_aircraft_field_runner.py', 'test_aircraft_field_rules.py', 'test_aircraft_field_envelope.py', 'test_aircraft_field_flight.py', 'test_command_maintenance.py', 'test_aircraft_service.py', 'test_aircraft_service_cancel_runner.py', 'test_prison_action_selection_proof.py', 'test_prison_action_selection_evidence.py', 'test_ordinary_gate_choices.py', 'test_aircraft_control_bridge.py', 'test_prison_alignment_proof.py', 'test_prison_alignment_evidence.py', 'test_aircraft_route_demand.py', 'test_prison_approach_proof.py', 'test_prison_approach_evidence.py', 'test_ordinary_gate_evidence.py', 'test_ordinary_gate_observer.py', 'test_ordinary_look_observer.py', 'test_ordinary_look_evidence.py', 'test_relative_look_runner.py', 'test_radio_waiting_text.py', 'test_inventory_control_runner.py', 'test_inventory_layout.py', 'test_headless_input_proof.py', 'test_headless_input_exercise_runner.py', 'test_private_prefix_cleanup.py', 'test_runner_private_cleanup.py', 'test_ordinary_input_runner.py', 'test_ordinary_input_observer.py', 'test_aircraft_route_envelope.py', 'test_aircraft_route_policy.py', 'test_aircraft_route_probe.py', 'test_rough_intel_feedback.py', 'test_headless_display_probe.py', 'test_headless_display_runner.py', 'test_preparation_status.py', 'test_hint_delivery.py', 'test_native_end_lifecycle.py', 'test_native_end_runner.py', 'test_escape_result_wording.py', 'test_native_stats.py', 'test_aircraft_translation.py', 'test_spawn_retry_budget.py', 'test_action_feedback.py', 'test_native_aircraft_control.py', 'test_aircraft_flight_policy.py', 'test_aircraft_flight_envelope.py', 'test_ordinary_screenshot.py', 'test_participant_selection.py', 'test_native_shared_map_ownership.py', 'test_shared_map_ownership.py', 'test_intel_registration.py', 'test_mortar_activity_completion.py', 'test_packed_chat_game.py', 'test_native_mortar_refresh.py', 'test_archive_packed.py', 'test_mortar_refresh.py', 'test_packed_core_game.py', 'test_pak_inventory.py', 'test_native_mortar_salvo.py', 'test_spectator_guidance.py', 'test_native_package.py', 'test_item_station_teardown.py', 'test_source_bundle.py', 'test_native_flight_footprint.py', 'test_native_flight_input_diagnostics.py', 'test_mortar_logistics.py', 'test_mortar_courier_storage.py','test_powered_flight_pad.py','test_prison_escape_policy.py','test_powered_flight_policy.py','test_flight_action_runner.py','test_native_local_admission_probe.py','test_mortar_report_ledger.py','test_dedicated_native.py','test_native_mortar_transfer.py','test_mortar_aim_renewal.py','test_dedicated_preflight.py','test_mortar_transactions.py','test_native_mortar_probe.py','test_diagnostic_no_splash.py','test_casualty_incapacitation.py','test_casualty_remove_probe.py','test_extraction_placement_policy.py','test_guard_cancellation_policy.py','test_casualty_ground_policy.py','test_casualty_reservation_death.py','test_casualty_loading_policy.py','test_initial_guard_policy.py','test_headless_game_runner.py','test_vanilla_game_control.py','test_archive_game_control.py','test_site_discovery_policy.py','test_faction_catalog_scope.py','test_mission_rules.py','test_admin_setting_policy.py', 'test_player_admission_policy.py','test_progression_identity.py','test_discovery_map_position.py','test_local_admission.py','test_prison_placement_policy.py', 'test_recovery_policy.py','test_time_policy.py','test_environment_policy.py','test_environment_restart_runner.py', 'test_inventory_enumeration_policy.py','test_radio_defence_policy.py','test_radio_feedback_policy.py','test_performance_comparison.py','test_release_check.py','test_settings_migration.py','hq_network_regression.py','helicopter_availability_regression.py','mortar_salvo_regression.py']: + for name in ['test_hunter_lifecycle.py', 'test_enemy_awareness.py', 'test_intel_body_inspection.py', 'test_air_support_policy.py', 'test_air_logistics_orders.py', 'test_air_recon.py', 'test_scouts.py', 'test_mortar_station.py', 'test_random_settings.py', 'test_debug_ai.py', 'test_generated_sites.py', 'test_faction_selection.py', 'test_content_policy.py', 'test_hq_road_intercept.py', 'test_hq_delivered_task.py', 'test_hq_local_handoff.py', 'test_hq_local_handoff_intake.py', 'test_native_local_handoff_probe.py', 'test_infantry_resupply_waypoints.py', 'test_infantry_placement_settle.py', 'test_native_infantry_fixture_lifecycle.py', 'test_infantry_ammo_access.py', 'test_infantry_resupply_planning.py', 'test_enemy_gunner_skill.py', 'test_native_memory_deadlines.py', 'test_convoy_auto_settings.py', 'test_convoy_startup.py', 'test_failure_result_refresh.py', 'test_infantry_resupply_coordinator.py', 'test_infantry_ammo_transfer.py', 'test_hq_ammo_reporting.py', 'test_enemy_radio.py', 'test_native_maintenance_stock.py', 'test_packed_external_game.py', 'test_hq_radio_node.py', 'test_vehicle_maintenance_stock.py', 'test_vehicle_entry_diagnostics.py', 'test_vehicle_security_native_probe.py', 'test_vehicle_security.py', 'test_native_convoy_cover_probe.py', 'test_enemy_optics.py', 'test_convoy_combat.py', 'test_ai_stinger_admin.py', 'test_hq_ammo_dispatch.py', 'test_hq_convoy_combat.py', 'test_hq_ammo_sampler.py', 'test_native_hq_body_probe.py', 'test_hq_delivered_casualties.py', 'test_external_profile_review.py', 'test_hq_uplink_fairness.py', 'test_actor_group.py', 'test_native_package_external.py', 'test_native_convoy_probe.py', 'test_convoy_placement.py', 'test_convoy_road_plan.py', 'test_hq_convoy_dispatch.py', 'test_convoy_admission.py', 'test_convoy_dispatch.py', 'test_convoy_lifecycle.py', 'test_convoy_budget.py','test_supply_convoys.py', 'test_hq_body_observer.py', 'test_hq_status_sampler.py', 'test_hq_watch.py', 'test_hq_assignment_lifecycle.py', 'test_force_ledger.py', 'test_enemy_equipment.py', 'test_hq_doctrine.py', 'test_hq_coverage.py', 'test_hq_pursuit.py', 'test_hq_memory.py', 'test_external_addons.py', 'test_admin_tick_delivery.py', 'test_project_schema.py', 'test_admin_session.py', 'test_admin_providers.py', 'test_admin_menu.py', 'test_admin_player_tools.py', 'test_intel_admin.py', 'test_intel_reroll.py', 'test_intel_discovery_feedback.py', 'test_hq_report_selection.py', 'test_casualty_feedback.py', 'test_initial_admission_exhaustion.py', 'test_prison_held_action_proof.py', 'test_prison_held_action_evidence.py', 'test_prison_held_input_adapter.py', 'test_prison_held_runner.py', 'test_prison_coarse_facing.py', 'test_aircraft_field_probe.py', 'test_aircraft_field_runner.py', 'test_aircraft_field_rules.py', 'test_aircraft_field_envelope.py', 'test_aircraft_field_flight.py', 'test_command_maintenance.py', 'test_aircraft_service.py', 'test_aircraft_service_cancel_runner.py', 'test_prison_action_selection_proof.py', 'test_prison_action_selection_evidence.py', 'test_ordinary_gate_choices.py', 'test_aircraft_control_bridge.py', 'test_prison_alignment_proof.py', 'test_prison_alignment_evidence.py', 'test_aircraft_route_demand.py', 'test_prison_approach_proof.py', 'test_prison_approach_evidence.py', 'test_ordinary_gate_evidence.py', 'test_ordinary_gate_observer.py', 'test_ordinary_look_observer.py', 'test_ordinary_look_evidence.py', 'test_relative_look_runner.py', 'test_radio_waiting_text.py', 'test_inventory_control_runner.py', 'test_inventory_layout.py', 'test_headless_input_proof.py', 'test_headless_input_exercise_runner.py', 'test_private_prefix_cleanup.py', 'test_runner_private_cleanup.py', 'test_ordinary_input_runner.py', 'test_ordinary_input_observer.py', 'test_aircraft_route_envelope.py', 'test_aircraft_route_policy.py', 'test_aircraft_route_probe.py', 'test_rough_intel_feedback.py', 'test_headless_display_probe.py', 'test_headless_display_runner.py', 'test_preparation_status.py', 'test_hint_delivery.py', 'test_native_end_lifecycle.py', 'test_native_end_runner.py', 'test_escape_result_wording.py', 'test_native_stats.py', 'test_aircraft_translation.py', 'test_spawn_retry_budget.py', 'test_action_feedback.py', 'test_native_aircraft_control.py', 'test_aircraft_flight_policy.py', 'test_aircraft_flight_envelope.py', 'test_ordinary_screenshot.py', 'test_participant_selection.py', 'test_native_shared_map_ownership.py', 'test_shared_map_ownership.py', 'test_intel_registration.py', 'test_mortar_activity_completion.py', 'test_packed_chat_game.py', 'test_native_mortar_refresh.py', 'test_archive_packed.py', 'test_mortar_refresh.py', 'test_packed_core_game.py', 'test_pak_inventory.py', 'test_native_mortar_salvo.py', 'test_spectator_guidance.py', 'test_native_package.py', 'test_item_station_teardown.py', 'test_source_bundle.py', 'test_native_flight_footprint.py', 'test_native_flight_input_diagnostics.py', 'test_mortar_logistics.py', 'test_mortar_courier_storage.py','test_powered_flight_pad.py','test_prison_escape_policy.py','test_powered_flight_policy.py','test_flight_action_runner.py','test_native_local_admission_probe.py','test_mortar_report_ledger.py','test_dedicated_native.py','test_native_mortar_transfer.py','test_mortar_aim_renewal.py','test_dedicated_preflight.py','test_mortar_transactions.py','test_native_mortar_probe.py','test_diagnostic_no_splash.py','test_casualty_incapacitation.py','test_casualty_remove_probe.py','test_extraction_placement_policy.py','test_guard_cancellation_policy.py','test_casualty_ground_policy.py','test_casualty_reservation_death.py','test_casualty_loading_policy.py','test_initial_guard_policy.py','test_headless_game_runner.py','test_vanilla_game_control.py','test_archive_game_control.py','test_site_discovery_policy.py','test_faction_catalog_scope.py','test_mission_rules.py','test_admin_setting_policy.py', 'test_player_admission_policy.py','test_progression_identity.py','test_discovery_map_position.py','test_local_admission.py','test_prison_placement_policy.py', 'test_recovery_policy.py','test_time_policy.py','test_environment_policy.py','test_environment_restart_runner.py', 'test_inventory_enumeration_policy.py','test_radio_defence_policy.py','test_radio_feedback_policy.py','test_performance_comparison.py','test_release_check.py','test_settings_migration.py','hq_network_regression.py','helicopter_availability_regression.py','mortar_salvo_regression.py']: subprocess.run([sys.executable,str(ROOT/'tests'/name)],check=True) print('All repository checks passed. Native compilation and multiplayer tests are separate requirements.') if __name__=='__main__':check() diff --git a/tools/external_addons.py b/tools/external_addons.py index 9add7b5..5f07e99 100644 --- a/tools/external_addons.py +++ b/tools/external_addons.py @@ -4,8 +4,9 @@ Never copy third-party assets or expose the whole workshop tree to Workbench. from pathlib import Path, PurePosixPath import hashlib,json,re,stat BASE='58D0FB3206B6F859' -DIRECT=('595F2BF2F44836FB','629B2BA37EFFD577','5E524E4FEECCA92B') +DIRECT=('595F2BF2F44836FB','629B2BA37EFFD577','5E524E4FEECCA92B','65930CB4CD0237B2') ALLOWED={ + '65930CB4CD0237B2':{BASE}, '595F2BF2F44836FB':{BASE,'1337C0DE5DABBEEF','BADC0DEDABBEDA5E'}, '1337C0DE5DABBEEF':{BASE},'BADC0DEDABBEDA5E':{BASE}, '629B2BA37EFFD577':{BASE},'5E389BB9F58B79A6':{BASE,'629B2BA37EFFD577'}, diff --git a/tools/headless_workbench.py b/tools/headless_workbench.py index a709987..39a95bc 100644 --- a/tools/headless_workbench.py +++ b/tools/headless_workbench.py @@ -14,7 +14,7 @@ p.add_argument('--steam', type=Path, default=Path.home()/'.local/share/Steam') p.add_argument('--external-addons', type=Path, help='Installed RHS/WCS/BMP source root; expose only audited closure in a separate Chat profile') p.add_argument('--compat', type=Path, required=True, help='Disposable cloned Proton compatdata directory outside Steam') p.add_argument('--profile', type=Path, required=True, help='Separate disposable successor Workbench profile') -p.add_argument('--smoke', choices=['hq-local-handoff', 'infantry-transfer', 'hq-body', 'convoy', 'hq-memory', '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'], default='victory') +p.add_argument('--smoke', choices=['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', 'hq-memory', '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'], default='victory') p.add_argument('--convoy-cover', action='store_true', help='After convoy driving, arrange the existing prisoner to verify native sighting/radio HOLD and RESUME') p.add_argument('--field-terrain-audit', action='store_true', help='After a fixed aircraft-field survey refusal, log one read-only 1681-node coarse terrain grid; never selects or qualifies a corridor') p.add_argument('--field-service-cancel', action='store_true', help='Explicit aircraft-field variant: Stop the original retained service during measured cruise; requires physical cancellation landing') @@ -23,10 +23,12 @@ p.add_argument('--station-teardown-diagnostics', action='store_true', help='Opt- p.add_argument('--flight-autohover', action='store_true', help='Opt-in owned native helicopter autohover experiment; requires Core powered-flight and actor-local action inputs') p.add_argument('--flight-action-inputs', action='store_true', help='Experimental exact-AI ActionManager inputs; Core powered-flight fixture only') p.add_argument('--flight-input-diagnostics', action='store_true', help='Opt-in read-only powered-flight input/application and native rotor signal observations') +p.add_argument('--recon-takeover-only', action='store_true', help='Air-recon fixture: only native faction handover/release and explicit aircraft deletion') p.add_argument('--rounds', type=int, default=2) p.add_argument('--timeout', type=int, default=360) p.add_argument('--project', choices=['core', 'chat'], default='chat', help='Diagnostic fixture family (both load the combined mod)') a = p.parse_args() +if a.recon_takeover_only and (a.smoke != 'air-recon' or a.project != 'core' or a.rounds != 1): p.error('--recon-takeover-only requires Core air-recon and one round') steam, compat, profile = a.steam.resolve(), a.compat.resolve(), a.profile.resolve() if not 1 <= a.rounds <= 10 or not 60 <= a.timeout <= 1800: p.error('Use 1..10 rounds and a 60..1800 second timeout') @@ -41,6 +43,7 @@ if a.smoke in {'mortar-refresh', 'mortar-salvo', 'mortar-expiry', 'mortar-transf if a.smoke in {'aircraft-field', 'aircraft-route', 'aircraft-control', 'aircraft-cancel', 'aircraft-translate'} and (a.project != 'chat' or a.rounds != 1 or a.timeout < 420): p.error('aircraft-field/aircraft-route/aircraft-control/aircraft-cancel/aircraft-translate requires Chat, one round, and at least 420 seconds') if a.convoy_cover and a.smoke != 'convoy': p.error('--convoy-cover requires --smoke convoy') if a.convoy_cover and a.timeout < 900: p.error('--convoy-cover requires timeout at least900 seconds') +if a.smoke == 'supply-convoys' and (a.project != 'chat' or a.rounds != 1 or a.timeout < 900): p.error('supply-convoys requires Chat, one round, and at least900 seconds') if a.smoke == 'convoy' and (a.project != 'chat' or a.rounds != 1 or a.timeout < 600): p.error('convoy requires Chat, exactly one round, and timeout at least600 seconds') if a.smoke == 'infantry-transfer' and (a.project != 'chat' or a.rounds != 1 or a.timeout < 360): p.error('infantry-transfer requires Chat, one round and timeout at least360 seconds') if a.smoke == 'hq-local-handoff' and (a.project != 'chat' or a.rounds != 1 or a.timeout < 360): p.error('hq-local-handoff requires Chat, one round and timeout at least360 seconds') @@ -111,8 +114,9 @@ if a.station_teardown_diagnostics: command += ['-errStationTeardownDiag', '1'] if a.flight_input_diagnostics: command += ['-errFlightInputDiag', '1'] if a.flight_action_inputs: command += ['-errFlightActionInputs', '1'] if a.flight_autohover: command += ['-errFlightAutohover', '1'] +if a.recon_takeover_only: command += ['-errReconTakeoverOnly', '1'] if a.project == 'core': - if a.smoke not in {'native-end-active', 'native-end-preparing', 'station-teardown', 'prison-breach', 'powered-flight', 'powered-translate', 'local-admission', 'victory', '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'}: p.error('Unsupported Core-only fixture') + if a.smoke not in {'aggression', 'air-logistics', 'air-assault', 'air-recon', 'airfield-markers', 'opening-tools', 'mortar-station', 'generated-sites', 'native-end-active', 'native-end-preparing', 'station-teardown', 'prison-breach', 'powered-flight', 'powered-translate', 'local-admission', 'victory', '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'}: p.error('Unsupported Core-only fixture') command[command.index('-plugin=ERR_ValidateWorldPlugin')] = '-plugin=ERR_ValidateBaseWorldPlugin' command[command.index('-errSmoke')] = '-errBaseSmoke' if a.smoke in {'station-teardown', 'prison-breach', 'powered-flight', 'powered-translate', 'local-admission', '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'} and a.project != 'core': p.error('This fixture requires --project core') diff --git a/tools/import_settings.py b/tools/import_settings.py index e932e03..22a4305 100644 --- a/tools/import_settings.py +++ b/tools/import_settings.py @@ -15,8 +15,10 @@ SCHEMA={ 'weatherProfile':(0,0,3), 'stingerChanceOneIn':(15,0,10000), 'automaticConvoyEnabled':(1,0,1), + 'convoyCount':(3,0,20), + 'heliTimerMinutes':(15,1,1440), } -AI_KEYS=('reportIntervalSeconds','supportSquadLimit','responseRadiusMetres','stingerChanceOneIn','automaticConvoyEnabled') +AI_KEYS=('reportIntervalSeconds','supportSquadLimit','responseRadiusMetres','stingerChanceOneIn','automaticConvoyEnabled','heliTimerMinutes') INTEL_KEYS=('aiIntelChancePercent','intelRevealChancePercent') def merge(ai=None,intel=None): result={key:spec[0] for key,spec in SCHEMA.items()};deferred=[] @@ -38,8 +40,8 @@ def merge(ai=None,intel=None): if type(count) not in (int,float) or not 0<=count<=20 or int(count)!=count: raise ValueError('convoyCount must be an integer in [0,20]') result['automaticConvoyEnabled']=int(count>0) + result['convoyCount']=int(count) recognized.add('convoyCount') - if count>1:deferred.append(f'ai:convoyCount={int(count)} mapped to automaticConvoyEnabled=1; successor capped at one initial convoy') deferred.extend(label+':'+key for key in data if key not in recognized) return result,deferred