From 6a9de50692afb720d772340554b7cb9d038395d2 Mon Sep 17 00:00:00 2001 From: Ykkrosh Date: Sat, 17 Apr 2010 11:34:40 +0000 Subject: [PATCH] # Use the correct projectile models. Fixes #470. Make CUnit::GetObject return a reference so it's clear it can never be NULL. This was SVN commit r7463. --- source/graphics/MapWriter.cpp | 2 +- source/graphics/ObjectEntry.cpp | 20 +++++++++-------- source/graphics/ObjectEntry.h | 3 ++- source/graphics/Unit.cpp | 2 +- source/graphics/Unit.h | 4 ++-- source/graphics/UnitAnimation.cpp | 4 ++++ source/graphics/UnitManager.cpp | 2 +- source/graphics/UnitManager.h | 3 ++- source/simulation/Projectile.cpp | 2 +- .../components/CCmpProjectileManager.cpp | 16 ++++++++++++-- .../components/CCmpVisualActor.cpp | 22 +++++++++++++++---- source/simulation2/components/ICmpVisual.h | 12 ++++++++++ .../GameInterface/Handlers/ObjectHandlers.cpp | 4 ++-- source/tools/atlas/GameInterface/SimState.cpp | 2 +- 14 files changed, 72 insertions(+), 26 deletions(-) diff --git a/source/graphics/MapWriter.cpp b/source/graphics/MapWriter.cpp index e604b7c6f6..796ecc5717 100644 --- a/source/graphics/MapWriter.cpp +++ b/source/graphics/MapWriter.cpp @@ -376,7 +376,7 @@ void CMapWriter::WriteXML(const VfsPath& filename, XML_Element("Nonentity"); - XML_Setting("Actor", (*unit)->GetObject()->m_Base->m_Name); + XML_Setting("Actor", (*unit)->GetObject().m_Base->m_Name); { CVector3D position = (*unit)->GetModel()->GetTransform().GetTranslation(); diff --git a/source/graphics/ObjectEntry.cpp b/source/graphics/ObjectEntry.cpp index c1a2e3fe2f..5076944b8c 100644 --- a/source/graphics/ObjectEntry.cpp +++ b/source/graphics/ObjectEntry.cpp @@ -41,7 +41,7 @@ CObjectEntry::CObjectEntry(CObjectBase* base) : m_Base(base), m_Color(1.0f, 1.0f, 1.0f, 1.0f), - m_ProjectileModel(NULL), m_AmmunitionModel(NULL), m_AmmunitionPoint(NULL), m_Model(NULL) + m_AmmunitionModel(NULL), m_AmmunitionPoint(NULL), m_Model(NULL) { } @@ -153,7 +153,14 @@ bool CObjectEntry::BuildVariation(const std::vector >& selections for (size_t p = 0; p < props.size(); p++) { const CObjectBase::Prop& prop = props[p]; - + + // Pluck out the special attachpoint 'projectile' + if (prop.m_PropPointName == "projectile") + { + m_ProjectileModelName = prop.m_ModelName.string(); + continue; + } + CObjectEntry* oe = objectManager.FindObjectVariation(prop.m_ModelName.string().c_str(), selections); if (!oe) { @@ -161,13 +168,8 @@ bool CObjectEntry::BuildVariation(const std::vector >& selections continue; } - // Pluck out the special attachpoint 'projectile' - if (prop.m_PropPointName == "projectile") - { - m_ProjectileModel = oe->m_Model; - } - // Also the other special attachpoint 'loaded-' - else if (prop.m_PropPointName.length() > 7 && prop.m_PropPointName.Left(7) == "loaded-") + // Also pluck out the other special attachpoint 'loaded-' + if (prop.m_PropPointName.length() > 7 && prop.m_PropPointName.Left(7) == "loaded-") { CStr ppn = prop.m_PropPointName.substr(7); m_AmmunitionModel = oe->m_Model; diff --git a/source/graphics/ObjectEntry.h b/source/graphics/ObjectEntry.h index 1f4fba6265..761918de22 100644 --- a/source/graphics/ObjectEntry.h +++ b/source/graphics/ObjectEntry.h @@ -55,7 +55,8 @@ public: // so we can have lots of colour variations without wasting memory on // lots of objectEntries) - CModel* m_ProjectileModel; + CStrW m_ProjectileModelName; + CModel* m_AmmunitionModel; SPropPoint* m_AmmunitionPoint; diff --git a/source/graphics/Unit.cpp b/source/graphics/Unit.cpp index 9228e6af3d..92f97e2b56 100644 --- a/source/graphics/Unit.cpp +++ b/source/graphics/Unit.cpp @@ -216,7 +216,7 @@ void CUnit::ReloadObject() // If these selections give a different object, change this unit to use it CObjectEntry* newObject = m_ObjectManager.FindObjectVariation(m_Object->m_Base, selections); - if (newObject != m_Object) + if (newObject && newObject != m_Object) { // Clone the new object's base (non-instance) model CModel* newModel = newObject->m_Model->Clone(); diff --git a/source/graphics/Unit.h b/source/graphics/Unit.h index 828121c60c..bcf5a87394 100644 --- a/source/graphics/Unit.h +++ b/source/graphics/Unit.h @@ -57,8 +57,8 @@ public: // destructor ~CUnit(); - // get unit's template object; never NULL - CObjectEntry* GetObject() const { return m_Object; } + // get unit's template object + const CObjectEntry& GetObject() const { return *m_Object; } // get unit's model data; never NULL CModel* GetModel() const { return m_Model; } // get actor's entity; can be NULL diff --git a/source/graphics/UnitAnimation.cpp b/source/graphics/UnitAnimation.cpp index 701768b803..0e0fedaace 100644 --- a/source/graphics/UnitAnimation.cpp +++ b/source/graphics/UnitAnimation.cpp @@ -66,6 +66,10 @@ void CUnitAnimation::SetAnimationState(const CStr& name, bool once, float speed, void CUnitAnimation::SetAnimationSync(float actionTime, float repeatTime) { CModel* model = m_Unit.GetModel(); + + if (!model || !model->m_Anim || !model->m_Anim->m_AnimDef) + return; + float duration = model->m_Anim->m_AnimDef->GetDuration(); // Set the speed so it loops once in repeatTime diff --git a/source/graphics/UnitManager.cpp b/source/graphics/UnitManager.cpp index d708919e77..917f62a81f 100644 --- a/source/graphics/UnitManager.cpp +++ b/source/graphics/UnitManager.cpp @@ -136,7 +136,7 @@ CUnit* CUnitManager::PickUnit(const CVector3D& origin, const CVector3D& dir, boo /////////////////////////////////////////////////////////////////////////////// // CreateUnit: create a new unit and add it to the world -CUnit* CUnitManager::CreateUnit(const CStr& actorName, CEntity* entity, const std::set& selections) +CUnit* CUnitManager::CreateUnit(const CStrW& actorName, CEntity* entity, const std::set& selections) { if (! m_ObjectManager) return NULL; diff --git a/source/graphics/UnitManager.h b/source/graphics/UnitManager.h index 235a517af9..98e65ba9f1 100644 --- a/source/graphics/UnitManager.h +++ b/source/graphics/UnitManager.h @@ -30,6 +30,7 @@ class CVector3D; class CEntity; class CObjectManager; class CStr8; +class CStrW; /////////////////////////////////////////////////////////////////////////////// // CUnitManager: simple container class holding all units within the world @@ -50,7 +51,7 @@ public: void DeleteAll(); // creates a new unit and adds it to the world - CUnit* CreateUnit(const CStr8& actorName, CEntity* entity, const std::set& selections); + CUnit* CreateUnit(const CStrW& actorName, CEntity* entity, const std::set& selections); // return the units const std::vector& GetUnits() const { return m_Units; } diff --git a/source/simulation/Projectile.cpp b/source/simulation/Projectile.cpp index 1d889cd946..6e95a04ced 100644 --- a/source/simulation/Projectile.cpp +++ b/source/simulation/Projectile.cpp @@ -158,7 +158,7 @@ JSBool CProjectile::Construct( JSContext* cx, JSObject* UNUSED(obj), uintN argc, Temp = ToNative( argv[0] ); if(Temp) { - Model = Temp->m_actor->GetObject()->m_ProjectileModel; +// Model = Temp->m_actor->GetObject()->m_ProjectileModel; if( !Model ) { err = "No projectile model is defined for that entity's actor."; diff --git a/source/simulation2/components/CCmpProjectileManager.cpp b/source/simulation2/components/CCmpProjectileManager.cpp index 3f54005a64..e8fc053404 100644 --- a/source/simulation2/components/CCmpProjectileManager.cpp +++ b/source/simulation2/components/CCmpProjectileManager.cpp @@ -21,6 +21,7 @@ #include "ICmpProjectileManager.h" #include "ICmpPosition.h" +#include "ICmpVisual.h" #include "simulation2/MessageTypes.h" #include "graphics/Frustum.h" @@ -30,6 +31,7 @@ #include "maths/Matrix3D.h" #include "maths/Quaternion.h" #include "maths/Vector3D.h" +#include "ps/CLogger.h" #include "renderer/Scene.h" class CCmpProjectileManager : public ICmpProjectileManager @@ -125,10 +127,20 @@ void CCmpProjectileManager::LaunchProjectile(entity_id_t source, CFixedVector3D if (!m_Context->HasUnitManager()) return; // do nothing if graphics are disabled - Projectile projectile; + CmpPtr sourceVisual(*m_Context, source); + if (sourceVisual.null()) + return; + + std::wstring name = sourceVisual->GetProjectileActor(); + if (name.empty()) + { + LOGERROR(L"Unit with actor '%ls' launched a projectile but has no actor on 'projectile' attachpoint", sourceVisual->GetActor().c_str()); + return; + } std::set selections; - std::string name = "props/units/weapons/arrow_front.xml"; // TODO: get from somewhere proper (entity or actor?) + + Projectile projectile; projectile.unit = m_Context->GetUnitManager().CreateUnit(name, NULL, selections); if (!projectile.unit) { diff --git a/source/simulation2/components/CCmpVisualActor.cpp b/source/simulation2/components/CCmpVisualActor.cpp index 6890005cd1..25224616da 100644 --- a/source/simulation2/components/CCmpVisualActor.cpp +++ b/source/simulation2/components/CCmpVisualActor.cpp @@ -79,11 +79,11 @@ public: // TODO: we should do some fancy animation of under-construction buildings rising from the ground, // but for now we'll just use the foundation actor and ignore the normal one - std::string name; + std::wstring name; if (paramNode.GetChild("Foundation").IsOk() && paramNode.GetChild("FoundationActor").IsOk()) - name = utf8_from_wstring(paramNode.GetChild("FoundationActor").ToString()); + name = paramNode.GetChild("FoundationActor").ToString(); else - name = utf8_from_wstring(paramNode.GetChild("Actor").ToString()); + name = paramNode.GetChild("Actor").ToString(); std::set selections; m_Unit = context.GetUnitManager().CreateUnit(name, NULL, selections); @@ -116,7 +116,7 @@ public: if (m_Unit == NULL) serialize.StringASCII("actor", "[none]", 0, 256); else - serialize.String("actor", m_Unit->GetObject()->m_Base->m_Name, 0, 256); + serialize.String("actor", m_Unit->GetObject().m_Base->m_Name, 0, 256); } // TODO: store random variation. This ought to be synchronised across saved games @@ -176,6 +176,20 @@ public: return m_Unit->GetModel()->GetTransform().GetTranslation(); } + virtual std::wstring GetActor() + { + if (!m_Unit) + return L""; + return m_Unit->GetObject().m_Base->m_Name; + } + + virtual std::wstring GetProjectileActor() + { + if (!m_Unit) + return L""; + return m_Unit->GetObject().m_ProjectileModelName; + } + virtual void SelectAnimation(std::string name, bool once, float speed, std::wstring soundgroup) { if (!m_Unit) diff --git a/source/simulation2/components/ICmpVisual.h b/source/simulation2/components/ICmpVisual.h index 62582ec268..d5628d87e6 100644 --- a/source/simulation2/components/ICmpVisual.h +++ b/source/simulation2/components/ICmpVisual.h @@ -41,6 +41,18 @@ public: */ virtual CVector3D GetPosition() = 0; + /** + * Return the filename of the actor that's being displayed, or the empty string on error. + * (Not safe for use in simulation code.) + */ + virtual std::wstring GetActor() = 0; + + /** + * Return the filename of the actor to be used for projectiles from this unit, or the empty string if none. + * (Not safe for use in simulation code.) + */ + virtual std::wstring GetProjectileActor() = 0; + /** * Start playing the given animation. If there are multiple possible animations then it will * pick one at random (not network-synchronised). diff --git a/source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp b/source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp index b8975922ac..47ae41b0e4 100644 --- a/source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp +++ b/source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp @@ -69,7 +69,7 @@ namespace if (unit->GetEntity()) return (unit->GetEntity()->m_base->m_anchorType != L"Ground"); else - return unit->GetObject()->m_Base->m_Properties.m_FloatOnWater; + return unit->GetObject().m_Base->m_Properties.m_FloatOnWater; } CUnitManager& GetUnitManager() @@ -219,7 +219,7 @@ QUERYHANDLER(GetObjectSettings) settings.player = unit->GetPlayerID(); // Get the unit's possible variants and selected variants - std::vector > groups = unit->GetObject()->m_Base->GetVariantGroups(); + std::vector > groups = unit->GetObject().m_Base->GetVariantGroups(); const std::set& selections = unit->GetActorSelections(); // Iterate over variant groups diff --git a/source/tools/atlas/GameInterface/SimState.cpp b/source/tools/atlas/GameInterface/SimState.cpp index 9e351b187b..345c991fdc 100644 --- a/source/tools/atlas/GameInterface/SimState.cpp +++ b/source/tools/atlas/GameInterface/SimState.cpp @@ -69,7 +69,7 @@ CEntity* SimState::Entity::Thaw() SimState::Nonentity SimState::Nonentity::Freeze(CUnit* unit) { Nonentity n; - n.actorName = unit->GetObject()->m_Base->m_Name; + n.actorName = unit->GetObject().m_Base->m_Name; n.unitID = unit->GetID(); n.selections = unit->GetActorSelections(); n.position = unit->GetModel()->GetTransform().GetTranslation();