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)