Index: binaries/data/mods/public/simulation/components/UnitAI.js
===================================================================
--- binaries/data/mods/public/simulation/components/UnitAI.js
+++ binaries/data/mods/public/simulation/components/UnitAI.js
@@ -342,11 +342,15 @@
"Order.PickupUnit": function(msg) {
let cmpGarrisonHolder = Engine.QueryInterface(this.entity, IID_GarrisonHolder);
- if (!cmpGarrisonHolder || cmpGarrisonHolder.IsFull())
+ let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
+
+ if (!cmpTimer || !cmpGarrisonHolder || cmpGarrisonHolder.IsFull()
+ || this.lastPickupTime && this.lastPickupTime + 100 > cmpTimer.GetTime())
{
this.FinishOrder();
return;
}
+ this.lastPickupTime = cmpTimer.GetTime(); // for performance, don't repeat pickup for each unit
if (this.CheckRange(this.order.data))
{
@@ -355,14 +359,11 @@
}
// Check if we need to move
- // TODO implement a better way to know if we are on the shoreline
let needToMove = true;
+ let range = cmpGarrisonHolder.GetLoadingRange();
let cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
- if (this.lastShorelinePosition && cmpPosition && (this.lastShorelinePosition.x == cmpPosition.GetPosition().x) &&
- (this.lastShorelinePosition.z == cmpPosition.GetPosition().z))
- // we were already on the shoreline, and have not moved since
- if (DistanceBetweenEntities(this.entity, this.order.data.target) < 50)
- needToMove = false;
+ if (Engine.QueryInterface(SYSTEM_ENTITY, IID_Pathfinder).CheckNearShore(this.entity, this.order.data.target, range.max))
+ needToMove = false;
if (needToMove)
this.SetNextState("INDIVIDUAL.PICKUP.APPROACHING");
@@ -2944,10 +2945,6 @@
// If a pickup has been requested, remove it
if (this.pickup)
{
- var cmpHolderPosition = Engine.QueryInterface(target, IID_Position);
- var cmpHolderUnitAI = Engine.QueryInterface(target, IID_UnitAI);
- if (cmpHolderUnitAI && cmpHolderPosition)
- cmpHolderUnitAI.lastShorelinePosition = cmpHolderPosition.GetPosition();
Engine.PostMessage(this.pickup, MT_PickupCanceled, { "entity": this.entity });
delete this.pickup;
}
Index: binaries/data/mods/public/simulation/templates/template_unit_ship.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_unit_ship.xml
+++ binaries/data/mods/public/simulation/templates/template_unit_ship.xml
@@ -90,4 +90,13 @@
90
+
+ 1
+ 0
+ FemaleCitizen Infantry Dog
+ Support Infantry Cavalry Dog Siege Elephant
+ 0
+ true
+ 15
+
Index: binaries/data/mods/public/simulation/templates/template_unit_ship_bireme.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_unit_ship_bireme.xml
+++ binaries/data/mods/public/simulation/templates/template_unit_ship_bireme.xml
@@ -41,12 +41,7 @@
20
- 0
- FemaleCitizen Infantry Healer Dog
- Support Infantry Cavalry Dog
- 0
- 10
- true
+ -Siege -Elephant
800
Index: binaries/data/mods/public/simulation/templates/template_unit_ship_fishing.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_unit_ship_fishing.xml
+++ binaries/data/mods/public/simulation/templates/template_unit_ship_fishing.xml
@@ -24,12 +24,7 @@
1
- 0
- FemaleCitizen Infantry Healer
- Support Infantry
- 0
- 10
- true
+ -Dog -Cavalry -Siege -Elephant
-ConquestCritical
Index: binaries/data/mods/public/simulation/templates/template_unit_ship_merchant.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_unit_ship_merchant.xml
+++ binaries/data/mods/public/simulation/templates/template_unit_ship_merchant.xml
@@ -13,12 +13,7 @@
15
- 0
- FemaleCitizen Infantry Healer Dog
- Support Infantry Cavalry Dog
- 0
- 10
- true
+ -Siege -Elephant
400
Index: binaries/data/mods/public/simulation/templates/template_unit_ship_quinquereme.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_unit_ship_quinquereme.xml
+++ binaries/data/mods/public/simulation/templates/template_unit_ship_quinquereme.xml
@@ -52,12 +52,6 @@
50
- 0
- FemaleCitizen Infantry Healer Dog
- Support Infantry Cavalry Dog Siege Elephant
- 0
- 10
- true
2000
Index: binaries/data/mods/public/simulation/templates/template_unit_ship_trireme.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_unit_ship_trireme.xml
+++ binaries/data/mods/public/simulation/templates/template_unit_ship_trireme.xml
@@ -41,12 +41,6 @@
30
- 0
- FemaleCitizen Infantry Healer Dog
- Support Infantry Cavalry Dog Siege Elephant
- 0
- 10
- true
1400
Index: source/simulation2/components/CCmpPathfinder.cpp
===================================================================
--- source/simulation2/components/CCmpPathfinder.cpp
+++ source/simulation2/components/CCmpPathfinder.cpp
@@ -40,6 +40,8 @@
#include "simulation2/helpers/Rasterize.h"
#include "simulation2/helpers/VertexPathfinder.h"
#include "simulation2/serialization/SerializeTemplates.h"
+#include "simulation2/components/ICmpPosition.h"
+#include "simulation2/components/ICmpUnitMotion.h"
REGISTER_COMPONENT_TYPE(Pathfinder)
@@ -248,6 +250,73 @@
return it->second;
}
+/**
+ * Assuming we're a ship, check if we're near the shore.
+ */
+bool CCmpPathfinder::CheckNearShore(entity_id_t ship, entity_id_t landUnit, fixed pickupRange) const
+{
+ if (pickupRange == fixed::FromInt(0))
+ return false;
+
+ CmpPtr cmpPositionShip(GetSimContext(), ship);
+ if (!cmpPositionShip || !cmpPositionShip->IsInWorld())
+ return false;
+
+ CmpPtr cmpPositionLand(GetSimContext(), landUnit);
+ if (!cmpPositionLand || !cmpPositionLand->IsInWorld())
+ return false;
+
+ CmpPtr cmpUnitMotionLand(GetSimContext(), landUnit);
+ if (!cmpUnitMotionLand)
+ return false;
+
+ CmpPtr cmpUnitMotionShip(GetSimContext(), ship);
+ if (!cmpUnitMotionShip)
+ return false;
+ fixed clearance = cmpUnitMotionShip->GetUnitClearance();
+
+ CFixedVector2D posShip = cmpPositionShip->GetPosition2D();
+ CFixedVector2D posLand = cmpPositionLand->GetPosition2D();
+ u16 i, j;
+ Pathfinding::NearestNavcell(posLand.X, posLand.Y, i, j, m_TerrainOnlyGrid->m_W, m_TerrainOnlyGrid->m_H);
+ pass_class_t passClass = cmpUnitMotionLand->GetPassabilityClass();
+ HierarchicalPathfinder::RegionID landRegion = m_PathfinderHier->Get(i, j, passClass);
+
+ std::set reachable;
+ m_PathfinderHier->template FindReachableRegions >(landRegion, reachable, passClass);
+ u16 i0, j0, i1, j1; // bounds of square to search for land
+ Pathfinding::NearestNavcell(posShip.X, posShip.Y, i, j, m_TerrainOnlyGrid->m_W, m_TerrainOnlyGrid->m_H);
+ i16 hw = ((pickupRange + clearance) / Pathfinding::NAVCELL_SIZE).ToInt_RoundToInfinity();
+ i0 = i-hw;
+ i1 = i+hw;
+ j0 = j-hw;
+ j1 = j+hw;
+
+ i = i0;
+ j = j0;
+ u16 offset = j1-j0;
+ while (true)
+ {
+ landRegion = m_PathfinderHier->Get(i, j, passClass);
+ if (reachable.find(landRegion) != reachable.end())
+ return true;
+ // i,j takes on the values on the border of the square
+ // centered on the ship, with side width (pickupRange + clearance)*2
+ if (i == i0 || i == i1)
+ j++;
+ else
+ j += offset;
+ if (j > j1)
+ {
+ i++;
+ j=j0;
+ }
+ if (i > i1)
+ break;
+ }
+ return false;
+}
+
void CCmpPathfinder::GetPassabilityClasses(std::map& passClasses) const
{
passClasses = m_PassClassMasks;
Index: source/simulation2/components/CCmpPathfinder_Common.h
===================================================================
--- source/simulation2/components/CCmpPathfinder_Common.h
+++ source/simulation2/components/CCmpPathfinder_Common.h
@@ -154,6 +154,8 @@
virtual pass_class_t GetPassabilityClass(const std::string& name) const;
+ virtual bool CheckNearShore(entity_id_t ship, entity_id_t landUnit, fixed pickupRange) const;
+
virtual void GetPassabilityClasses(std::map& passClasses) const;
virtual void GetPassabilityClasses(
std::map& nonPathfindingPassClasses,
Index: source/simulation2/components/ICmpPathfinder.h
===================================================================
--- source/simulation2/components/ICmpPathfinder.h
+++ source/simulation2/components/ICmpPathfinder.h
@@ -81,6 +81,11 @@
*/
virtual pass_class_t GetPassabilityClass(const std::string& name) const = 0;
+ /**
+ * Assuming the entity is a ship, returns true if near shore.
+ */
+ virtual bool CheckNearShore(entity_id_t ship, entity_id_t landUnit, fixed pickupRange) const = 0;
+
virtual entity_pos_t GetClearance(pass_class_t passClass) const = 0;
/**
Index: source/simulation2/components/ICmpPathfinder.cpp
===================================================================
--- source/simulation2/components/ICmpPathfinder.cpp
+++ source/simulation2/components/ICmpPathfinder.cpp
@@ -25,4 +25,5 @@
DEFINE_INTERFACE_METHOD_1("SetDebugOverlay", void, ICmpPathfinder, SetDebugOverlay, bool)
DEFINE_INTERFACE_METHOD_1("SetHierDebugOverlay", void, ICmpPathfinder, SetHierDebugOverlay, bool)
DEFINE_INTERFACE_METHOD_CONST_1("GetPassabilityClass", pass_class_t, ICmpPathfinder, GetPassabilityClass, std::string)
+DEFINE_INTERFACE_METHOD_CONST_3("CheckNearShore", bool, ICmpPathfinder, CheckNearShore, entity_id_t, entity_id_t, fixed)
END_INTERFACE_WRAPPER(Pathfinder)
Index: source/simulation2/helpers/HierarchicalPathfinder.h
===================================================================
--- source/simulation2/helpers/HierarchicalPathfinder.h
+++ source/simulation2/helpers/HierarchicalPathfinder.h
@@ -139,6 +139,12 @@
*/
Grid GetConnectivityGrid(pass_class_t passClass) const;
+ /**
+ * Find all regions reachable from the given region by a unit with the specified pass class.
+ */
+ template
+ void FindReachableRegions(RegionID from, std::set& reachable, pass_class_t passClass) const;
+
pass_class_t GetPassabilityClass(const std::string& name) const
{
auto it = m_PassClassMasks.find(name);
@@ -194,12 +200,6 @@
void UpdateGlobalRegions(const std::map >& needNewGlobalRegionMap);
- /**
- * Returns all reachable regions, optionally ordered in a specific manner.
- */
- template
- void FindReachableRegions(RegionID from, std::set& reachable, pass_class_t passClass) const;
-
struct SortByCenterToPoint
{
SortByCenterToPoint(u16 i, u16 j): gi(i), gj(j) {};