diff --git a/binaries/data/mods/public/art/actors/props/special/common/athen_waypoint_flag.xml b/binaries/data/mods/public/art/actors/props/special/common/athen_waypoint_flag.xml new file mode 100644 index 0000000000..82c4b25369 --- /dev/null +++ b/binaries/data/mods/public/art/actors/props/special/common/athen_waypoint_flag.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + basic_trans_norm_spec.xml + diff --git a/binaries/data/mods/public/art/actors/props/special/common/brit_waypoint_flag.xml b/binaries/data/mods/public/art/actors/props/special/common/brit_waypoint_flag.xml new file mode 100644 index 0000000000..d6ac063cd5 --- /dev/null +++ b/binaries/data/mods/public/art/actors/props/special/common/brit_waypoint_flag.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + basic_trans_norm_spec.xml + diff --git a/binaries/data/mods/public/art/actors/props/special/common/cart_waypoint_flag.xml b/binaries/data/mods/public/art/actors/props/special/common/cart_waypoint_flag.xml new file mode 100644 index 0000000000..3cdb724e8a --- /dev/null +++ b/binaries/data/mods/public/art/actors/props/special/common/cart_waypoint_flag.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + basic_trans_norm_spec.xml + diff --git a/binaries/data/mods/public/art/actors/props/special/common/gaul_waypoint_flag.xml b/binaries/data/mods/public/art/actors/props/special/common/gaul_waypoint_flag.xml new file mode 100644 index 0000000000..1e9fb0ba2f --- /dev/null +++ b/binaries/data/mods/public/art/actors/props/special/common/gaul_waypoint_flag.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + basic_trans_norm_spec.xml + diff --git a/binaries/data/mods/public/art/actors/props/special/common/han_waypoint_flag.xml b/binaries/data/mods/public/art/actors/props/special/common/han_waypoint_flag.xml new file mode 100644 index 0000000000..3da7ef0667 --- /dev/null +++ b/binaries/data/mods/public/art/actors/props/special/common/han_waypoint_flag.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + basic_trans_norm_spec.xml + diff --git a/binaries/data/mods/public/art/actors/props/special/common/iber_waypoint_flag.xml b/binaries/data/mods/public/art/actors/props/special/common/iber_waypoint_flag.xml new file mode 100644 index 0000000000..26b0e663c9 --- /dev/null +++ b/binaries/data/mods/public/art/actors/props/special/common/iber_waypoint_flag.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + basic_trans_norm_spec.xml + diff --git a/binaries/data/mods/public/art/actors/props/special/common/kush_waypoint_flag.xml b/binaries/data/mods/public/art/actors/props/special/common/kush_waypoint_flag.xml new file mode 100644 index 0000000000..ed51d37b48 --- /dev/null +++ b/binaries/data/mods/public/art/actors/props/special/common/kush_waypoint_flag.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + basic_trans_norm_spec.xml + diff --git a/binaries/data/mods/public/art/actors/props/special/common/mace_waypoint_flag.xml b/binaries/data/mods/public/art/actors/props/special/common/mace_waypoint_flag.xml new file mode 100644 index 0000000000..9310ed13d9 --- /dev/null +++ b/binaries/data/mods/public/art/actors/props/special/common/mace_waypoint_flag.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + basic_trans_norm_spec.xml + diff --git a/binaries/data/mods/public/art/actors/props/special/common/maur_waypoint_flag.xml b/binaries/data/mods/public/art/actors/props/special/common/maur_waypoint_flag.xml new file mode 100644 index 0000000000..1e29dcec9a --- /dev/null +++ b/binaries/data/mods/public/art/actors/props/special/common/maur_waypoint_flag.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + basic_trans_norm_spec.xml + diff --git a/binaries/data/mods/public/art/actors/props/special/common/pers_waypoint_flag.xml b/binaries/data/mods/public/art/actors/props/special/common/pers_waypoint_flag.xml new file mode 100644 index 0000000000..875fefb04b --- /dev/null +++ b/binaries/data/mods/public/art/actors/props/special/common/pers_waypoint_flag.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + basic_trans_norm_spec.xml + diff --git a/binaries/data/mods/public/art/actors/props/special/common/ptol_waypoint_flag.xml b/binaries/data/mods/public/art/actors/props/special/common/ptol_waypoint_flag.xml new file mode 100644 index 0000000000..fc51a1ec1f --- /dev/null +++ b/binaries/data/mods/public/art/actors/props/special/common/ptol_waypoint_flag.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + basic_trans_norm_spec.xml + diff --git a/binaries/data/mods/public/art/actors/props/special/common/rome_waypoint_flag.xml b/binaries/data/mods/public/art/actors/props/special/common/rome_waypoint_flag.xml new file mode 100644 index 0000000000..40f967c782 --- /dev/null +++ b/binaries/data/mods/public/art/actors/props/special/common/rome_waypoint_flag.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + basic_trans_norm_spec.xml + diff --git a/binaries/data/mods/public/art/actors/props/special/common/sele_waypoint_flag.xml b/binaries/data/mods/public/art/actors/props/special/common/sele_waypoint_flag.xml new file mode 100644 index 0000000000..481ad69b98 --- /dev/null +++ b/binaries/data/mods/public/art/actors/props/special/common/sele_waypoint_flag.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + basic_trans_norm_spec.xml + diff --git a/binaries/data/mods/public/art/actors/props/special/common/spart_waypoint_flag.xml b/binaries/data/mods/public/art/actors/props/special/common/spart_waypoint_flag.xml new file mode 100644 index 0000000000..3b9bfa0755 --- /dev/null +++ b/binaries/data/mods/public/art/actors/props/special/common/spart_waypoint_flag.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + basic_trans_norm_spec.xml + diff --git a/binaries/data/mods/public/art/actors/props/special/common/waypoint_flag.xml b/binaries/data/mods/public/art/actors/props/special/common/waypoint_flag.xml deleted file mode 100644 index 8fd86dcfbb..0000000000 --- a/binaries/data/mods/public/art/actors/props/special/common/waypoint_flag.xml +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - - props/waypoint_flag.dae - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - basic_trans_norm_spec.xml - diff --git a/binaries/data/mods/public/art/variants/others/waypoints/base.xml b/binaries/data/mods/public/art/variants/others/waypoints/base.xml new file mode 100644 index 0000000000..ccdd40c197 --- /dev/null +++ b/binaries/data/mods/public/art/variants/others/waypoints/base.xml @@ -0,0 +1,11 @@ + + + + + + props/waypoint_flag.dae + + + + + diff --git a/binaries/data/mods/public/maps/random/caledonian_meadows.js b/binaries/data/mods/public/maps/random/caledonian_meadows.js index 564e86cdaa..f1463f9b73 100644 --- a/binaries/data/mods/public/maps/random/caledonian_meadows.js +++ b/binaries/data/mods/public/maps/random/caledonian_meadows.js @@ -161,7 +161,7 @@ export function* generateMap() "units/gaul/infantry_slinger_b", "units/gaul/infantry_javelineer_b", "units/gaul/champion_fanatic", - "actor|props/special/common/waypoint_flag.xml", + "actor|props/special/common/waypoint_flag_factions.xml", "actor|props/special/eyecandy/barrel_a.xml", "actor|props/special/eyecandy/basket_celt_a.xml", "actor|props/special/eyecandy/crate_a.xml", diff --git a/binaries/data/mods/public/maps/random/survivalofthefittest.js b/binaries/data/mods/public/maps/random/survivalofthefittest.js index 6b68e109e7..bd77c1c9ae 100644 --- a/binaries/data/mods/public/maps/random/survivalofthefittest.js +++ b/binaries/data/mods/public/maps/random/survivalofthefittest.js @@ -28,7 +28,7 @@ export function* generateMap(mapSettings) const aRockMedium = g_Decoratives.rockMedium; const aBushMedium = g_Decoratives.bushMedium; const aBushSmall = g_Decoratives.bushSmall; - const aWaypointFlag = "actor|props/special/common/waypoint_flag.xml"; + const aWaypointFlag = "actor|props/special/common/waypoint_flag_factions.xml"; const pForest1 = [ tForestFloor2 + TERRAIN_SEPARATOR + oTree1, diff --git a/binaries/data/mods/public/maps/random/wild_lake_biomes.json b/binaries/data/mods/public/maps/random/wild_lake_biomes.json index 167c179759..b85aa73f8b 100644 --- a/binaries/data/mods/public/maps/random/wild_lake_biomes.json +++ b/binaries/data/mods/public/maps/random/wild_lake_biomes.json @@ -272,7 +272,7 @@ "campEntities": [ "gaia/treasure/metal", "gaia/treasure/standing_stone", - "actor|props/special/common/waypoint_flag.xml", + "actor|props/special/common/waypoint_flag_factions.xml", "actor|props/special/eyecandy/barrel_a.xml", "actor|props/special/eyecandy/basket_celt_a.xml", "actor|props/special/eyecandy/crate_a.xml", diff --git a/binaries/data/mods/public/simulation/templates/special/rallypoint.xml b/binaries/data/mods/public/simulation/templates/special/rallypoint.xml index 4418e5abcf..0349079696 100644 --- a/binaries/data/mods/public/simulation/templates/special/rallypoint.xml +++ b/binaries/data/mods/public/simulation/templates/special/rallypoint.xml @@ -1,9 +1,15 @@ + + gaia + Rally point flag + true + + true - props/special/common/waypoint_flag.xml + props/special/common/{civ}_waypoint_flag.xml diff --git a/binaries/data/mods/public/simulation/templates/special/rallypoints/athen.xml b/binaries/data/mods/public/simulation/templates/special/rallypoints/athen.xml new file mode 100644 index 0000000000..2ed54cee58 --- /dev/null +++ b/binaries/data/mods/public/simulation/templates/special/rallypoints/athen.xml @@ -0,0 +1,6 @@ + + + + athen + + diff --git a/binaries/data/mods/public/simulation/templates/special/rallypoints/brit.xml b/binaries/data/mods/public/simulation/templates/special/rallypoints/brit.xml new file mode 100644 index 0000000000..d9c2707893 --- /dev/null +++ b/binaries/data/mods/public/simulation/templates/special/rallypoints/brit.xml @@ -0,0 +1,6 @@ + + + + brit + + diff --git a/binaries/data/mods/public/simulation/templates/special/rallypoints/cart.xml b/binaries/data/mods/public/simulation/templates/special/rallypoints/cart.xml new file mode 100644 index 0000000000..7c9423a8fe --- /dev/null +++ b/binaries/data/mods/public/simulation/templates/special/rallypoints/cart.xml @@ -0,0 +1,6 @@ + + + + cart + + diff --git a/binaries/data/mods/public/simulation/templates/special/rallypoints/gaul.xml b/binaries/data/mods/public/simulation/templates/special/rallypoints/gaul.xml new file mode 100644 index 0000000000..10e06626f9 --- /dev/null +++ b/binaries/data/mods/public/simulation/templates/special/rallypoints/gaul.xml @@ -0,0 +1,6 @@ + + + + gaul + + diff --git a/binaries/data/mods/public/simulation/templates/special/rallypoints/han.xml b/binaries/data/mods/public/simulation/templates/special/rallypoints/han.xml new file mode 100644 index 0000000000..105af98119 --- /dev/null +++ b/binaries/data/mods/public/simulation/templates/special/rallypoints/han.xml @@ -0,0 +1,6 @@ + + + + han + + diff --git a/binaries/data/mods/public/simulation/templates/special/rallypoints/iber.xml b/binaries/data/mods/public/simulation/templates/special/rallypoints/iber.xml new file mode 100644 index 0000000000..3215440faa --- /dev/null +++ b/binaries/data/mods/public/simulation/templates/special/rallypoints/iber.xml @@ -0,0 +1,6 @@ + + + + iber + + diff --git a/binaries/data/mods/public/simulation/templates/special/rallypoints/kush.xml b/binaries/data/mods/public/simulation/templates/special/rallypoints/kush.xml new file mode 100644 index 0000000000..35d81439e4 --- /dev/null +++ b/binaries/data/mods/public/simulation/templates/special/rallypoints/kush.xml @@ -0,0 +1,6 @@ + + + + kush + + diff --git a/binaries/data/mods/public/simulation/templates/special/rallypoints/mace.xml b/binaries/data/mods/public/simulation/templates/special/rallypoints/mace.xml new file mode 100644 index 0000000000..671e597050 --- /dev/null +++ b/binaries/data/mods/public/simulation/templates/special/rallypoints/mace.xml @@ -0,0 +1,6 @@ + + + + mace + + diff --git a/binaries/data/mods/public/simulation/templates/special/rallypoints/maur.xml b/binaries/data/mods/public/simulation/templates/special/rallypoints/maur.xml new file mode 100644 index 0000000000..1c7d2d1eb5 --- /dev/null +++ b/binaries/data/mods/public/simulation/templates/special/rallypoints/maur.xml @@ -0,0 +1,6 @@ + + + + maur + + diff --git a/binaries/data/mods/public/simulation/templates/special/rallypoints/pers.xml b/binaries/data/mods/public/simulation/templates/special/rallypoints/pers.xml new file mode 100644 index 0000000000..93c05b0375 --- /dev/null +++ b/binaries/data/mods/public/simulation/templates/special/rallypoints/pers.xml @@ -0,0 +1,6 @@ + + + + pers + + diff --git a/binaries/data/mods/public/simulation/templates/special/rallypoints/ptol.xml b/binaries/data/mods/public/simulation/templates/special/rallypoints/ptol.xml new file mode 100644 index 0000000000..f7bb9d1319 --- /dev/null +++ b/binaries/data/mods/public/simulation/templates/special/rallypoints/ptol.xml @@ -0,0 +1,6 @@ + + + + ptol + + diff --git a/binaries/data/mods/public/simulation/templates/special/rallypoints/rome.xml b/binaries/data/mods/public/simulation/templates/special/rallypoints/rome.xml new file mode 100644 index 0000000000..e8d59bff10 --- /dev/null +++ b/binaries/data/mods/public/simulation/templates/special/rallypoints/rome.xml @@ -0,0 +1,6 @@ + + + + rome + + diff --git a/binaries/data/mods/public/simulation/templates/special/rallypoints/sele.xml b/binaries/data/mods/public/simulation/templates/special/rallypoints/sele.xml new file mode 100644 index 0000000000..4bb14c90f7 --- /dev/null +++ b/binaries/data/mods/public/simulation/templates/special/rallypoints/sele.xml @@ -0,0 +1,6 @@ + + + + sele + + diff --git a/binaries/data/mods/public/simulation/templates/special/rallypoints/spart.xml b/binaries/data/mods/public/simulation/templates/special/rallypoints/spart.xml new file mode 100644 index 0000000000..8464e8f58f --- /dev/null +++ b/binaries/data/mods/public/simulation/templates/special/rallypoints/spart.xml @@ -0,0 +1,6 @@ + + + + spart + + diff --git a/binaries/data/mods/public/simulation/templates/template_structure.xml b/binaries/data/mods/public/simulation/templates/template_structure.xml index 478cfc8f61..94b1633189 100644 --- a/binaries/data/mods/public/simulation/templates/template_structure.xml +++ b/binaries/data/mods/public/simulation/templates/template_structure.xml @@ -79,7 +79,7 @@ - special/rallypoint + special/rallypoints/{civ} art/textures/misc/rallypoint_line.png art/textures/misc/rallypoint_line_mask.png 0.25 diff --git a/binaries/data/mods/public/simulation/templates/template_territory_pull.xml b/binaries/data/mods/public/simulation/templates/template_territory_pull.xml index 63de91aeb3..2ede38278d 100644 --- a/binaries/data/mods/public/simulation/templates/template_territory_pull.xml +++ b/binaries/data/mods/public/simulation/templates/template_territory_pull.xml @@ -35,7 +35,7 @@ false true - props/special/common/waypoint_flag.xml + props/special/common/waypoint_flag_factions.xml true diff --git a/source/ps/algorithm.h b/source/ps/algorithm.h index 54e2be2319..2e4e28fdbd 100644 --- a/source/ps/algorithm.h +++ b/source/ps/algorithm.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2024 Wildfire Games. +/* Copyright (C) 2025 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -18,6 +18,10 @@ #ifndef ALGORITHM_H #define ALGORITHM_H +#include +#include +#include + namespace PS { /** @@ -34,6 +38,27 @@ bool contains(Range&& range, const T& value) return elem == value; }); } + +/** + * @brief Replaces all occurrences of a substring within a string with a given value. + * + * This function searches the input string `base` for all instances of the specified + * `tag` and replaces them with the provided `value`. The replacement is performed + * in-place and modifies the original string. + * + * @param base The string in which to perform replacements. Modified in-place. + * @param tag The substring to search for (e.g., a placeholder like L"{civ}"). + * @param value The string to replace each occurrence of `tag` with. + */ +inline void ReplaceSubrange(std::wstring& base, std::wstring_view tag, std::wstring_view value) +{ + size_t pos = 0; + while ((pos = base.find(tag, pos)) != std::wstring::npos) + { + base.replace(pos, tag.length(), value); + pos += value.length(); + } } +} // namespace PS #endif // ALGORITHM_H diff --git a/source/simulation2/components/CCmpRallyPointRenderer.cpp b/source/simulation2/components/CCmpRallyPointRenderer.cpp index b126772120..60958fd481 100644 --- a/source/simulation2/components/CCmpRallyPointRenderer.cpp +++ b/source/simulation2/components/CCmpRallyPointRenderer.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2025 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -17,7 +17,9 @@ #include "precompiled.h" #include "CCmpRallyPointRenderer.h" +#include "ICmpIdentity.h" +#include "ps/algorithm.h" #include "ps/Profile.h" #include "simulation2/components/ICmpRangeManager.h" #include "simulation2/helpers/Los.h" @@ -218,69 +220,71 @@ void CCmpRallyPointRenderer::UpdateMessageSubscriptions() GetSimContext().GetComponentManager().DynamicSubscriptionNonsync(MT_RenderSubmit, this, m_Displayed && IsSet()); } +void CCmpRallyPointRenderer::CreateMarkerEntity(size_t index, player_id_t ownerId) +{ + if (m_MarkerTemplate.empty() || ownerId == INVALID_PLAYER) + return; + + CmpPtr cmpPlayerManager(GetSystemEntity()); + if (!cmpPlayerManager) + return; + + CmpPtr cmpPlayer(GetSimContext(), cmpPlayerManager->GetPlayerByID(ownerId)); + if (!cmpPlayer) + return; + + CmpPtr cmpIdentity(GetSimContext(), cmpPlayer->GetEntityId()); + if (!cmpIdentity) + return; + + // Create a copy we do not want to alter the marker template. + std::wstring markerTemplate = m_MarkerTemplate; + PS::ReplaceSubrange(markerTemplate, L"{civ}", cmpIdentity->GetCiv()); + + CComponentManager& componentMgr = GetSimContext().GetComponentManager(); + entity_id_t newMarker = componentMgr.AllocateNewLocalEntity(); + + if (newMarker != INVALID_ENTITY) + newMarker = componentMgr.AddEntity(markerTemplate, newMarker); + + m_MarkerEntityIds[index] = newMarker; +} + void CCmpRallyPointRenderer::UpdateMarkers() { player_id_t previousOwner = m_LastOwner; + CmpPtr cmpOwnership(GetEntityHandle()); + const player_id_t ownerId{cmpOwnership ? cmpOwnership->GetOwner() : 0}; + for (size_t i = 0; i < m_RallyPoints.size(); ++i) { if (i >= m_MarkerEntityIds.size()) m_MarkerEntityIds.push_back(INVALID_ENTITY); if (m_MarkerEntityIds[i] == INVALID_ENTITY) - { - // No marker exists yet, create one first - CComponentManager& componentMgr = GetSimContext().GetComponentManager(); + CreateMarkerEntity(i, ownerId); - // Allocate a new entity for the marker - if (!m_MarkerTemplate.empty()) - { - m_MarkerEntityIds[i] = componentMgr.AllocateNewLocalEntity(); - if (m_MarkerEntityIds[i] != INVALID_ENTITY) - m_MarkerEntityIds[i] = componentMgr.AddEntity(m_MarkerTemplate, m_MarkerEntityIds[i]); - } - } - - // The marker entity should be valid at this point, otherwise something went wrong trying to allocate it if (m_MarkerEntityIds[i] == INVALID_ENTITY) + { LOGERROR("Failed to create rally point marker entity"); + continue; + } CmpPtr markerCmpPosition(GetSimContext(), m_MarkerEntityIds[i]); if (markerCmpPosition) { if (m_Displayed && IsSet()) - { markerCmpPosition->MoveTo(m_RallyPoints[i].X, m_RallyPoints[i].Y); - } else - { markerCmpPosition->MoveOutOfWorld(); - } } - // Set rally point flag selection based on player civilization - CmpPtr cmpOwnership(GetEntityHandle()); - if (!cmpOwnership) - continue; - - player_id_t ownerId = cmpOwnership->GetOwner(); if (ownerId == INVALID_PLAYER || (ownerId == previousOwner && m_LastMarkerCount >= i)) continue; m_LastOwner = ownerId; - CmpPtr cmpPlayerManager(GetSystemEntity()); - // cmpPlayerManager should not be null as long as this method is called on-demand instead of at Init() time - // (we can't rely on component initialization order in Init()) - if (!cmpPlayerManager) - continue; - - CmpPtr cmpIdentity(GetSimContext(), cmpPlayerManager->GetPlayerByID(ownerId)); - if (!cmpIdentity) - continue; - - CmpPtr cmpVisualActor(GetSimContext(), m_MarkerEntityIds[i]); - if (cmpVisualActor) - cmpVisualActor->SetVariant("civ", CStrW(cmpIdentity->GetCiv()).ToUTF8()); } + m_LastMarkerCount = m_RallyPoints.size() - 1; } diff --git a/source/simulation2/components/CCmpRallyPointRenderer.h b/source/simulation2/components/CCmpRallyPointRenderer.h index 1e73d5ea54..e283b03fed 100644 --- a/source/simulation2/components/CCmpRallyPointRenderer.h +++ b/source/simulation2/components/CCmpRallyPointRenderer.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 Wildfire Games. +/* Copyright (C) 2025 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -194,6 +194,14 @@ private: */ void UpdateMarkers(); + /** + * @brief Creates a rally point marker entity for the specified index and owner. + * + * @param index The index in the rally point list for which to create a marker. + * @param ownerId The ID of the player who currently owns the entity. + */ + void CreateMarkerEntity(size_t index, player_id_t ownerId); + /** * Recomputes all the full paths from this entity to the rally point and from the rally point to the next, and does all the necessary * post-processing to make them prettier. diff --git a/source/simulation2/components/CCmpVisualActor.cpp b/source/simulation2/components/CCmpVisualActor.cpp index 8cb19c3206..9113919e25 100644 --- a/source/simulation2/components/CCmpVisualActor.cpp +++ b/source/simulation2/components/CCmpVisualActor.cpp @@ -27,6 +27,8 @@ #include "ICmpIdentity.h" #include "ICmpMirage.h" #include "ICmpOwnership.h" +#include "ICmpPlayer.h" +#include "ICmpPlayerManager.h" #include "ICmpPosition.h" #include "ICmpTemplateManager.h" #include "ICmpTerrain.h" @@ -47,6 +49,7 @@ #include "maths/Frustum.h" #include "maths/Matrix3D.h" #include "maths/Vector3D.h" +#include "ps/algorithm.h" #include "ps/CLogger.h" #include "ps/GameSetup/Config.h" #include "renderer/Scene.h" @@ -560,7 +563,7 @@ public: } private: - // Replace {phenotype} with the correct value in m_ActorName + // Replace {phenotype} and {civ} with the correct value in m_ActorName void ParseActorName(std::wstring base); /// Helper function shared by component init and actor reloading @@ -583,18 +586,13 @@ REGISTER_COMPONENT_TYPE(VisualActor) void CCmpVisualActor::ParseActorName(std::wstring base) { CmpPtr cmpIdentity(GetEntityHandle()); - const std::wstring pattern = L"{phenotype}"; if (cmpIdentity) { - size_t pos = base.find(pattern); - while (pos != std::string::npos) - { - base.replace(pos, pattern.size(), cmpIdentity->GetPhenotype()); - pos = base.find(pattern, pos + pattern.size()); - } + PS::ReplaceSubrange(base, L"{phenotype}", cmpIdentity->GetPhenotype()); + PS::ReplaceSubrange(base, L"{civ}", cmpIdentity->GetCiv()); } - m_ActorName = base; + m_ActorName = std::move(base); } void CCmpVisualActor::InitModel() diff --git a/source/tools/entity/checkrefs.py b/source/tools/entity/checkrefs.py index 5d3e56e79d..31a1901820 100755 --- a/source/tools/entity/checkrefs.py +++ b/source/tools/entity/checkrefs.py @@ -340,22 +340,32 @@ class CheckRefs: and entity.find("VisualActor").find("Actor") is not None and entity.find("Identity") is not None ): - phenotype_tag = entity.find("Identity").find("Phenotype") - phenotypes = ( - phenotype_tag.text.split() - if (phenotype_tag is not None and phenotype_tag.text) - else ["default"] - ) + cmp_identity = entity.find("Identity") + actor = entity.find("VisualActor").find("Actor") - if "{phenotype}" in actor.text: - for phenotype in phenotypes: - # See simulation2/components/CCmpVisualActor.cpp and Identity.js - # for explanation. - actor_path = actor.text.replace("{phenotype}", phenotype) - self.deps.append((fp, Path(f"art/actors/{actor_path}"))) + if cmp_identity is not None: + actor_path = actor.text + if "{civ}" in actor_path: + civ_tag = cmp_identity.find("Civ") + civ = civ_tag.text if civ_tag is not None else "gaia" + actor_path = actor_path.replace("{civ}", civ) + + if "{phenotype}" in actor_path: + phenotype_tag = cmp_identity.find("Phenotype") + phenotypes = ( + phenotype_tag.text.split() + if (phenotype_tag is not None and phenotype_tag.text) + else ["default"] + ) + for phenotype in phenotypes: + # See simulation2/components/CCmpVisualActor.cpp and Identity.js + # for explanation. + phenotype_path = actor_path.replace("{phenotype}", phenotype) + self.deps.append((fp, Path(f"art/actors/{phenotype_path}"))) else: actor_path = actor.text self.deps.append((fp, Path(f"art/actors/{actor_path}"))) + foundation_actor = entity.find("VisualActor").find("FoundationActor") if foundation_actor is not None: self.deps.append((fp, Path(f"art/actors/{foundation_actor.text}")))