Index: binaries/data/mods/public/simulation/components/Fogging.js =================================================================== --- binaries/data/mods/public/simulation/components/Fogging.js +++ binaries/data/mods/public/simulation/components/Fogging.js @@ -109,6 +109,17 @@ error("Failed to copy the visual data of the fogged entity " + this.entity); return; } + // If we were already created once, force a reload of the visual actor + // as technologies may have changed the actor in the meantime + if (cmpMirageVisualActor.GetActorSeed() == cmpParentVisualActor.GetActorSeed()) + { + // Hack below. + cmpMirageOwnership.SetOwner(INVALID_PLAYER); + let cmpModifiersManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_ModifiersManager); + cmpModifiersManager.InvalidateCache("VisualActor/Actor", this.mirages[player]); + cmpModifiersManager.InvalidateCache("VisualActor/FoundationActor", this.mirages[player]); + cmpMirageOwnership.SetOwner(cmpParentOwnership.GetOwner()); + } cmpMirageVisualActor.SetActorSeed(cmpParentVisualActor.GetActorSeed()); // Store valuable information into the mirage component (especially for the GUI) Index: binaries/data/mods/public/simulation/components/Mirage.js =================================================================== --- binaries/data/mods/public/simulation/components/Mirage.js +++ binaries/data/mods/public/simulation/components/Mirage.js @@ -68,9 +68,10 @@ Mirage.prototype.CopyIdentity = function(cmpIdentity) { this.miragedIids.add(IID_Identity); - // In almost all cases we want to ignore mirage entities when querying Identity components of owned entities. - // To avoid adding a test everywhere, we don't transfer the classeslist in the template but here. - // We clone this since the classes list is not synchronized and since the mirage should be a snapshot of the entity at the given time. + // Mirages don't get identity classes via the template-filter, so that code can query + // identity components via Engine.QueryInterface without having to explicitly check for mirages. + // Clone this as otherwise we get a reference to the Identity array, + // and that array is deleted when serializing (it's not seralized), which ends in OOS. this.classesList = clone(cmpIdentity.GetClassesList()); }; Index: binaries/data/mods/public/simulation/components/ModifiersManager.js =================================================================== --- binaries/data/mods/public/simulation/components/ModifiersManager.js +++ binaries/data/mods/public/simulation/components/ModifiersManager.js @@ -161,7 +161,7 @@ newValue = originalValue; - let cmpIdentity = Engine.QueryInterface(entity, IID_Identity); + let cmpIdentity = QueryMiragedInterface(entity, IID_Identity); if (!cmpIdentity) return originalValue; let classesList = cmpIdentity.GetClassesList(); Index: binaries/data/mods/public/simulation/data/technologies/test.json =================================================================== --- /dev/null +++ binaries/data/mods/public/simulation/data/technologies/test.json @@ -0,0 +1,11 @@ +{ + "genericName": "Walls", + "description": "The Mauryans built their city walls out of wood, an abundant natural resource in India.", + "icon": "wooden_walls.png", + "tooltip": "Mauryan city walls have 20% less health and 20% less build time.", + "modifications": [ + {"value": "VisualActor/Actor", "replace": "units/hellenes/infantry_javelinist_c_thureophoros.xml"} + ], + "researchTime": 5, + "affects": ["Support", "Structure"] +} Index: binaries/data/mods/public/simulation/templates/special/filter/construction.xml =================================================================== --- binaries/data/mods/public/simulation/templates/special/filter/construction.xml +++ binaries/data/mods/public/simulation/templates/special/filter/construction.xml @@ -1,6 +1,7 @@ + Index: binaries/data/mods/public/simulation/templates/special/filter/mirage.xml =================================================================== --- binaries/data/mods/public/simulation/templates/special/filter/mirage.xml +++ binaries/data/mods/public/simulation/templates/special/filter/mirage.xml @@ -9,6 +9,8 @@ + Index: binaries/data/mods/public/simulation/templates/template_structure_civic_civil_centre.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_structure_civic_civil_centre.xml +++ binaries/data/mods/public/simulation/templates/template_structure_civic_civil_centre.xml @@ -110,6 +110,7 @@ phase_city_{civ} unlock_spies spy_counter + test Index: source/simulation2/components/CCmpVisualActor.cpp =================================================================== --- source/simulation2/components/CCmpVisualActor.cpp +++ source/simulation2/components/CCmpVisualActor.cpp @@ -24,12 +24,13 @@ #include "ICmpFootprint.h" #include "ICmpIdentity.h" -#include "ICmpUnitRenderer.h" +#include "ICmpMirage.h" #include "ICmpOwnership.h" #include "ICmpPosition.h" #include "ICmpTemplateManager.h" #include "ICmpTerrain.h" #include "ICmpUnitMotion.h" +#include "ICmpUnitRenderer.h" #include "ICmpValueModificationManager.h" #include "ICmpVisibility.h" #include "ICmpSound.h" @@ -295,11 +296,21 @@ { case MT_OwnershipChanged: { - if (!m_Unit) - break; - const CMessageOwnershipChanged& msgData = static_cast (msg); m_Unit->GetModel().SetPlayerID(msgData.to); + + CmpPtr cmpValueModificationManager(GetSystemEntity()); + std::wstring newActorName; + if (m_IsFoundationActor) + newActorName = cmpValueModificationManager->ApplyModifications(L"VisualActor/FoundationActor", m_BaseActorName, GetEntityId()); + else + newActorName = cmpValueModificationManager->ApplyModifications(L"VisualActor/Actor", m_BaseActorName, GetEntityId()); + printf("For %i from %ls to %ls\n", GetEntityId(), m_BaseActorName.c_str(), newActorName.c_str()); + if (newActorName != m_ActorName) + { + ParseActorName(newActorName); + ReloadActor(); + } break; } case MT_TerrainChanged: @@ -313,6 +324,11 @@ } case MT_ValueModification: { + // Mirages don't respond to technology modifications. + CmpPtr cmpMirage(GetEntityHandle()); + if (cmpMirage) + return; + const CMessageValueModification& msgData = static_cast (msg); if (msgData.component != L"VisualActor") break;