mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-06-17 13:53:57 -07:00
Avoid cases of filenames Update years in terms and other legal(ish) documents Don't update years in license headers, since change is not meaningful Will add linter rule in seperate commit Happy recompiling everyone! Original Patch By: Nescio Comment By: Gallaecio Differential Revision: D2620 This was SVN commit r27786.
166 lines
5.2 KiB
C++
166 lines
5.2 KiB
C++
/* Copyright (C) 2022 Wildfire Games.
|
||
* This file is part of 0 A.D.
|
||
*
|
||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||
* it under the terms of the GNU General Public License as published by
|
||
* the Free Software Foundation, either version 2 of the License, or
|
||
* (at your option) any later version.
|
||
*
|
||
* 0 A.D. is distributed in the hope that it will be useful,
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
* GNU General Public License for more details.
|
||
*
|
||
* You should have received a copy of the GNU General Public License
|
||
* along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
|
||
*/
|
||
|
||
#ifndef INCLUDED_CCMPUNITMOTIONMANAGER
|
||
#define INCLUDED_CCMPUNITMOTIONMANAGER
|
||
|
||
#include "simulation2/system/Component.h"
|
||
#include "ICmpUnitMotionManager.h"
|
||
|
||
#include "simulation2/MessageTypes.h"
|
||
#include "simulation2/components/ICmpTerrain.h"
|
||
#include "simulation2/helpers/Grid.h"
|
||
#include "simulation2/system/EntityMap.h"
|
||
|
||
class CCmpUnitMotion;
|
||
|
||
class CCmpUnitMotionManager final : public ICmpUnitMotionManager
|
||
{
|
||
public:
|
||
static void ClassInit(CComponentManager& componentManager);
|
||
|
||
DEFAULT_COMPONENT_ALLOCATOR(UnitMotionManager)
|
||
|
||
/**
|
||
* Maximum value for pushing pressure.
|
||
*/
|
||
static constexpr int MAX_PRESSURE = 255;
|
||
|
||
// Persisted state for each unit.
|
||
struct MotionState
|
||
{
|
||
MotionState(ICmpPosition* cmpPos, CCmpUnitMotion* cmpMotion);
|
||
|
||
// Component references - these must be kept alive for the duration of motion.
|
||
// NB: this is generally a super dangerous thing to do,
|
||
// but the tight coupling with CCmpUnitMotion makes it workable.
|
||
// NB: this assumes that components do _not_ move in memory,
|
||
// which is currently a fair assumption but might change in the future.
|
||
ICmpPosition* cmpPosition;
|
||
CCmpUnitMotion* cmpUnitMotion;
|
||
|
||
// Position before units start moving
|
||
CFixedVector2D initialPos;
|
||
// Transient position during the movement.
|
||
CFixedVector2D pos;
|
||
|
||
// Accumulated "pushing" from nearby units.
|
||
CFixedVector2D push;
|
||
|
||
fixed speed;
|
||
|
||
fixed initialAngle;
|
||
fixed angle;
|
||
|
||
// Used for formations - units with the same control group won't push at a distance.
|
||
// (this is required because formations may be tight and large units may end up never settling.
|
||
entity_id_t controlGroup = INVALID_ENTITY;
|
||
|
||
// This is a ad-hoc counter to store under how much pushing 'pressure' an entity is.
|
||
// More pressure will slow the unit down and make it harder to push,
|
||
// which effectively bogs down groups of colliding units.
|
||
uint8_t pushingPressure = 0;
|
||
|
||
// Meta-flag -> this entity won't push nor be pushed.
|
||
// (used for entities that have their obstruction disabled).
|
||
bool ignore = false;
|
||
|
||
// If true, the entity needs to be handled during movement.
|
||
bool needUpdate = false;
|
||
|
||
bool wentStraight = false;
|
||
bool wasObstructed = false;
|
||
|
||
// Clone of the obstruction manager flag for efficiency
|
||
bool isMoving = false;
|
||
};
|
||
|
||
// "Template" state, not serialized (cannot be changed mid-game).
|
||
|
||
// The maximal distance at which units push each other is the combined unit clearances, multipled by this factor,
|
||
// itself pre-multiplied by the circle-square correction factor.
|
||
entity_pos_t m_PushingRadiusMultiplier;
|
||
// Additive modifiers to the maximum pushing distance for moving units and idle units respectively.
|
||
entity_pos_t m_MovingPushExtension;
|
||
entity_pos_t m_StaticPushExtension;
|
||
// Multiplier for the pushing 'spread'.
|
||
// This should be understand as the % of the maximum distance where pushing will be "in full force".
|
||
entity_pos_t m_MovingPushingSpread;
|
||
entity_pos_t m_StaticPushingSpread;
|
||
|
||
// Pushing forces below this value are ignored - this prevents units moving forever by very small increments.
|
||
entity_pos_t m_MinimalPushing;
|
||
|
||
// Multiplier for pushing pressure strength.
|
||
entity_pos_t m_PushingPressureStrength;
|
||
// Per-turn reduction in pushing pressure.
|
||
entity_pos_t m_PushingPressureDecay;
|
||
|
||
// These vectors are reconstructed on deserialization.
|
||
|
||
EntityMap<MotionState> m_Units;
|
||
EntityMap<MotionState> m_FormationControllers;
|
||
|
||
// Turn-local state below, not serialised.
|
||
|
||
Grid<std::vector<EntityMap<MotionState>::iterator>> m_MovingUnits;
|
||
bool m_ComputingMotion;
|
||
|
||
static std::string GetSchema()
|
||
{
|
||
return "<a:component type='system'/><empty/>";
|
||
}
|
||
|
||
void Init(const CParamNode& UNUSED(paramNode)) override;
|
||
|
||
void Deinit() override
|
||
{
|
||
}
|
||
|
||
void Serialize(ISerializer& serialize) override;
|
||
void Deserialize(const CParamNode& paramNode, IDeserializer& deserialize) override;
|
||
|
||
void HandleMessage(const CMessage& msg, bool global) override;
|
||
|
||
void Register(CCmpUnitMotion* component, entity_id_t ent, bool formationController) override;
|
||
void Unregister(entity_id_t ent) override;
|
||
|
||
bool ComputingMotion() const override
|
||
{
|
||
return m_ComputingMotion;
|
||
}
|
||
|
||
bool IsPushingActivated() const override
|
||
{
|
||
return m_PushingRadiusMultiplier != entity_pos_t::Zero();
|
||
}
|
||
|
||
private:
|
||
void OnDeserialized();
|
||
void ResetSubdivisions();
|
||
void OnTurnStart();
|
||
|
||
void MoveUnits(fixed dt);
|
||
void MoveFormations(fixed dt);
|
||
void Move(EntityMap<MotionState>& ents, fixed dt);
|
||
|
||
void Push(EntityMap<MotionState>::value_type& a, EntityMap<MotionState>::value_type& b, fixed dt);
|
||
};
|
||
|
||
REGISTER_COMPONENT_TYPE(UnitMotionManager)
|
||
|
||
#endif // INCLUDED_CCMPUNITMOTIONMANAGER
|