Recompute rally point lines when the rally point is set on a moving unit.

Does not account for setting rally points on units that can move into
the FoW/SoD.
Recalculates paths even if the rally points are not displayed.
Refactors UpdateMarkers() to remove some indentation levels.
Based on patch by Itms. Fixes #1257.

This was SVN commit r15288.
This commit is contained in:
leper
2014-06-04 22:07:58 +00:00
parent 6b015e935e
commit b09a702c60
4 changed files with 69 additions and 30 deletions
@@ -19,6 +19,29 @@ RallyPoint.prototype.AddPosition = function(x, z)
RallyPoint.prototype.GetPositions = function()
{
// Update positions for moving target entities
// TODO: If we target an enemy unit we should update its position
// as long as it is outside of FoW and SoD.
for (var i = 0; i < this.pos.length; i++)
{
if (!this.data[i].target)
continue;
// Get the actual position of the target entity
var cmpPosition = Engine.QueryInterface(this.data[i].target, IID_Position);
if (!cmpPosition)
continue;
var targetPosition = cmpPosition.GetPosition2D();
if (!targetPosition)
continue;
this.pos[i] = {"x": targetPosition.x, "z": targetPosition.y};
var cmpRallyPointRenderer = Engine.QueryInterface(this.entity, IID_RallyPointRenderer);
if (cmpRallyPointRenderer)
cmpRallyPointRenderer.UpdatePosition(i, targetPosition);
}
return this.pos;
};
@@ -1,4 +1,4 @@
/* Copyright (C) 2012 Wildfire Games.
/* Copyright (C) 2014 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -277,6 +277,21 @@ public:
}
}
virtual void UpdatePosition(u32 rallyPointId, CFixedVector2D pos)
{
if (rallyPointId >= m_RallyPoints.size())
return;
m_RallyPoints[rallyPointId] = pos;
UpdateMarkers();
// Compute a new path for the current, and if existing the next rally point
RecomputeRallyPointPath_wrapper(rallyPointId);
if (rallyPointId+1 < m_RallyPoints.size())
RecomputeRallyPointPath_wrapper(rallyPointId+1);
}
virtual void SetDisplayed(bool displayed)
{
if (m_Displayed != displayed)
@@ -285,7 +300,7 @@ public:
// move the markers out of oblivion and back into the real world, or vice-versa
UpdateMarkers();
// Check for changes to the SoD and update the overlay lines accordingly. We need to do this here because this method
// only takes effect when the display flag is active; we need to pick up changes to the SoD that might have occurred
// while this rally point was not being displayed.
@@ -507,29 +522,27 @@ void CCmpRallyPointRenderer::UpdateMarkers()
// set rally point flag selection based on player civilization
CmpPtr<ICmpOwnership> cmpOwnership(GetEntityHandle());
if (cmpOwnership)
{
player_id_t ownerId = cmpOwnership->GetOwner();
if (ownerId != INVALID_PLAYER && (ownerId != previousOwner || m_LastMarkerCount < i))
{
m_LastOwner = ownerId;
CmpPtr<ICmpPlayerManager> 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)
{
CmpPtr<ICmpPlayer> cmpPlayer(GetSimContext(), cmpPlayerManager->GetPlayerByID(ownerId));
if (cmpPlayer)
{
CmpPtr<ICmpVisual> cmpVisualActor(GetSimContext(), m_MarkerEntityIds[i]);
if (cmpVisualActor)
{
cmpVisualActor->SetUnitEntitySelection(CStrW(cmpPlayer->GetCiv()).ToUTF8());
}
}
}
}
}
if (!cmpOwnership)
continue;
player_id_t ownerId = cmpOwnership->GetOwner();
if (ownerId == INVALID_PLAYER || (ownerId == previousOwner && m_LastMarkerCount >= i))
continue;
m_LastOwner = ownerId;
CmpPtr<ICmpPlayerManager> 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<ICmpPlayer> cmpPlayer(GetSimContext(), cmpPlayerManager->GetPlayerByID(ownerId));
if (!cmpPlayer)
continue;
CmpPtr<ICmpVisual> cmpVisualActor(GetSimContext(), m_MarkerEntityIds[i]);
if (cmpVisualActor)
cmpVisualActor->SetUnitEntitySelection(CStrW(cmpPlayer->GetCiv()).ToUTF8());
}
m_LastMarkerCount = m_RallyPoints.size() - 1;
}
@@ -1011,7 +1024,7 @@ void CCmpRallyPointRenderer::ReduceSegmentsByVisibility(std::vector<CVector2D>&
size_t baseNodeIdx = 0;
size_t curNodeIdx = 1;
float baseNodeY;
entity_pos_t baseNodeX;
entity_pos_t baseNodeZ;
@@ -1167,10 +1180,9 @@ void CCmpRallyPointRenderer::MergeVisibilitySegments(std::deque<SVisibilitySegme
int firstSegmentStartIndex = segments.front().m_StartIndex;
ENSURE(firstSegmentStartIndex == 0);
ENSURE(!segments[1].IsSinglePoint()); // at this point, the second segment should never be a single-point segment
segments.erase(segments.begin());
segments.front().m_StartIndex = firstSegmentStartIndex;
}
// check to see if the last segment needs to be merged with its neighbour
@@ -1,4 +1,4 @@
/* Copyright (C) 2012 Wildfire Games.
/* Copyright (C) 2014 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -25,6 +25,7 @@ class CFixedVector2D;
BEGIN_INTERFACE_WRAPPER(RallyPointRenderer)
DEFINE_INTERFACE_METHOD_1("SetDisplayed", void, ICmpRallyPointRenderer, SetDisplayed, bool)
DEFINE_INTERFACE_METHOD_1("SetPosition", void, ICmpRallyPointRenderer, SetPosition, CFixedVector2D)
DEFINE_INTERFACE_METHOD_2("UpdatePosition", void, ICmpRallyPointRenderer, UpdatePosition, u32, CFixedVector2D)
DEFINE_INTERFACE_METHOD_1("AddPosition", void, ICmpRallyPointRenderer, AddPosition_wrapper, CFixedVector2D)
DEFINE_INTERFACE_METHOD_0("Reset", void, ICmpRallyPointRenderer, Reset)
DEFINE_INTERFACE_METHOD_0("IsSet", bool, ICmpRallyPointRenderer, IsSet)
@@ -1,4 +1,4 @@
/* Copyright (C) 2012 Wildfire Games.
/* Copyright (C) 2014 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -37,6 +37,9 @@ public:
/// Discards all previous positions
virtual void SetPosition(CFixedVector2D position) = 0;
/// Updates the position of one given rally point marker.
virtual void UpdatePosition(u32 rallyPointId, CFixedVector2D position) = 0;
/// Add another position at which a marker should be displayed, connected
/// to the previous one.
virtual void AddPosition_wrapper(CFixedVector2D position) = 0;