From 647b5f13aa0f3f7a7d29ec71afc1e27886dc0cc3 Mon Sep 17 00:00:00 2001 From: Yoshi Date: Fri, 28 Aug 2026 00:08:25 -0700 Subject: [PATCH 1/2] Fixes spotlight behavior and tevent 35 behavior --- code/blight.cpp | 11 ++++++++++- code/blight.h | 7 +++++++ code/taction.cpp | 42 +++++++++++++++++++++++++++++++++++++++++- code/trigger.cpp | 8 +++++++- 4 files changed, 65 insertions(+), 3 deletions(-) diff --git a/code/blight.cpp b/code/blight.cpp index 7850a58..f2c9231 100644 --- a/code/blight.cpp +++ b/code/blight.cpp @@ -56,6 +56,7 @@ BuildingLightClass::BuildingLightClass(TechnoClass * owner) : RotationPivot(COORD_NONE), RotationTarget(COORD_NONE), Acceleration(0), + IsDetectionSource(false), IsOppositeDirection(false), Behavior(0), Target(NULL), @@ -177,6 +178,8 @@ void BuildingLightClass::AI(void) return; } + bool resumed_sweep = false; + Coord coord = PositionCoord; switch (Behavior) { default: @@ -188,6 +191,8 @@ void BuildingLightClass::AI(void) coord = Lerp(PositionCoord, Target->PositionCoord, 0.25); } else { Set_Behavior_Type(LIGHT_BEHAVIOR_SWEEP); + + resumed_sweep = true; } break; @@ -248,7 +253,7 @@ void BuildingLightClass::AI(void) BuildingClass * owner_building = (Owner->RTTI == RTTI_BUILDING) ? (BuildingClass *)Owner : NULL; - if (Behavior == LIGHT_BEHAVIOR_SWEEP) { + if (Behavior == LIGHT_BEHAVIOR_SWEEP && !resumed_sweep) { if (owner_building != NULL && owner_building->IsActive && owner_building->Is_Powered_On() && owner_building->Tag != NULL) { bool found = false; Cell cell = PositionCell; @@ -272,8 +277,12 @@ void BuildingLightClass::AI(void) } if (found) { + IsDetectionSource = true; + owner_building->Tag->Spring(TEVENT_ENEMY_IN_SPOTLIGHT, owner_building); owner_building->Tag->Spring(TEVENT_ENEMY_IN_SPOTLIGHT_REPEATING, owner_building); + + IsDetectionSource = false; } } } diff --git a/code/blight.h b/code/blight.h index c12e01e..dda6f66 100644 --- a/code/blight.h +++ b/code/blight.h @@ -89,6 +89,13 @@ class BuildingLightClass : public ObjectClass */ double Acceleration; + /* + * Used to ensure that Follow behavior is only applied to the + * spotlight that actually detected the enemy, rather than to + * other spotlights sharing the same trigger/tag. + */ + bool IsDetectionSource; + /* * If the beam is sweeping back the other way along its arc, then this flag will be * true. Alternate lights are created with it already set, so that a row of spotlights diff --git a/code/taction.cpp b/code/taction.cpp index 1eabdc7..da279f9 100644 --- a/code/taction.cpp +++ b/code/taction.cpp @@ -85,6 +85,7 @@ #include "tagtype.h" #include "team.h" #include "teamtype.h" +#include "tevent.h" #include "theme.h" #include "tracker.h" #include "trigger.h" @@ -2045,8 +2046,47 @@ bool TActionClass::TAction_RESHROUD(HouseClass * , ObjectClass * , TriggerClass /// the new behavior, so a scenario can have the searchlights start hunting on cue. /// /// bool; Was at least one spotlight changed? -bool TActionClass::TAction_CHANGE_SPOTLIGHT_BEHAVIOR(HouseClass * , ObjectClass * , TriggerClass * trig, Cell const & ) +bool TActionClass::TAction_CHANGE_SPOTLIGHT_BEHAVIOR(HouseClass * , ObjectClass * object, TriggerClass * trig, Cell const & ) { + bool spotlight_event = false; + + if (trig != NULL && trig->Class != NULL) { + TEventClass* tevent = trig->Class->FirstEvent; + + while (tevent != NULL) { + if (tevent->Event == TEVENT_ENEMY_IN_SPOTLIGHT || tevent->Event == TEVENT_ENEMY_IN_SPOTLIGHT_REPEATING) { + + spotlight_event = true; + break; + } + + tevent = tevent->Next; + } + } + + if (Data.LightBehavior == LIGHT_BEHAVIOR_FOLLOW && spotlight_event) { + if (object == NULL || object->RTTI != RTTI_BUILDING) { + return(false); + } + + BuildingClass* building = (BuildingClass*)object; + + if (building->Strength > 0 && + building->IsActive && + building->IsDown && + !building->IsInLimbo && + building->Class->HasSpotlight && + building->BuildingLight != NULL && + building->BuildingLight->IsDetectionSource) { + + building->BuildingLight->Set_Behavior_Type(LIGHT_BEHAVIOR_FOLLOW); + + return(true); + } + + return(false); + } + bool success = false; for (int index = 0; index < Buildings.Count(); index++) { BuildingClass * ptr = Buildings[index]; diff --git a/code/trigger.cpp b/code/trigger.cpp index cbedf69..e433b98 100644 --- a/code/trigger.cpp +++ b/code/trigger.cpp @@ -293,7 +293,13 @@ bool TriggerClass::Should_Spring(TEventType event, ObjectClass * object, bool fo TEventClass * tevent = Class->FirstEvent; int index = 0; while (tevent != NULL) { - if (Is_Event_Tripped(index) || tevent->operator()(event, House_From_HousesType((HousesType)Class->House->HeapID), object, Timer, persistent, source)) { + bool event_tripped = Is_Event_Tripped(index); + + if (event_tripped && tevent->Event == TEVENT_ENEMY_IN_SPOTLIGHT && Class->FirstEvent->Next == NULL && event != TEVENT_ENEMY_IN_SPOTLIGHT) { + event_tripped = false; + } + + if (event_tripped || tevent->operator()(event, House_From_HousesType((HousesType)Class->House->HeapID), object, Timer, persistent, source)) { if (persistent) { if (tevent->Is_Time_Based() && tevent->Is_To_Flag_As_Tripped()) { Flag_Event_Tripped(index); From 8c33cb8db7609f4a04c74179ec3c91a601ff4568 Mon Sep 17 00:00:00 2001 From: Mitchell Kim <68473890+krnyoshi@users.noreply.github.com> Date: Sat, 29 Aug 2026 01:11:48 -0700 Subject: [PATCH 2/2] fix spotlight follow trigger scoping --- code/blight.cpp | 5 ---- code/blight.h | 7 ------ code/taction.cpp | 65 ++++++++++++++---------------------------------- code/trigger.cpp | 11 +++++++- 4 files changed, 28 insertions(+), 60 deletions(-) diff --git a/code/blight.cpp b/code/blight.cpp index f2c9231..d8def10 100644 --- a/code/blight.cpp +++ b/code/blight.cpp @@ -56,7 +56,6 @@ BuildingLightClass::BuildingLightClass(TechnoClass * owner) : RotationPivot(COORD_NONE), RotationTarget(COORD_NONE), Acceleration(0), - IsDetectionSource(false), IsOppositeDirection(false), Behavior(0), Target(NULL), @@ -277,12 +276,8 @@ void BuildingLightClass::AI(void) } if (found) { - IsDetectionSource = true; - owner_building->Tag->Spring(TEVENT_ENEMY_IN_SPOTLIGHT, owner_building); owner_building->Tag->Spring(TEVENT_ENEMY_IN_SPOTLIGHT_REPEATING, owner_building); - - IsDetectionSource = false; } } } diff --git a/code/blight.h b/code/blight.h index dda6f66..c12e01e 100644 --- a/code/blight.h +++ b/code/blight.h @@ -89,13 +89,6 @@ class BuildingLightClass : public ObjectClass */ double Acceleration; - /* - * Used to ensure that Follow behavior is only applied to the - * spotlight that actually detected the enemy, rather than to - * other spotlights sharing the same trigger/tag. - */ - bool IsDetectionSource; - /* * If the beam is sweeping back the other way along its arc, then this flag will be * true. Alternate lights are created with it already set, so that a row of spotlights diff --git a/code/taction.cpp b/code/taction.cpp index da279f9..c22700c 100644 --- a/code/taction.cpp +++ b/code/taction.cpp @@ -2046,62 +2046,33 @@ bool TActionClass::TAction_RESHROUD(HouseClass * , ObjectClass * , TriggerClass /// the new behavior, so a scenario can have the searchlights start hunting on cue. /// /// bool; Was at least one spotlight changed? -bool TActionClass::TAction_CHANGE_SPOTLIGHT_BEHAVIOR(HouseClass * , ObjectClass * object, TriggerClass * trig, Cell const & ) +bool TActionClass::TAction_CHANGE_SPOTLIGHT_BEHAVIOR(HouseClass*, ObjectClass* object, TriggerClass* trig, Cell const&) { - bool spotlight_event = false; - - if (trig != NULL && trig->Class != NULL) { - TEventClass* tevent = trig->Class->FirstEvent; - - while (tevent != NULL) { - if (tevent->Event == TEVENT_ENEMY_IN_SPOTLIGHT || tevent->Event == TEVENT_ENEMY_IN_SPOTLIGHT_REPEATING) { - - spotlight_event = true; - break; - } - - tevent = tevent->Next; - } - } - - if (Data.LightBehavior == LIGHT_BEHAVIOR_FOLLOW && spotlight_event) { - if (object == NULL || object->RTTI != RTTI_BUILDING) { - return(false); - } - - BuildingClass* building = (BuildingClass*)object; - - if (building->Strength > 0 && - building->IsActive && - building->IsDown && - !building->IsInLimbo && - building->Class->HasSpotlight && - building->BuildingLight != NULL && - building->BuildingLight->IsDetectionSource) { - - building->BuildingLight->Set_Behavior_Type(LIGHT_BEHAVIOR_FOLLOW); - - return(true); - } - - return(false); - } + bool restrict_to_source = + Data.LightBehavior == LIGHT_BEHAVIOR_FOLLOW && + object != NULL && + object->RTTI == RTTI_BUILDING; bool success = false; + for (int index = 0; index < Buildings.Count(); index++) { - BuildingClass * ptr = Buildings[index]; + BuildingClass* ptr = Buildings[index]; + if (ptr->Strength > 0 && - ptr->IsActive && - ptr->IsDown && - !ptr->IsInLimbo && - ptr->Class->HasSpotlight && - ptr->BuildingLight != NULL && - ptr->Tag != NULL && - ptr->Tag->Is_Trigger_Attached(trig)) { + ptr->IsActive && + ptr->IsDown && + !ptr->IsInLimbo && + ptr->Class->HasSpotlight && + ptr->BuildingLight != NULL && + ptr->Tag != NULL && + ptr->Tag->Is_Trigger_Attached(trig) && + (!restrict_to_source || ptr == object)) { + ptr->BuildingLight->Set_Behavior_Type(Data.LightBehavior); success = true; } } + return(success); } diff --git a/code/trigger.cpp b/code/trigger.cpp index e433b98..544b849 100644 --- a/code/trigger.cpp +++ b/code/trigger.cpp @@ -295,7 +295,16 @@ bool TriggerClass::Should_Spring(TEventType event, ObjectClass * object, bool fo while (tevent != NULL) { bool event_tripped = Is_Event_Tripped(index); - if (event_tripped && tevent->Event == TEVENT_ENEMY_IN_SPOTLIGHT && Class->FirstEvent->Next == NULL && event != TEVENT_ENEMY_IN_SPOTLIGHT) { + /* + ** A latched event only helps a persistent trigger when another event + ** still needs to be satisfied. Keep this exception scoped to Event 35 + ** rather than changing latch behavior for other trigger events. + */ + if (event_tripped && + tevent->Event == TEVENT_ENEMY_IN_SPOTLIGHT && + index == 0 && + tevent->Next == NULL && + event != TEVENT_ENEMY_IN_SPOTLIGHT) { event_tripped = false; }