diff --git a/binaries/data/mods/public/maps/scenarios/unit_dancing_test_triggers.js b/binaries/data/mods/public/maps/scenarios/unit_dancing_test_triggers.js
index 2d4dca2198..32a26c05e0 100644
--- a/binaries/data/mods/public/maps/scenarios/unit_dancing_test_triggers.js
+++ b/binaries/data/mods/public/maps/scenarios/unit_dancing_test_triggers.js
@@ -3,6 +3,7 @@ const JAV_TEMPLATE = "units/mace/infantry_javelineer_b";
const REG_UNIT_TEMPLATE = "units/athen/infantry_spearman_b";
const FAST_UNIT_TEMPLATE = "units/athen/cavalry_swordsman_b";
+const FAST_UNIT_TEMPLATE_2 = "units/athen/cavalry_javelineer_b";
const ATTACKER = 2;
@@ -180,6 +181,27 @@ var manual_formation_dance = function(attacker, target, dance_distance, att_dist
};
+/**
+ * This isn't really dancing, but it can still fail.
+ */
+var avoidance = function(attacker, target, att_distance = 10)
+{
+ return () => {
+ let dancer = QuickSpawn(200, 300, target);
+ for (let i = 0; i < 5; ++i)
+ {
+ WalkTo(300, 400, true, dancer);
+ WalkTo(400, 300, true, dancer);
+ WalkTo(300, 200, true, dancer);
+ WalkTo(200, 300, true, dancer);
+ }
+
+ let attackers = [];
+ attackers.push(Attack(dancer, QuickSpawn(200, 290, attacker, ATTACKER), ATTACKER));
+ return [[dancer], attackers];
+ };
+};
+
experiments.unit_manual_dance_archer = {
"spawn": manual_dance(ARCHER_TEMPLATE, REG_UNIT_TEMPLATE, 5)
};
@@ -280,6 +302,10 @@ experiments.formation_bad_dance_fast_archer = {
"spawn": manual_formation_dance(ARCHER_TEMPLATE, FAST_UNIT_TEMPLATE, 50, 50, 5)
};
+experiments.fast_on_fast = {
+ "spawn": avoidance(FAST_UNIT_TEMPLATE, FAST_UNIT_TEMPLATE_2)
+};
+
var cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger);
Trigger.prototype.SetupUnits = function()
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_cavalry_melee_axeman.xml b/binaries/data/mods/public/simulation/templates/template_unit_cavalry_melee_axeman.xml
index d9fc5efc8c..8cd73dc623 100644
--- a/binaries/data/mods/public/simulation/templates/template_unit_cavalry_melee_axeman.xml
+++ b/binaries/data/mods/public/simulation/templates/template_unit_cavalry_melee_axeman.xml
@@ -8,7 +8,7 @@
0
2.3
- 3.5
+ 4
500
1000
Unit+!Ship
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_cavalry_melee_spearman.xml b/binaries/data/mods/public/simulation/templates/template_unit_cavalry_melee_spearman.xml
index cc1f3eeea5..2b0ff79c1b 100644
--- a/binaries/data/mods/public/simulation/templates/template_unit_cavalry_melee_spearman.xml
+++ b/binaries/data/mods/public/simulation/templates/template_unit_cavalry_melee_spearman.xml
@@ -14,7 +14,7 @@
1.75
- 4.5
+ 4
625
1250
Human
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_cavalry_melee_swordsman.xml b/binaries/data/mods/public/simulation/templates/template_unit_cavalry_melee_swordsman.xml
index 58d030d666..075560bd1b 100644
--- a/binaries/data/mods/public/simulation/templates/template_unit_cavalry_melee_swordsman.xml
+++ b/binaries/data/mods/public/simulation/templates/template_unit_cavalry_melee_swordsman.xml
@@ -8,7 +8,7 @@
0
0
- 3.5
+ 4
375
750
Unit+!Ship
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_cavalry_ranged_archer.xml b/binaries/data/mods/public/simulation/templates/template_unit_cavalry_ranged_archer.xml
index dc6f8c5c1f..e51b631574 100644
--- a/binaries/data/mods/public/simulation/templates/template_unit_cavalry_ranged_archer.xml
+++ b/binaries/data/mods/public/simulation/templates/template_unit_cavalry_ranged_archer.xml
@@ -38,4 +38,7 @@
attack/weapon/bow_attack.xml
+
+ 0.9
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_cavalry_ranged_javelineer.xml b/binaries/data/mods/public/simulation/templates/template_unit_cavalry_ranged_javelineer.xml
index 3a52faccc5..6e5e6d4ab0 100644
--- a/binaries/data/mods/public/simulation/templates/template_unit_cavalry_ranged_javelineer.xml
+++ b/binaries/data/mods/public/simulation/templates/template_unit_cavalry_ranged_javelineer.xml
@@ -38,4 +38,7 @@
attack/impact/javelin_impact.xml
+
+ 0.9
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_champion_cavalry_archer.xml b/binaries/data/mods/public/simulation/templates/template_unit_champion_cavalry_archer.xml
index 78c912b79e..b8ba3710f9 100644
--- a/binaries/data/mods/public/simulation/templates/template_unit_champion_cavalry_archer.xml
+++ b/binaries/data/mods/public/simulation/templates/template_unit_champion_cavalry_archer.xml
@@ -44,4 +44,7 @@
attack/weapon/bow_attack.xml
+
+ 0.9
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_champion_cavalry_axeman.xml b/binaries/data/mods/public/simulation/templates/template_unit_champion_cavalry_axeman.xml
index cf7bfac608..c92034428c 100644
--- a/binaries/data/mods/public/simulation/templates/template_unit_champion_cavalry_axeman.xml
+++ b/binaries/data/mods/public/simulation/templates/template_unit_champion_cavalry_axeman.xml
@@ -8,7 +8,7 @@
0
4.6
- 3.5
+ 4
500
1000
Unit+!Ship
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_champion_cavalry_javelineer.xml b/binaries/data/mods/public/simulation/templates/template_unit_champion_cavalry_javelineer.xml
index da63ec165e..d70e06b492 100644
--- a/binaries/data/mods/public/simulation/templates/template_unit_champion_cavalry_javelineer.xml
+++ b/binaries/data/mods/public/simulation/templates/template_unit_champion_cavalry_javelineer.xml
@@ -44,4 +44,7 @@
attack/impact/javelin_impact.xml
+
+ 0.9
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_champion_cavalry_spearman.xml b/binaries/data/mods/public/simulation/templates/template_unit_champion_cavalry_spearman.xml
index fd1eab7bd9..8291d12413 100644
--- a/binaries/data/mods/public/simulation/templates/template_unit_champion_cavalry_spearman.xml
+++ b/binaries/data/mods/public/simulation/templates/template_unit_champion_cavalry_spearman.xml
@@ -8,7 +8,7 @@
6
0
- 4.5
+ 4
Cavalry
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_champion_cavalry_swordsman.xml b/binaries/data/mods/public/simulation/templates/template_unit_champion_cavalry_swordsman.xml
index 78fc2ff9d0..ee06dbae8c 100644
--- a/binaries/data/mods/public/simulation/templates/template_unit_champion_cavalry_swordsman.xml
+++ b/binaries/data/mods/public/simulation/templates/template_unit_champion_cavalry_swordsman.xml
@@ -8,7 +8,7 @@
0
0.0
- 3.5
+ 4
375
750
Unit+!Ship
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_archer.xml b/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_archer.xml
index f2bc83f516..0f73b34ad6 100644
--- a/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_archer.xml
+++ b/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_archer.xml
@@ -44,4 +44,7 @@
attack/weapon/bow_attack.xml
+
+ 0.9
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_axeman.xml b/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_axeman.xml
index 571d66cd83..43638eed73 100644
--- a/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_axeman.xml
+++ b/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_axeman.xml
@@ -8,7 +8,7 @@
0
9.2
- 3.5
+ 4
500
1000
Unit+!Ship
@@ -30,4 +30,7 @@
attack/weapon/sword_attack.xml
+
+ 1.1
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_javelineer.xml b/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_javelineer.xml
index b6e0df01aa..8d0dbdbe35 100644
--- a/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_javelineer.xml
+++ b/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_javelineer.xml
@@ -44,4 +44,7 @@
attack/impact/javelin_impact.xml
+
+ 0.9
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_maceman.xml b/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_maceman.xml
index 624e5258b1..d57a02d966 100644
--- a/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_maceman.xml
+++ b/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_maceman.xml
@@ -22,4 +22,7 @@
attack/weapon/sword_attack.xml
+
+ 1.1
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_spearman.xml b/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_spearman.xml
index baaa79014e..12e6ef2bb7 100644
--- a/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_spearman.xml
+++ b/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_spearman.xml
@@ -8,7 +8,7 @@
12
0
- 4.5
+ 4
Cavalry
@@ -38,4 +38,7 @@
attack/weapon/spear_attack.xml
+
+ 1.1
+
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_swordsman.xml b/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_swordsman.xml
index 86b62db2b3..c8cbdcd3e3 100644
--- a/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_swordsman.xml
+++ b/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_swordsman.xml
@@ -8,7 +8,7 @@
0.0
0.0
- 3.5
+ 4
375
750
Unit+!Ship
@@ -37,4 +37,7 @@
attack/weapon/sword_attack.xml
+
+ 1.1
+
diff --git a/source/simulation2/components/CCmpUnitMotion.cpp b/source/simulation2/components/CCmpUnitMotion.cpp
index 965881e3a2..de773c6c70 100644
--- a/source/simulation2/components/CCmpUnitMotion.cpp
+++ b/source/simulation2/components/CCmpUnitMotion.cpp
@@ -69,7 +69,7 @@ static const entity_pos_t LONG_PATH_MIN_DIST = entity_pos_t::FromInt(TERRAIN_TIL
* If we are this close to our target entity/point, then think about heading
* for it in a straight line instead of pathfinding.
*/
-static const entity_pos_t DIRECT_PATH_RANGE = entity_pos_t::FromInt(TERRAIN_TILE_SIZE*4);
+static const entity_pos_t DIRECT_PATH_RANGE = entity_pos_t::FromInt(TERRAIN_TILE_SIZE*6);
/**
* To avoid recomputing paths too often, have some leeway for target range checks
@@ -731,8 +731,9 @@ private:
/**
* Start an asynchronous short path query.
+ * @param extendRange - if true, extend the search range to at least the distance to the goal.
*/
- void RequestShortPath(const CFixedVector2D& from, const PathGoal& goal, bool avoidMovingUnits);
+ void RequestShortPath(const CFixedVector2D& from, const PathGoal& goal, bool extendRange);
/**
* General handler for MoveTo interface functions.
@@ -1028,7 +1029,8 @@ bool CCmpUnitMotion::PerformMove(fixed dt, const fixed& turnRate, WaypointPath&
}
// Rotate towards the next waypoint and continue moving.
angle = atan2_approx(offset.X, offset.Y);
- timeLeft = (maxRotation - absoluteAngleDiff) / turnRate;
+ // Give some 'free' rotation for angles below 0.5 radians.
+ timeLeft = (std::min(maxRotation, maxRotation - absoluteAngleDiff + fixed::FromInt(1)/2)) / turnRate;
}
}
@@ -1159,7 +1161,7 @@ bool CCmpUnitMotion::HandleObstructedMove(bool moved)
// The goal here is to manage to move in the general direction of our target, not to be super accurate.
fixed radius = Clamp(skipbeyond/3, fixed::FromInt(TERRAIN_TILE_SIZE), fixed::FromInt(TERRAIN_TILE_SIZE*3));
PathGoal subgoal = { PathGoal::CIRCLE, m_LongPath.m_Waypoints.back().x, m_LongPath.m_Waypoints.back().z, radius };
- RequestShortPath(pos, subgoal, true);
+ RequestShortPath(pos, subgoal, false);
return true;
}()) return true;
@@ -1529,6 +1531,7 @@ void CCmpUnitMotion::ComputePathToGoal(const CFixedVector2D& from, const PathGoa
if (shortPath)
{
m_LongPath.m_Waypoints.clear();
+ // Extend the range so that our first path is probably valid.
RequestShortPath(from, goal, true);
}
else
@@ -1555,16 +1558,22 @@ void CCmpUnitMotion::RequestLongPath(const CFixedVector2D& from, const PathGoal&
m_ExpectedPathTicket.m_Ticket = cmpPathfinder->ComputePathAsync(from.X, from.Y, improvedGoal, m_PassClass, GetEntityId());
}
-void CCmpUnitMotion::RequestShortPath(const CFixedVector2D &from, const PathGoal& goal, bool avoidMovingUnits)
+void CCmpUnitMotion::RequestShortPath(const CFixedVector2D &from, const PathGoal& goal, bool extendRange)
{
CmpPtr cmpPathfinder(GetSystemEntity());
if (!cmpPathfinder)
return;
entity_pos_t searchRange = ShortPathSearchRange();
+ if (extendRange)
+ {
+ CFixedVector2D dist(from.X - goal.x, from.Y - goal.z);
+ if (dist.CompareLength(searchRange - entity_pos_t::FromInt(1)) >= 0)
+ searchRange = dist.Length() + fixed::FromInt(1);
+ }
m_ExpectedPathTicket.m_Type = Ticket::SHORT_PATH;
- m_ExpectedPathTicket.m_Ticket = cmpPathfinder->ComputeShortPathAsync(from.X, from.Y, m_Clearance, searchRange, goal, m_PassClass, avoidMovingUnits, GetGroup(), GetEntityId());
+ m_ExpectedPathTicket.m_Ticket = cmpPathfinder->ComputeShortPathAsync(from.X, from.Y, m_Clearance, searchRange, goal, m_PassClass, true, GetGroup(), GetEntityId());
}
bool CCmpUnitMotion::MoveTo(MoveRequest request)