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 @@ -356,16 +356,11 @@ return; } - // Check if we need to move TODO implement a better way to know if we are on the shoreline - var needToMove = true; - var 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; - } + // Check if we need to move + let range = cmpGarrisonHolder.GetLoadingRange(); + let needToMove = true; + if (Engine.QueryInterface(SYSTEM_ENTITY, IID_Pathfinder).CheckNearShore(this.entity, range.max)) + needToMove = false; // TODO: what if the units are on a cliff ? the ship will go below the cliff // and the units won't be able to garrison. Should go to the nearest (accessible) shore @@ -3035,10 +3030,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_mechanical_ship.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship.xml +++ binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship.xml @@ -70,4 +70,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_mechanical_ship_bireme.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_bireme.xml +++ binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_bireme.xml @@ -34,12 +34,6 @@ 20 - 0 - FemaleCitizen Infantry Dog - Support Infantry Cavalry Dog - 0 - 10 - true 800 Index: binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_fishing.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_fishing.xml +++ binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_fishing.xml @@ -21,13 +21,7 @@ 6.0 - 1 - 0 - FemaleCitizen Infantry - Support Infantry - 0 - 10 - true + -Dog -Cavalry -Siege -Elephant Fishing Boat Index: binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_merchant.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_merchant.xml +++ binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_merchant.xml @@ -13,12 +13,7 @@ 15 - 0 - FemaleCitizen Infantry Dog - Support Infantry Cavalry Dog - 0 - 10 - true + -Siege -Elephant 400 Index: binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_quinquereme.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_quinquereme.xml +++ binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_quinquereme.xml @@ -43,12 +43,6 @@ 50 - 0 - FemaleCitizen Infantry Dog - Support Infantry Cavalry Dog Siege Elephant - 0 - 10 - true 2000 Index: binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_trireme.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_trireme.xml +++ binaries/data/mods/public/simulation/templates/template_unit_mechanical_ship_trireme.xml @@ -34,12 +34,6 @@ 30 - 0 - FemaleCitizen Infantry 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 @@ -36,6 +36,8 @@ #include "simulation2/components/ICmpWaterManager.h" #include "simulation2/helpers/Rasterize.h" #include "simulation2/serialization/SerializeTemplates.h" +#include "simulation2/components/ICmpPosition.h" +#include "simulation2/components/ICmpUnitMotion.h" REGISTER_COMPONENT_TYPE(Pathfinder) @@ -215,6 +217,33 @@ return it->second; } +/** + * Assuming we're a ship, check if we're near the shore. + */ +bool CCmpPathfinder::CheckNearShore(entity_id_t ent, fixed pickupRange) const +{ + CmpPtr cmpPosition(GetSimContext(), ent); + if (!cmpPosition || !cmpPosition->IsInWorld()) + return false; + + CmpPtr cmpUnitMotion(GetSimContext(), ent); + if (!cmpUnitMotion) + return false; + + CFixedVector2D pos = cmpPosition->GetPosition2D(); + fixed x = pos.X; + fixed z = pos.Y; + pass_class_t passClass = cmpUnitMotion->GetPassabilityClass(); + + fixed hw = pickupRange; + // If we can move freely around the border of a square centered on the current position, then we're not on the shore. + bool test = Pathfinding::CheckLineMovement(x-hw, z-hw, x+hw, z-hw, passClass, *m_TerrainOnlyGrid) + && Pathfinding::CheckLineMovement(x+hw, z-hw, x+hw, z+hw, passClass, *m_TerrainOnlyGrid) + && Pathfinding::CheckLineMovement(x+hw, z+hw, x-hw, z+hw, passClass, *m_TerrainOnlyGrid) + && Pathfinding::CheckLineMovement(x-hw, z+hw, x-hw, z-hw, passClass, *m_TerrainOnlyGrid); + return !test; +} + 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 @@ -204,6 +204,8 @@ virtual pass_class_t GetPassabilityClass(const std::string& name) const; + virtual bool CheckNearShore(entity_id_t ent, 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 @@ -68,6 +68,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 ent, 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_2("CheckNearShore", bool, ICmpPathfinder, CheckNearShore, entity_id_t, fixed) END_INTERFACE_WRAPPER(Pathfinder)