From 0e403632cff8e03ea0190e090903841a362b1ef7 Mon Sep 17 00:00:00 2001 From: wraitii Date: Sun, 30 Jan 2022 14:22:27 +0000 Subject: [PATCH] Allow giving different weights to different templates when pushing. This makes it possible to make units heavier, which both push more & get pushed less by other units. In particular, the diff does it for siege units & elephants. This improves movement for these units in crowd situation, since they will now basically not move when other regular units push into them. Supported By: asterix, marder Refs #6127 Differential Revision: https://code.wildfiregames.com/D4452 This was SVN commit r26275. --- .../maps/scenarios/unit_pushing_test.js | 10 ++++++++++ .../templates/template_formation.xml | 1 + .../simulation/templates/template_unit.xml | 1 + .../templates/template_unit_catafalque.xml | 1 + .../template_unit_champion_elephant.xml | 1 + .../templates/template_unit_elephant.xml | 1 + ...ate_unit_fauna_hunt_defensive_elephant.xml | 1 + .../template_unit_fauna_hunt_whale.xml | 1 + .../template_unit_hero_elephant_melee.xml | 1 + .../templates/template_unit_siege.xml | 1 + .../template_unit_support_elephant.xml | 1 + .../simulation2/components/CCmpUnitMotion.h | 12 ++++++++++- .../components/CCmpUnitMotion_System.cpp | 20 ++++++++++++++++--- 13 files changed, 48 insertions(+), 4 deletions(-) diff --git a/binaries/data/mods/public/maps/scenarios/unit_pushing_test.js b/binaries/data/mods/public/maps/scenarios/unit_pushing_test.js index 7d5deaa87f..9c0c04b11a 100644 --- a/binaries/data/mods/public/maps/scenarios/unit_pushing_test.js +++ b/binaries/data/mods/public/maps/scenarios/unit_pushing_test.js @@ -242,6 +242,16 @@ experiments.overlapping = { } }; +experiments.large_against_units = { + "spawn": (gx, gy) => { + for (let i = -18; i < 20; i += 2) + for (let j = 0; j < 40; j += 3) + WalkTo(gx, gy - 50, false, QuickSpawn(gx + i, gy + 10 + j, REG_UNIT_TEMPLATE)); + WalkTo(gx - 5, gy + 100, false, QuickSpawn(gx - 5, gy, LARGE_UNIT_TEMPLATE)); + WalkTo(gx + 5, gy + 100, false, QuickSpawn(gx + 5, gy, ELE_TEMPLATE)); + } +}; + var perf_experiments = {}; // Perf check: put units everywhere, not moving. diff --git a/binaries/data/mods/public/simulation/templates/template_formation.xml b/binaries/data/mods/public/simulation/templates/template_formation.xml index 99b90fa9ed..803268686e 100644 --- a/binaries/data/mods/public/simulation/templates/template_formation.xml +++ b/binaries/data/mods/public/simulation/templates/template_formation.xml @@ -74,5 +74,6 @@ 0.1 100 large + 100 diff --git a/binaries/data/mods/public/simulation/templates/template_unit.xml b/binaries/data/mods/public/simulation/templates/template_unit.xml index 24f801420c..0a276fc8b8 100644 --- a/binaries/data/mods/public/simulation/templates/template_unit.xml +++ b/binaries/data/mods/public/simulation/templates/template_unit.xml @@ -127,6 +127,7 @@ 1.67 1.5 18 + 10 false diff --git a/binaries/data/mods/public/simulation/templates/template_unit_catafalque.xml b/binaries/data/mods/public/simulation/templates/template_unit_catafalque.xml index debc121d34..ae05c27738 100644 --- a/binaries/data/mods/public/simulation/templates/template_unit_catafalque.xml +++ b/binaries/data/mods/public/simulation/templates/template_unit_catafalque.xml @@ -53,6 +53,7 @@ large 0.55 0.275 + 10.0 units/global/catafalque.xml diff --git a/binaries/data/mods/public/simulation/templates/template_unit_champion_elephant.xml b/binaries/data/mods/public/simulation/templates/template_unit_champion_elephant.xml index e2c5852125..7a4e47ac13 100644 --- a/binaries/data/mods/public/simulation/templates/template_unit_champion_elephant.xml +++ b/binaries/data/mods/public/simulation/templates/template_unit_champion_elephant.xml @@ -56,6 +56,7 @@ large 0.5 + 5.0 100 diff --git a/binaries/data/mods/public/simulation/templates/template_unit_elephant.xml b/binaries/data/mods/public/simulation/templates/template_unit_elephant.xml index 577d027579..416f582a2b 100644 --- a/binaries/data/mods/public/simulation/templates/template_unit_elephant.xml +++ b/binaries/data/mods/public/simulation/templates/template_unit_elephant.xml @@ -56,6 +56,7 @@ large 0.5 + 5.0 100 diff --git a/binaries/data/mods/public/simulation/templates/template_unit_fauna_hunt_defensive_elephant.xml b/binaries/data/mods/public/simulation/templates/template_unit_fauna_hunt_defensive_elephant.xml index 3227215780..ac6e078622 100644 --- a/binaries/data/mods/public/simulation/templates/template_unit_fauna_hunt_defensive_elephant.xml +++ b/binaries/data/mods/public/simulation/templates/template_unit_fauna_hunt_defensive_elephant.xml @@ -19,5 +19,6 @@ large 0.5 0.25 + 5.0 diff --git a/binaries/data/mods/public/simulation/templates/template_unit_fauna_hunt_whale.xml b/binaries/data/mods/public/simulation/templates/template_unit_fauna_hunt_whale.xml index d0dc180ec4..83e4690275 100644 --- a/binaries/data/mods/public/simulation/templates/template_unit_fauna_hunt_whale.xml +++ b/binaries/data/mods/public/simulation/templates/template_unit_fauna_hunt_whale.xml @@ -53,5 +53,6 @@ 1.8 1 1.8 + 5.0 diff --git a/binaries/data/mods/public/simulation/templates/template_unit_hero_elephant_melee.xml b/binaries/data/mods/public/simulation/templates/template_unit_hero_elephant_melee.xml index 9290065d09..50d83a9342 100644 --- a/binaries/data/mods/public/simulation/templates/template_unit_hero_elephant_melee.xml +++ b/binaries/data/mods/public/simulation/templates/template_unit_hero_elephant_melee.xml @@ -75,5 +75,6 @@ large 0.5 + 5.0 diff --git a/binaries/data/mods/public/simulation/templates/template_unit_siege.xml b/binaries/data/mods/public/simulation/templates/template_unit_siege.xml index 5f5e763f83..fc753e9b99 100644 --- a/binaries/data/mods/public/simulation/templates/template_unit_siege.xml +++ b/binaries/data/mods/public/simulation/templates/template_unit_siege.xml @@ -63,5 +63,6 @@ 1 0.75 0.25 + 5.0 diff --git a/binaries/data/mods/public/simulation/templates/template_unit_support_elephant.xml b/binaries/data/mods/public/simulation/templates/template_unit_support_elephant.xml index aa247f05f4..b2f6c7f631 100644 --- a/binaries/data/mods/public/simulation/templates/template_unit_support_elephant.xml +++ b/binaries/data/mods/public/simulation/templates/template_unit_support_elephant.xml @@ -71,6 +71,7 @@ large 0.6 0.3 + 5.0 50 diff --git a/source/simulation2/components/CCmpUnitMotion.h b/source/simulation2/components/CCmpUnitMotion.h index 227b9f363d..939f94b30d 100644 --- a/source/simulation2/components/CCmpUnitMotion.h +++ b/source/simulation2/components/CCmpUnitMotion.h @@ -155,7 +155,7 @@ public: bool m_IsFormationController; - fixed m_TemplateWalkSpeed, m_TemplateRunMultiplier, m_TemplateAcceleration; + fixed m_TemplateWalkSpeed, m_TemplateRunMultiplier, m_TemplateAcceleration, m_TemplateWeight; pass_class_t m_PassClass; std::string m_PassClassName; @@ -270,6 +270,9 @@ public: "" "" "" + "" + "" + "" "" "" "" @@ -295,6 +298,8 @@ public: m_Acceleration = m_TemplateAcceleration = paramNode.GetChild("Acceleration").ToFixed(); + m_TemplateWeight = paramNode.GetChild("Weight").ToFixed(); + CmpPtr cmpPathfinder(GetSystemEntity()); if (cmpPathfinder) { @@ -497,6 +502,11 @@ public: m_Acceleration = acceleration; } + virtual entity_pos_t GetWeight() const + { + return m_TemplateWeight; + } + virtual pass_class_t GetPassabilityClass() const { return m_PassClass; diff --git a/source/simulation2/components/CCmpUnitMotion_System.cpp b/source/simulation2/components/CCmpUnitMotion_System.cpp index 1c9eef515c..7e696b753b 100644 --- a/source/simulation2/components/CCmpUnitMotion_System.cpp +++ b/source/simulation2/components/CCmpUnitMotion_System.cpp @@ -69,6 +69,12 @@ constexpr int PUSHING_REDUCTION_FACTOR = 2; */ constexpr entity_pos_t MAX_DISTANCE_FACTOR = entity_pos_t::FromFraction(5, 2); +/** + * Maximum pushing multiplier for a single push calculation. + * This exists for numerical stability of the system between a lightweight and a heavy unit. + */ +constexpr int MAX_PUSHING_MULTIPLIER = 4; + /** * When two units collide, if their movement dot product is below this value, give them a perpendicular nudge instead of trying to push in the regular way. */ @@ -745,9 +751,17 @@ void CCmpUnitMotionManager::Push(EntityMap::value_type& a, EntityMa CFixedVector2D pushingDir = offset.Multiply(distanceFactor); - // Divide by an arbitrary constant to avoid pushing too much. - a.second.push += pushingDir.Multiply(dt / PUSHING_REDUCTION_FACTOR); - b.second.push -= pushingDir.Multiply(dt / PUSHING_REDUCTION_FACTOR); + // These cannot be zero, checked in the schema. + entity_pos_t aWeight = a.second.cmpUnitMotion->GetWeight(); + entity_pos_t bWeight = b.second.cmpUnitMotion->GetWeight(); + + // Final corrections: + // - divide by an arbitrary constant to avoid pushing too much. + // - multiply by the weight ratio (limiting the maximum positive push for numerical accuracy). + entity_pos_t timeFactor = dt / PUSHING_REDUCTION_FACTOR; + entity_pos_t maxPushing = timeFactor * MAX_PUSHING_MULTIPLIER; + a.second.push += pushingDir.Multiply(std::min(bWeight.MulDiv(timeFactor, aWeight), maxPushing)); + b.second.push -= pushingDir.Multiply(std::min(aWeight.MulDiv(timeFactor, bWeight), maxPushing)); // Use a constant factor to get a more general slowdown in crowded area. // The distance factor heavily dampens units that are overlapping.