LCOV - code coverage report
Current view: top level - source/simulation2/components - CCmpUnitMotionManager.h (source / functions) Hit Total Coverage
Test: 0 A.D. test coverage report Lines: 7 11 63.6 %
Date: 2023-01-19 00:18:29 Functions: 8 11 72.7 %

          Line data    Source code
       1             : /* Copyright (C) 2022 Wildfire Games.
       2             :  * This file is part of 0 A.D.
       3             :  *
       4             :  * 0 A.D. is free software: you can redistribute it and/or modify
       5             :  * it under the terms of the GNU General Public License as published by
       6             :  * the Free Software Foundation, either version 2 of the License, or
       7             :  * (at your option) any later version.
       8             :  *
       9             :  * 0 A.D. is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :  * GNU General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU General Public License
      15             :  * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : #ifndef INCLUDED_CCMPUNITMOTIONMANAGER
      19             : #define INCLUDED_CCMPUNITMOTIONMANAGER
      20             : 
      21             : #include "simulation2/system/Component.h"
      22             : #include "ICmpUnitMotionManager.h"
      23             : 
      24             : #include "simulation2/MessageTypes.h"
      25             : #include "simulation2/components/ICmpTerrain.h"
      26             : #include "simulation2/helpers/Grid.h"
      27             : #include "simulation2/system/EntityMap.h"
      28             : 
      29             : class CCmpUnitMotion;
      30             : 
      31           9 : class CCmpUnitMotionManager final : public ICmpUnitMotionManager
      32             : {
      33             : public:
      34             :     static void ClassInit(CComponentManager& componentManager);
      35             : 
      36           6 :     DEFAULT_COMPONENT_ALLOCATOR(UnitMotionManager)
      37             : 
      38             :     /**
      39             :      * Maximum value for pushing pressure.
      40             :      */
      41             :     static constexpr int MAX_PRESSURE = 255;
      42             : 
      43             :     // Persisted state for each unit.
      44             :     struct MotionState
      45             :     {
      46             :         MotionState(ICmpPosition* cmpPos, CCmpUnitMotion* cmpMotion);
      47             : 
      48             :         // Component references - these must be kept alive for the duration of motion.
      49             :         // NB: this is generally a super dangerous thing to do,
      50             :         // but the tight coupling with CCmpUnitMotion makes it workable.
      51             :         // NB: this assumes that components do _not_ move in memory,
      52             :         // which is currently a fair assumption but might change in the future.
      53             :         ICmpPosition* cmpPosition;
      54             :         CCmpUnitMotion* cmpUnitMotion;
      55             : 
      56             :         // Position before units start moving
      57             :         CFixedVector2D initialPos;
      58             :         // Transient position during the movement.
      59             :         CFixedVector2D pos;
      60             : 
      61             :         // Accumulated "pushing" from nearby units.
      62             :         CFixedVector2D push;
      63             : 
      64             :         fixed speed;
      65             : 
      66             :         fixed initialAngle;
      67             :         fixed angle;
      68             : 
      69             :         // Used for formations - units with the same control group won't push at a distance.
      70             :         // (this is required because formations may be tight and large units may end up never settling.
      71             :         entity_id_t controlGroup = INVALID_ENTITY;
      72             : 
      73             :         // This is a ad-hoc counter to store under how much pushing 'pressure' an entity is.
      74             :         // More pressure will slow the unit down and make it harder to push,
      75             :         // which effectively bogs down groups of colliding units.
      76             :         uint8_t pushingPressure = 0;
      77             : 
      78             :         // Meta-flag -> this entity won't push nor be pushed.
      79             :         // (used for entities that have their obstruction disabled).
      80             :         bool ignore = false;
      81             : 
      82             :         // If true, the entity needs to be handled during movement.
      83             :         bool needUpdate = false;
      84             : 
      85             :         bool wentStraight = false;
      86             :         bool wasObstructed = false;
      87             : 
      88             :         // Clone of the obstruction manager flag for efficiency
      89             :         bool isMoving = false;
      90             :     };
      91             : 
      92             :     // "Template" state, not serialized (cannot be changed mid-game).
      93             : 
      94             :     // The maximal distance at which units push each other is the combined unit clearances, multipled by this factor,
      95             :     // itself pre-multiplied by the circle-square correction factor.
      96             :     entity_pos_t m_PushingRadiusMultiplier;
      97             :     // Additive modifiers to the maximum pushing distance for moving units and idle units respectively.
      98             :     entity_pos_t m_MovingPushExtension;
      99             :     entity_pos_t m_StaticPushExtension;
     100             :     // Multiplier for the pushing 'spread'.
     101             :     // This should be understand as the % of the maximum distance where pushing will be "in full force".
     102             :     entity_pos_t m_MovingPushingSpread;
     103             :     entity_pos_t m_StaticPushingSpread;
     104             : 
     105             :     // Pushing forces below this value are ignored - this prevents units moving forever by very small increments.
     106             :     entity_pos_t m_MinimalPushing;
     107             : 
     108             :     // Multiplier for pushing pressure strength.
     109             :     entity_pos_t m_PushingPressureStrength;
     110             :     // Per-turn reduction in pushing pressure.
     111             :     entity_pos_t m_PushingPressureDecay;
     112             : 
     113             :     // These vectors are reconstructed on deserialization.
     114             : 
     115             :     EntityMap<MotionState> m_Units;
     116             :     EntityMap<MotionState> m_FormationControllers;
     117             : 
     118             :     // Turn-local state below, not serialised.
     119             : 
     120             :     Grid<std::vector<EntityMap<MotionState>::iterator>> m_MovingUnits;
     121             :     bool m_ComputingMotion;
     122             : 
     123         116 :     static std::string GetSchema()
     124             :     {
     125         116 :         return "<a:component type='system'/><empty/>";
     126             :     }
     127             : 
     128             :     void Init(const CParamNode& UNUSED(paramNode)) override;
     129             : 
     130           3 :     void Deinit() override
     131             :     {
     132           3 :     }
     133             : 
     134             :     void Serialize(ISerializer& serialize) override;
     135             :     void Deserialize(const CParamNode& paramNode, IDeserializer& deserialize) override;
     136             : 
     137             :     void HandleMessage(const CMessage& msg, bool global) override;
     138             : 
     139             :     void Register(CCmpUnitMotion* component, entity_id_t ent, bool formationController) override;
     140             :     void Unregister(entity_id_t ent) override;
     141             : 
     142           0 :     bool ComputingMotion() const override
     143             :     {
     144           0 :         return m_ComputingMotion;
     145             :     }
     146             : 
     147           0 :     bool IsPushingActivated() const override
     148             :     {
     149           0 :         return m_PushingRadiusMultiplier != entity_pos_t::Zero();
     150             :     }
     151             : 
     152             : private:
     153             :     void OnDeserialized();
     154             :     void ResetSubdivisions();
     155             :     void OnTurnStart();
     156             : 
     157             :     void MoveUnits(fixed dt);
     158             :     void MoveFormations(fixed dt);
     159             :     void Move(EntityMap<MotionState>& ents, fixed dt);
     160             : 
     161             :     void Push(EntityMap<MotionState>::value_type& a, EntityMap<MotionState>::value_type& b, fixed dt);
     162             : };
     163             : 
     164         116 : REGISTER_COMPONENT_TYPE(UnitMotionManager)
     165             : 
     166             : #endif // INCLUDED_CCMPUNITMOTIONMANAGER

Generated by: LCOV version 1.13