mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-06-16 21:34:08 -07:00
Bug introduced in 76acc4e146.
The previous CUnit code had logic to select random aesthetic variants
once initially. The new code removed that, as I completely missed its
purpose, assuming that the random selection, being based on a seed,
would pick the same variants every time. This is incorrect because
entity selections can change the RNG calls, thus the variants, and thus
entity appearance can change when the animation changes (typically, a
horse will change color when walking and running).
The solution is to re-introduce the choice of actor selections on CUnit
creation. This makes sure that units don't change their purely-aesthetic
selections when e.g. animations change.
Reported by: Wowgetoffyourcellphone
Tested By: Stan
Differential Revision: https://code.wildfiregames.com/D4205
This was SVN commit r25844.
116 lines
3.7 KiB
C++
116 lines
3.7 KiB
C++
/* Copyright (C) 2021 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_UNIT
|
|
#define INCLUDED_UNIT
|
|
|
|
#include <map>
|
|
#include <set>
|
|
|
|
#include "ps/CStr.h"
|
|
#include "simulation2/system/Entity.h" // entity_id_t
|
|
|
|
class CActorDef;
|
|
class CModelAbstract;
|
|
class CObjectEntry;
|
|
class CObjectManager;
|
|
class CSkeletonAnim;
|
|
class CUnitAnimation;
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
// CUnit: simple "actor" definition - defines a sole object within the world
|
|
class CUnit
|
|
{
|
|
NONCOPYABLE(CUnit);
|
|
private:
|
|
// Private constructor. Needs complete list of selections for the variation.
|
|
CUnit(CObjectManager& objectManager, const CActorDef& actor, uint32_t seed);
|
|
|
|
public:
|
|
// Attempt to create a unit with the given actor.
|
|
// If specific selections are wanted, call SetEntitySelection or SetActorSelections after creation.
|
|
// Returns NULL on failure.
|
|
static CUnit* Create(const CStrW& actorName, uint32_t seed, CObjectManager& objectManager);
|
|
|
|
// destructor
|
|
~CUnit();
|
|
|
|
// get unit's template object
|
|
const CObjectEntry& GetObject() const { return *m_Object; }
|
|
// get unit's model data
|
|
CModelAbstract& GetModel() const { return *m_Model; }
|
|
|
|
CUnitAnimation* GetAnimation() { return m_Animation; }
|
|
|
|
/**
|
|
* Update the model's animation.
|
|
* @param frameTime time in seconds
|
|
*/
|
|
void UpdateModel(float frameTime);
|
|
|
|
// Sets the entity-selection, and updates the unit to use the new
|
|
// actor variation. Either set one key at a time, or a complete map.
|
|
void SetEntitySelection(const CStr& key, const CStr& selection);
|
|
void SetEntitySelection(const std::map<CStr, CStr>& selections);
|
|
|
|
// Most units have a hopefully-unique ID number, so they can be referred to
|
|
// persistently despite saving/loading maps. Default for new units is -1; should
|
|
// usually be set to CUnitManager::GetNewID() after creation.
|
|
entity_id_t GetID() const { return m_ID; }
|
|
void SetID(entity_id_t id);
|
|
|
|
const std::set<CStr>& GetActorSelections() const { return m_ActorSelections; }
|
|
|
|
/**
|
|
* Overwrite the seed-selected actor selections. Likely only useful for Atlas or debugging.
|
|
*/
|
|
void SetActorSelections(const std::set<CStr>& selections);
|
|
|
|
private:
|
|
// Actor for the unit
|
|
const CActorDef& m_Actor;
|
|
// object from which unit was created; never NULL once fully created.
|
|
CObjectEntry* m_Object = nullptr;
|
|
// object model representation; never NULL once fully created.
|
|
CModelAbstract* m_Model = nullptr;
|
|
|
|
CUnitAnimation* m_Animation = nullptr;
|
|
|
|
// unique (per map) ID number for units created in the editor, as a
|
|
// permanent way of referencing them.
|
|
entity_id_t m_ID;
|
|
|
|
// seed used when creating unit
|
|
uint32_t m_Seed;
|
|
|
|
// Actor-level selections for this unit. This is normally set at init time,
|
|
// so that we always re-use the same aesthetic variants.
|
|
// These have lower priority than entity-level selections.
|
|
std::set<CStr> m_ActorSelections;
|
|
// Entity-level selections for this unit (used for e.g. animation variants).
|
|
std::map<CStr, CStr> m_EntitySelections;
|
|
|
|
// object manager which looks after this unit's objectentry
|
|
CObjectManager& m_ObjectManager;
|
|
|
|
void ReloadObject();
|
|
|
|
friend class CUnitAnimation;
|
|
};
|
|
|
|
#endif
|