From ae9b6d314b2556d02416ba3d61cbefaa1f8e1c11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B9=9D=E5=8D=83=E5=A4=A9=E5=8D=8E?= <1065703286@qq.com> Date: Sun, 7 Dec 2025 14:54:38 +0800 Subject: [PATCH 1/4] PassSelection --- docs/New-or-Enhanced-Logics.md | 1 + src/Ext/Techno/Hooks.Misc.cpp | 85 ++++++++++++++++++++++++++-- src/New/Type/AttachmentTypeClass.cpp | 2 + src/New/Type/AttachmentTypeClass.h | 2 + 4 files changed, 84 insertions(+), 6 deletions(-) diff --git a/docs/New-or-Enhanced-Logics.md b/docs/New-or-Enhanced-Logics.md index fea18811b5..f5b39738b0 100644 --- a/docs/New-or-Enhanced-Logics.md +++ b/docs/New-or-Enhanced-Logics.md @@ -214,6 +214,7 @@ InheritCommands=true ; boolean InheritCommands.StopCommand=true ; boolean InheritCommands.DeployCommand=true ; boolean LowSelectionPriority=true ; boolean, whether the child is low priority while attached +PassSelection=true ; boolean, whether the child selection propagates to parent TransparentToMouse=false ; boolean, can't click on attached techno if set YSortPosition=default ; Attachment YSort position enumeration - default|underparent|overparent InheritDestruction=true ; boolean diff --git a/src/Ext/Techno/Hooks.Misc.cpp b/src/Ext/Techno/Hooks.Misc.cpp index c4344c0c79..64a863282c 100644 --- a/src/Ext/Techno/Hooks.Misc.cpp +++ b/src/Ext/Techno/Hooks.Misc.cpp @@ -722,15 +722,88 @@ DEFINE_HOOK(0x5F46AE, ObjectClass_Select, 0x7) { GET(ObjectClass*, pThis, ESI); - pThis->IsSelected = true; + TechnoClass* pOriginal = abstract_cast(pThis); + TechnoClass* pFinalTarget = pOriginal; - if (!Phobos::Config::ShowFlashOnSelecting) - return 0; + if (pOriginal) + { + TechnoClass* pCurrent = pOriginal; + while (pCurrent) + { + auto pExt = TechnoExt::ExtMap.Find(pCurrent); + if (!pExt || !pExt->ParentAttachment) + { + pFinalTarget = pCurrent; + break; + } + + auto pType = pExt->ParentAttachment->GetType(); + if (!pType || !pType->PassSelection) + { + pFinalTarget = pCurrent; + break; + } + + TechnoClass* pParent = pExt->ParentAttachment->Parent; + if (!pParent || pParent->IsDead()) + { + pFinalTarget = pCurrent; + break; + } + + pCurrent = pParent; + pFinalTarget = pParent; + } + + if (pFinalTarget && pFinalTarget != pOriginal) + { + for (int i = 0; i < ObjectClass::CurrentObjects.Count; i++) + { + if (ObjectClass::CurrentObjects[i] == pOriginal) + { + int lastIndex = ObjectClass::CurrentObjects.Count - 1; + ObjectClass::CurrentObjects[i] = ObjectClass::CurrentObjects[lastIndex]; + ObjectClass::CurrentObjects.Count--; + break; + } + } - auto const duration = RulesExt::Global()->SelectionFlashDuration; + pOriginal->IsSelected = false; - if (duration > 0 && pThis->GetOwningHouse()->IsControlledByCurrentPlayer()) - pThis->Flash(duration); + bool parentAlreadySelected = false; + for (int i = 0; i < ObjectClass::CurrentObjects.Count; i++) + { + if (ObjectClass::CurrentObjects[i] == pFinalTarget) + { + parentAlreadySelected = true; + break; + } + } + + if (!parentAlreadySelected) + { + ObjectClass::CurrentObjects.AddItem(pFinalTarget); + } + + R->ESI(pFinalTarget); + pThis = pFinalTarget; + } + } + + pThis->IsSelected = true; + + if (Phobos::Config::ShowFlashOnSelecting) + { + auto const duration = RulesExt::Global()->SelectionFlashDuration; + if (duration > 0) + { + TechnoClass* pFlashTarget = abstract_cast(pThis); + if (pFlashTarget && pFlashTarget->GetOwningHouse()->IsControlledByCurrentPlayer()) + { + pFlashTarget->Flash(duration); + } + } + } return 0; } diff --git a/src/New/Type/AttachmentTypeClass.cpp b/src/New/Type/AttachmentTypeClass.cpp index 793a81e361..4165f89bb2 100644 --- a/src/New/Type/AttachmentTypeClass.cpp +++ b/src/New/Type/AttachmentTypeClass.cpp @@ -24,6 +24,7 @@ void AttachmentTypeClass::LoadFromINI(CCINIClass* pINI) this->InheritHeightStatus.Read(exINI, section, "InheritHeightStatus"); this->OccupiesCell.Read(exINI, section, "OccupiesCell"); this->LowSelectionPriority.Read(exINI, section, "LowSelectionPriority"); + this->PassSelection.Read(exINI, section, "PassSelection"); this->TransparentToMouse.Read(exINI, section, "TransparentToMouse"); this->YSortPosition.Read(exINI, section, "YSortPosition"); this->DestructionWeapon_Child.Read(exINI, section, "DestructionWeapon.Child"); @@ -47,6 +48,7 @@ void AttachmentTypeClass::Serialize(T& Stm) .Process(this->InheritHeightStatus) .Process(this->OccupiesCell) .Process(this->LowSelectionPriority) + .Process(this->PassSelection) .Process(this->TransparentToMouse) .Process(this->YSortPosition) .Process(this->DestructionWeapon_Child) diff --git a/src/New/Type/AttachmentTypeClass.h b/src/New/Type/AttachmentTypeClass.h index 838413530c..eb519e8d4d 100644 --- a/src/New/Type/AttachmentTypeClass.h +++ b/src/New/Type/AttachmentTypeClass.h @@ -20,6 +20,7 @@ class AttachmentTypeClass final : public Enumerable Valueable InheritHeightStatus; Valueable OccupiesCell; Valueable LowSelectionPriority; + Valueable PassSelection; Valueable TransparentToMouse; Valueable YSortPosition; Nullable DestructionWeapon_Child; @@ -39,6 +40,7 @@ class AttachmentTypeClass final : public Enumerable , InheritDestruction { true } , InheritHeightStatus { true } , LowSelectionPriority { true } + , PassSelection { true } , TransparentToMouse { false } , YSortPosition { AttachmentYSortPosition::Default } , DestructionWeapon_Child { } From 90853e09895b591a26ae55047cc1bbde9e3c2e61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B9=9D=E5=8D=83=E5=A4=A9=E5=8D=8E?= <1065703286@qq.com> Date: Sun, 7 Dec 2025 21:34:08 +0800 Subject: [PATCH 2/4] Flash fix --- src/Misc/Hooks.AI.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/Misc/Hooks.AI.cpp b/src/Misc/Hooks.AI.cpp index aecb10ca8f..82f62a3d32 100644 --- a/src/Misc/Hooks.AI.cpp +++ b/src/Misc/Hooks.AI.cpp @@ -5,7 +5,24 @@ DEFINE_HOOK(0x55B6B3, LogicClass_AI_After, 0x5) { for (auto const& attachment : AttachmentClass::Array) - attachment->AI(); + { + auto pType = attachment->GetType(); + if (pType && pType->InheritStateEffects && !pType->PassSelection && attachment->Child) + { + int childFlashRemaining = attachment->Child->Flashing.DurationRemaining; + + attachment->AI(); + + if (childFlashRemaining > 0) + { + attachment->Child->Flash(childFlashRemaining); + } + } + else + { + attachment->AI(); + } + } return 0; } From da676b5d4a6d2f86ee266ade135ed17c161cbda6 Mon Sep 17 00:00:00 2001 From: NetsuNegi39 Date: Mon, 8 Dec 2025 14:42:01 +0800 Subject: [PATCH 3/4] replace functions in vtable --- src/Ext/Techno/Hooks.Misc.cpp | 79 ++--------------------- src/Ext/Techno/Hooks.TechnoAttachment.cpp | 47 ++++++++++++++ src/Misc/Hooks.AI.cpp | 19 +----- src/New/Entity/AttachmentClass.cpp | 2 +- 4 files changed, 54 insertions(+), 93 deletions(-) diff --git a/src/Ext/Techno/Hooks.Misc.cpp b/src/Ext/Techno/Hooks.Misc.cpp index 64a863282c..c1c04d92cc 100644 --- a/src/Ext/Techno/Hooks.Misc.cpp +++ b/src/Ext/Techno/Hooks.Misc.cpp @@ -721,87 +721,18 @@ DEFINE_HOOK_AGAIN(0x5F4718, ObjectClass_Select, 0x7) DEFINE_HOOK(0x5F46AE, ObjectClass_Select, 0x7) { GET(ObjectClass*, pThis, ESI); - - TechnoClass* pOriginal = abstract_cast(pThis); - TechnoClass* pFinalTarget = pOriginal; - - if (pOriginal) - { - TechnoClass* pCurrent = pOriginal; - while (pCurrent) - { - auto pExt = TechnoExt::ExtMap.Find(pCurrent); - if (!pExt || !pExt->ParentAttachment) - { - pFinalTarget = pCurrent; - break; - } - - auto pType = pExt->ParentAttachment->GetType(); - if (!pType || !pType->PassSelection) - { - pFinalTarget = pCurrent; - break; - } - - TechnoClass* pParent = pExt->ParentAttachment->Parent; - if (!pParent || pParent->IsDead()) - { - pFinalTarget = pCurrent; - break; - } - - pCurrent = pParent; - pFinalTarget = pParent; - } - - if (pFinalTarget && pFinalTarget != pOriginal) - { - for (int i = 0; i < ObjectClass::CurrentObjects.Count; i++) - { - if (ObjectClass::CurrentObjects[i] == pOriginal) - { - int lastIndex = ObjectClass::CurrentObjects.Count - 1; - ObjectClass::CurrentObjects[i] = ObjectClass::CurrentObjects[lastIndex]; - ObjectClass::CurrentObjects.Count--; - break; - } - } - - pOriginal->IsSelected = false; - - bool parentAlreadySelected = false; - for (int i = 0; i < ObjectClass::CurrentObjects.Count; i++) - { - if (ObjectClass::CurrentObjects[i] == pFinalTarget) - { - parentAlreadySelected = true; - break; - } - } - - if (!parentAlreadySelected) - { - ObjectClass::CurrentObjects.AddItem(pFinalTarget); - } - - R->ESI(pFinalTarget); - pThis = pFinalTarget; - } - } - pThis->IsSelected = true; if (Phobos::Config::ShowFlashOnSelecting) { - auto const duration = RulesExt::Global()->SelectionFlashDuration; + const int duration = RulesExt::Global()->SelectionFlashDuration; + if (duration > 0) { - TechnoClass* pFlashTarget = abstract_cast(pThis); - if (pFlashTarget && pFlashTarget->GetOwningHouse()->IsControlledByCurrentPlayer()) - { + const auto pFlashTarget = abstract_cast(pThis); + + if (pFlashTarget && pFlashTarget->Owner->IsControlledByCurrentPlayer()) pFlashTarget->Flash(duration); - } } } diff --git a/src/Ext/Techno/Hooks.TechnoAttachment.cpp b/src/Ext/Techno/Hooks.TechnoAttachment.cpp index 09c7bfea0a..f4912f1526 100644 --- a/src/Ext/Techno/Hooks.TechnoAttachment.cpp +++ b/src/Ext/Techno/Hooks.TechnoAttachment.cpp @@ -462,6 +462,53 @@ DEFINE_FUNCTION_JUMP(VTABLE, 0x7EB0D4, TechnoClass_IsSurfaced); #pragma endregion +#pragma region Select & Flash + +bool __fastcall TechnoClass_Select(TechnoClass* pThis) +{ + const auto pExt = TechnoExt::ExtMap.Find(pThis); + const auto pAttachment = pExt->ParentAttachment; + return pAttachment && pAttachment->GetType()->PassSelection + ? pAttachment->Parent->Select() + : reinterpret_cast(0x6FBFA0)(pThis); +} +DEFINE_FUNCTION_JUMP(VTABLE, 0x7F5DBC, TechnoClass_Select) // UnitClass +DEFINE_FUNCTION_JUMP(VTABLE, 0x7EB1A4, TechnoClass_Select) // InfantryClass +DEFINE_FUNCTION_JUMP(VTABLE, 0x7E4008, TechnoClass_Select) // BuildingClass +DEFINE_FUNCTION_JUMP(VTABLE, 0x7E23F0, TechnoClass_Select) // AircraftClass + +void __fastcall TechnoClass_Flash(TechnoClass* pThis, void*, int duration) +{ + const auto pExt = TechnoExt::ExtMap.Find(pThis); + + for (const auto& pAttachment : pExt->ChildAttachments) + { + if (pAttachment->GetType()->InheritStateEffects && pAttachment->Child) + pAttachment->Child->Flash(duration); + } + + return reinterpret_cast(0x6F9DD0)(pThis, duration);// TechnoClass::Flash +} +DEFINE_FUNCTION_JUMP(VTABLE, 0x7F5DB8, TechnoClass_Flash) // UnitClass +DEFINE_FUNCTION_JUMP(VTABLE, 0x7EB1A0, TechnoClass_Flash) // InfantryClass +DEFINE_FUNCTION_JUMP(VTABLE, 0x7E23EC, TechnoClass_Flash) // AircraftClass + +void __fastcall BuildingClass_Flash(TechnoClass* pThis, void*, int duration) +{ + const auto pExt = TechnoExt::ExtMap.Find(pThis); + + for (const auto& pAttachment : pExt->ChildAttachments) + { + if (pAttachment->GetType()->InheritStateEffects && pAttachment->Child) + pAttachment->Child->Flash(duration); + } + + return reinterpret_cast(0x456E00)(pThis, duration);// BuildingClass::Flash +} +DEFINE_FUNCTION_JUMP(VTABLE, 0x7E4004, BuildingClass_Flash) // BuildingClass + +#pragma endregion + DEFINE_HOOK(0x6CC763, SuperClass_Place_ChronoWarp_SkipChildren, 0x6) { enum { Skip = 0x6CCCCA, Continue = 0 }; diff --git a/src/Misc/Hooks.AI.cpp b/src/Misc/Hooks.AI.cpp index 82f62a3d32..aecb10ca8f 100644 --- a/src/Misc/Hooks.AI.cpp +++ b/src/Misc/Hooks.AI.cpp @@ -5,24 +5,7 @@ DEFINE_HOOK(0x55B6B3, LogicClass_AI_After, 0x5) { for (auto const& attachment : AttachmentClass::Array) - { - auto pType = attachment->GetType(); - if (pType && pType->InheritStateEffects && !pType->PassSelection && attachment->Child) - { - int childFlashRemaining = attachment->Child->Flashing.DurationRemaining; - - attachment->AI(); - - if (childFlashRemaining > 0) - { - attachment->Child->Flash(childFlashRemaining); - } - } - else - { - attachment->AI(); - } - } + attachment->AI(); return 0; } diff --git a/src/New/Entity/AttachmentClass.cpp b/src/New/Entity/AttachmentClass.cpp index 391cda8d3c..7bc94f7bd0 100644 --- a/src/New/Entity/AttachmentClass.cpp +++ b/src/New/Entity/AttachmentClass.cpp @@ -129,7 +129,7 @@ void AttachmentClass::AI() this->Child->unknown_280 = this->Parent->unknown_280; // sth related to teleport this->Child->BeingWarpedOut = this->Parent->BeingWarpedOut; this->Child->Deactivated = this->Parent->Deactivated; - this->Child->Flash(this->Parent->Flashing.DurationRemaining); + //this->Child->Flash(this->Parent->Flashing.DurationRemaining); this->Child->IronCurtainTimer = this->Parent->IronCurtainTimer; this->Child->IdleActionTimer = this->Parent->IdleActionTimer; From 7de05390278fe20d8ebc5ad1b481cce7d67f4fc6 Mon Sep 17 00:00:00 2001 From: NetsuNegi39 Date: Tue, 9 Dec 2025 16:01:44 +0800 Subject: [PATCH 4/4] update --- YRpp | 2 +- src/Ext/Techno/Hooks.TechnoAttachment.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/YRpp b/YRpp index 5af96790ce..5cd30376e7 160000 --- a/YRpp +++ b/YRpp @@ -1 +1 @@ -Subproject commit 5af96790ce73e4ea068a390c60c124dccbc220e1 +Subproject commit 5cd30376e723e65be5aa5e8741be8d1e55accad8 diff --git a/src/Ext/Techno/Hooks.TechnoAttachment.cpp b/src/Ext/Techno/Hooks.TechnoAttachment.cpp index f4912f1526..36a5248614 100644 --- a/src/Ext/Techno/Hooks.TechnoAttachment.cpp +++ b/src/Ext/Techno/Hooks.TechnoAttachment.cpp @@ -470,7 +470,7 @@ bool __fastcall TechnoClass_Select(TechnoClass* pThis) const auto pAttachment = pExt->ParentAttachment; return pAttachment && pAttachment->GetType()->PassSelection ? pAttachment->Parent->Select() - : reinterpret_cast(0x6FBFA0)(pThis); + : pThis->TechnoClass::Select(); } DEFINE_FUNCTION_JUMP(VTABLE, 0x7F5DBC, TechnoClass_Select) // UnitClass DEFINE_FUNCTION_JUMP(VTABLE, 0x7EB1A4, TechnoClass_Select) // InfantryClass @@ -487,13 +487,13 @@ void __fastcall TechnoClass_Flash(TechnoClass* pThis, void*, int duration) pAttachment->Child->Flash(duration); } - return reinterpret_cast(0x6F9DD0)(pThis, duration);// TechnoClass::Flash + return pThis->TechnoClass::Flash(duration); } DEFINE_FUNCTION_JUMP(VTABLE, 0x7F5DB8, TechnoClass_Flash) // UnitClass DEFINE_FUNCTION_JUMP(VTABLE, 0x7EB1A0, TechnoClass_Flash) // InfantryClass DEFINE_FUNCTION_JUMP(VTABLE, 0x7E23EC, TechnoClass_Flash) // AircraftClass -void __fastcall BuildingClass_Flash(TechnoClass* pThis, void*, int duration) +void __fastcall BuildingClass_Flash(BuildingClass* pThis, void*, int duration) { const auto pExt = TechnoExt::ExtMap.Find(pThis); @@ -503,7 +503,7 @@ void __fastcall BuildingClass_Flash(TechnoClass* pThis, void*, int duration) pAttachment->Child->Flash(duration); } - return reinterpret_cast(0x456E00)(pThis, duration);// BuildingClass::Flash + return pThis->BuildingClass::Flash(duration); } DEFINE_FUNCTION_JUMP(VTABLE, 0x7E4004, BuildingClass_Flash) // BuildingClass