modded class ERR_ReaperRHSCompat { bool ProbeResourceLoaded() { return m_Character != null; } } modded class ArmaReforgerScripted { protected int m_ERRCompatStage, m_ERRCompatFailures; protected float m_ERRCompatWait; protected ref array m_ERRCompatActors = {}; protected void CompatAssert(bool pass, string detail) { if (!pass) m_ERRCompatFailures++; PrintFormat("ERR COMPAT TEST pass=%1 %2", pass, detail); } override void OnUpdate(BaseWorld world, float timeslice) { super.OnUpdate(world, timeslice); if (!world || m_ERRCompatStage == 2) return; // MISSION_READY m_ERRCompatWait += timeslice; if (m_ERRCompatWait < 2) return; m_ERRCompatWait=0; bool both = ERR_ReaperRHSCompat.ModsPresent(); bool hasReaper; if ("REAPER_SpectatorCameraHelper".ToType()) hasReaper=true; bool hasRHS; if ("RHS_ThermalSlotManagerComponent".ToType()) hasRHS=true; if (m_ERRCompatStage == 0) { CompatAssert(m_ERRReaperRHSCompat.Applied() == both, "repair active exactly when both mods present"); CompatAssert(m_ERRReaperRHSCompat.ProbeResourceLoaded() == both, "resource untouched when optional pair absent"); CompatAssert(m_ERRReaperRHSCompat.Apply() == both, "second application idempotent"); array prefabs={"{DCB41B3746FDD1BE}Prefabs/Characters/Factions/OPFOR/USSR_Army/Character_USSR_Rifleman.et", "{26A9756790131354}Prefabs/Characters/Factions/BLUFOR/US_Army/Character_US_Rifleman.et"}; if (hasRHS) prefabs.Insert("{B3C496CCFA72D25E}Prefabs/Characters/Factions/OPFOR/RHS_AFRF/MSV/Flora/Character_RHS_RF_MSV_Flora_SL.et"); foreach (ResourceName prefab : prefabs) { EntitySpawnParams params=new EntitySpawnParams();params.TransformMode=ETransformMode.WORLD;params.Transform[3]="3000 20 3000"; IEntity actor=SpawnEntityPrefab(Resource.Load(prefab),world,params);m_ERRCompatActors.Insert(actor); CompatAssert(actor!=null,"spawn "+prefab); } m_ERRCompatStage=1;return; } foreach (IEntity actor : m_ERRCompatActors) { if (!actor) continue; SCR_ChimeraCharacter character=SCR_ChimeraCharacter.Cast(actor); CompatAssert(character && character.GetCharacterController()!=null && !character.GetCharacterController().IsDead(),"complete living character"); array managers={};actor.FindComponents(SlotManagerComponent,managers); if (!hasReaper && !hasRHS) { CompatAssert(managers.Count()==0,"vanilla remains without an added slot manager"); continue; } CompatAssert(managers.Count()==1,"exactly one slot manager"); if (managers.Count()!=1) continue; SlotManagerComponent manager=SlotManagerComponent.Cast(managers[0]); array slots={};manager.GetSlotInfos(slots); EntitySlotInfo body=manager.GetSlotByName("Body"); EntitySlotInfo camera=manager.GetSlotByName("SpectatorCameraHelper"); if (hasRHS) { CompatAssert(manager.Type().ToString()=="RHS_ThermalSlotManagerComponent","RHS manager class preserved"); CompatAssert(slots.Count()>0 && slots[0]==body && body.GetAttachedEntity()!=null,"thermal body still first and attached"); } if (hasReaper) { CompatAssert(camera && camera.GetAttachedEntity()!=null,"spectator camera helper attached"); if (camera && camera.GetAttachedEntity()) CompatAssert(camera.GetAttachedEntity().GetParent()==actor && camera.GetAttachedEntity().Type().ToString()=="REAPER_SpectatorCameraHelper","Reaper camera helper identity and parent preserved"); } else CompatAssert(camera==null,"no Reaper camera introduced when absent"); } m_ERRCompatStage=2; PrintFormat("ERR COMPAT COMPLETE failures=%1 both=%2 reaper=%3 rhs=%4",m_ERRCompatFailures,both,hasReaper,hasRHS); } }